Parte 2 — Testando aplicativo usando flutter_bloc

Rodrigo Bastos
5 min readFeb 2, 2020

Fala galera, hoje vamos continuar a nossa série que fala sobre o flutter_bloc. E o assunto será testes. Vamos testar o aplicativo de tiles que fizemos no primeiro artigo da série.

Vamos testar o projeto criado no primeiro artigo dessa série. Preparados? Vamos lá!

Para criarmos nossos testes vamos ter que adicionar algumas dependências ao nosso arquivo `pubspec.yaml`.

Adicionamos como dev_dependencies pois estas dependências serão utilizadas apenas para testar a aplicação e não queremos que elas sejam
adicionadas quando for gerada uma versão final do nosso app. As dependências adicionadas foram: `test` que é uma das dependências principais
para fazermos nossos testes, `bloc_test` que é um helper do ecossistema flutter_bloc para facilitar testes de blocs e `mockito` que é o pacote
já muito conhecido que nos facilita mockar classes, facilitando assim nosso teste.

Para testar nosso app vamos fazer 3 tipos de testes:
- Testes de Bloc
- Testes de Widget
- Testes de Integraçao usando flutter_driver

Começando com os testes de bloc temos que basicamente testar se os estados são produzidos corretamente de acordo com os eventos que são emitidos.
Para conseguir isso o pacote bloc_test vai nos ajudar para caramba.

Criemos então dentro do diretório test um subdiretório bloc, para colocarmos o arquivo `grid_bloc_test.dart` que iremos criar. Para que o flutter
consiga calcular a cobertura de código corretamente é crucial que o nome do arquivo de teste seja idêntico ao original adicionado de `_test` no final.

Como vamos testar os estados, é muito bom fazermos uso de outro package interessante. O nome dele é `equatable`, e ele facilita a comparação
entre objetos de classes. Em dart, por default as comparações de objetos são por referência e o que o equatable faz é tornar essa comparação por
valores das propriedades que você escolher dos objetos. Para tal adicione a dependência no `pubspec.yaml` e vamos em frente.

Vamos fazer nossa classe abstrata de estados extender Equatable, para que todos os estados que estendem essa classe possam implementar as props
do equatable.

E o nosso arquivo de estados ficará assim:

Para a comparação ser feita corretamente só temos que passas as propriedades que queremos comparar (nesse caso a lista de Tile) para o props do equatable. Agora temos tudo configurado para criar nossos testes de bloc.

O código acima mostra o formato de um teste de bloc. Ele tem um callback chamado build onde você precisa retornar uma instância do bloc que vai
ser testado, é aqui no build que podemos configurar os nossos mocks. Existe outro callback chamado act que recebemos uma instância do bloc a ser testado e podemos adicionar eventos ao bloc e por fim temos um array chamado expect, onde devemos colocar a lista de estados que foram produzidos pelo bloc em resposta aos eventos emitidos.

Nosso bloc recebe uma instância de um GridHelper, então temos que criar um mock dele para mockar os valores retornados por ele.

E como passamos a instância de mock para nosso bloc podemos configurar o valor retornado pelo método do helper usando assim:

Então nosso arquivo de teste de blocs ficará assim:

Temos todos os eventos mapeados para nossos estados com sucesso :). Agora podemos partir para testar nossos widgets.

O primeiro widget que testaremos é o `InitialStateWidget`. Um teste de widget no Flutter funciona da seguinte forma, você recebe um WidgetTester injetado como parâmetro do seu teste e executa o método `pumpWidget` do tester para “inflar” o widget que você deseja testar. Após feito isso você pode começar a fazer suas asserções. É sempre indicado inflar um MaterialApp que tenha o widget a ser testado como body dele, pois quando algum widget seu usa algo como MediaQuery ou Theme é sempre obrigado ter um material app na árvore de widgets.

O teste deste widget é muito simples e a única coisa que testamos é se o widget mostra o texto “Add a beautifull Tile”. Utilizamos um Finder para buscar algum widget que tenha o texto desejado e no nosso expect utilizamos um Matcher, no caso utilizamos o Matcher `findsOneWidget`, que compara se o Finder achou um e somente um widget. Nosso teste então fica assim:

Outro teste muito parecido é o teste do widget `NoTileLeftWidget`. Ele também testa apenas a presença de algum texto.

Vamos agora passar para um teste mais interessante. O teste do principal widget do app. No teste da GridPage, temos que testar comportamentos como: adiciona um tile quando pressiona o botão, adiciona dois tiles quando pressiona o botão duas vezes e remove um tile quando pressionado o tile.

Vamos testar então que adiciona um tile quando pressiona o botão. Como já sabemos inflamos o widget com o `pumpWidget`, perceba que como nosso widget faz uso de um Bloc precisamos utilizar o BlocProvider no nosso teste também. Após inflado o widget nós procuramos pelo fab e verificamos que ele é encontrado e utilizamos o método `tap` do tester que simula um toque no componente, depois precisamos chamar o método `pumpAndSettle` que aguarda qualquer tipo de animação ser finalizada e por fim fazemos a asserção `expect(find.byType(TileWidget), findsOneWidget)` que espera que um widget Tile esteja na tela. O código completo deste teste se encontra abaixo:

O próximo teste é checar se ao ser clicado duas vezes, aparecem dois tiles na tela. O código é muito similar ao teste passado, as diferenças são que executamos duas vezes o método tap e temos que esperar dois tiles no final.

O teste mais complicado deste widget é testar os comportamentos de adição e remoção de tiles em conjunto. A primeira parte do teste é idêntica ao anterior, onde criamos dois tiles na tela. Depois disso damos tap separadamente em cada Tile e no final esperamos que ambos sejam removidos e não exista nenhum Tile mais na tela.

Por fim, vamos agora partir para os testes de integração utilizando flutter_driver. Primeiro declare a dependência do flutter_driver no `pubspec.yaml` em dev_dependencies.

Crie um diretorio test_driver e dentro dele crie dois arquivos: um chamado `app.dart` e outro `app_test.dart`. O `app.dart` deve ser assim:

E o `app_test.dart` deve conter o código do driver a ser testado. Em um teste de driver nós conectamos ao driver no setup do teste e fechamos no tearDown.

No único teste nosso nós faremos uma simulação adicionando alguns tiles e os removendo. Adicionamos alguns timers para ficar mais visível a animação. O teste de driver é bem parecido com um teste de widget. Encontramos os widgets que queremos com nossos finders e interagimos com eles.

O código final do nosso arquivo é este:

Agora precisamos executar o nosso teste, para isso podemos criar um script para rodar nosso teste. O script que fiz para rodar o teste é o seguinte:

Ao executar o script com o simulador conectado podemos observar o test_driver sendo executado. O gif abaixo mostra isso:

Por hoje é isso pessoal, no próximo artigo da série falarei sobre o hydrated_bloc para guardamos o estado de um bloc.

--

--