Linguagem: Dart
Em todas as profissões se testa, e isso tem total relação com o grau de qualidade que um produto pode ter para poder ser oferecido. Inclusive, em algumas áreas os testes são obrigatórios e a qualidade controlada por órgãos (ex: Inmetro).
Vamos entender em seguida como funcionam os testes de software e como os testes podem nos ajudar a praticar a linguagem e aumentar a qualidade da entrega.
Tipos de teste de software
Existem muitas categorias de teste, cada um com suas vantagens, desvantagens e objetivos. Vou abordar neste post os tipos de testes recomendados na documentação do Dart:
Os testes unitários tem a responsabilidade de garantir a integridade dos nossos métodos. Um teste unitário deve ser rápido e barato de executar.
Os testes de componentes são responsáveis pela parte de 'interfaces' e interações que um componente pode receber. Normalmente garante a exibição de elementos e mudanças de estados.
Os testes de integração testam a aplicação de uma visão mais completa, navegando e simulando comportamentos dos componentes em conjunto. Verifica o comportamento da aplicação e também pode ser utilizado para medir desempenho.
(ref: https://flutter.dev/docs/testing)
Seguindo esta ordem, considere o seguinte: maior quantidade de testes unitários, seguido por testes de componentes e de integração.
Entrega
Quando você entrega seu trabalho testado para os outros profissionais revisarem (ex: 'code review'), isso economiza muito tempo das pessoas e o seu.
Com testes sua entrega sobe de nível e evita retorno de tarefas para correções (bugs).
Sem testes, além de ficar preocupado (despreocupado é pior), você terá a necessidade de alcançar mais rápido seus objetivos para não ser atropelado por falhas e anomalias em códigos sem testes.
TDD
Para escrever o primeiro teste e entender a vantagem de se testar, vamos utilizar uma técnica chamada TDD (ou desenvolvimento orientado a testes). O TDD, em resumo, é guiar seu desenvolvimento através de testes (vale pesquisar mais sobre o assunto).
Para chegarmos no resultado esperado, seguindo TDD, precisamos passar por três etapas principais:
- Escrever o teste e vê-lo falhar 🔴
- Desenvolver o método e ver o teste passar 🟢
- Melhorar o método com a garantia dos testes 🤓
Repeat!
Primeiro teste
Em uma aplicação Flutter a primeira coisa que eu penso em testar é a 'main'. Será que tem o que testar lá?
Tem sim! Podemos executar funções antes do 'bootstrap' do nosso aplicativo e isso pode ser testado.
Considere o seguinte: precisamos que uma função seja executada antes do runApp
do Flutter. Poderíamos ter colocado direto na 'main', mas alguém poderia alterar ou remover essa função e ela deixaria de ter o comportamento esperado.
A vantagem de um teste desse é justamente dele falhar se alguém alterar o código ou remover por engano. Outra vantagem é a descrição dos testes, que ajudam novos colaboradores a entender os casos de uso do código na aplicação.
Para entender as etapas deste primeiro teste é legal dar uma lida na documentação do Dart e no pacote mockito:
O que será testado:
A ideia é testar a execução do runner
da aplicação com a condição de executar uma função antes com as configurações de inicialização do projeto.
O teste:
Antes de começar a escrever o teste em si, precisamos criar as classes de Mock
para que apenas o método run
seja executado no teste.
Dentro do teste executamos o método run
(é o método que estamos testando) e o verifyInOrder
para verificar a execução na ordem correta.
Ficou assim:
// imports...
// bootstrap file import
class FunctionsMock extends Mock {
void runApp(dynamic widget) {}
void before() {}
}
class ComponentMock extends Mock {}
void main() {
test('App bootstrap method', () async {
final fMock = FunctionsMock();
final appMock = ComponentMock();
await Bootstrap(appMock, fMock.before).run(fMock.runApp);
verifyInOrder([fMock.before(), fMock.runApp(appMock)]);
});
}
tests/bootstrap_test.dart
Chegou a hora de executar o teste e ver falhar:
$ flutter test
00:04 +0 -1: loading test/bootstrap_test.dart [E]
Failed to load "test/bootstrap_test.dart":
Unable to spawn isolate: test/bootstrap_test.dart:17:11: Error: Method not found: 'Bootstrap'.
await Bootstrap(appMock, fMock.before).run(fMock.runApp);
^^^^^^^^^^^^
00:04 +0 -1: Some tests failed.
Escrevendo o método
Vamos criar uma classe Bootstrap
que recebe um Widget
e uma função before
no construtor.
O método run
recebe um runApp
(do Flutter) e executa a função before
antes do runner
com a nossa app (Widget
).
// imports...
class Bootstrap {
final Widget app;
final Function before;
Bootstrap(this.app, this.before);
Future<void> run(Function(Widget) runner) async {
await before();
await runner(app);
}
}
lib/bootstrap.dart
Utilizando a classe:
// imports...
void main() {
Bootstrap(MyApp(), () { ... }).run(runApp);
}
// MyApp Widget Implementation
lib/main.dart
Seguindo esta ordem, escrevendo o teste primeiro, podemos definir o que esperamos do método. Executando o teste esperamos sempre que ele falhe e está falha vai guiar o desenvolvimento do método. Faça o teste passar!
$ flutter test
00:02 +1: All tests passed!
Note que não testamos o método before
, isso deverá ser feito em outra descrição de teste.
Agora sua implementação começa a ficar mais segura e em caso de mudanças seu teste vai quebrar para a felicidade de todos.
A ideia de aprender com os testes é que nos arquivos de testes vamos precisar lidar com a classe/método fora da sua aplicação e isso nos leva a melhorar essas classes/métodos, além de utilizar outras partes da linguagem.
É apenas o começo
No caso do Flutter você pode seguir para os testes de componentes (widgets). Para todos os casos, vale a leitura de toda documentação do Dart sobre testes.
Espero voltar com os próximos passos, mas não espere por mim, gogogo!
Top comments (0)