Guia minimalista para testes em Flutter
https://methodpoet.com/test-driven-development-best-practices/Gostaria que você cumprimentasse a nova série de artigos sobre Testing in Flutter! Vou tentar cobrir todas as coisas em profundidade nesta série. Meu principal objetivo é aprender Testing corretamente e, ao aprendê-lo, criar o melhor guia para todos nós como um recurso! Espero que você ache útil e goste!
Sou novo neste tópico, portanto, se houver informações ausentes ou incorretas, informe-me e ajude-me a corrigi-lo! Desde já, obrigado!
Conteudo
Então vamos começar!
Se queremos levar a qualidade a sério, é hora de nos cansarmos de encontrar bugs e começarmos a prevenir que eles aconteçam em primeiro lugar — Robert Brunhage (grande cara)
O que é Testar?
Quando codificamos um aplicativo, o que vamos fazer primeiro?
Nós testamos! E olha só, está funcionando bem ou não! Se encontrarmos um bug, nós o corrigimos e continuamos a codificar, certo?
Esse é o teste, mas essa não é a única opção!
Existem dois tipos de testes por aí!
Teste manual (caixa preta):
O teste manual não requer nenhum conhecimento de programação ou algo assim. O testador apenas tenta quebrar o aplicativo manualmente sem saber qual algoritmo é executado dentro dele! É por isso que chamamos de teste de caixa preta! Não é tão confiável porque podemos encontrar comportamentos inesperados de outras partes ao adicionar novos recursos, e o testador pode não ser bom o suficiente (afinal, somos todos humanos) etc.
Teste automatizado (caixa branca):
Por outro lado, o teste automatizado precisa de uma linguagem de programação porque dizemos ao compilador como testar o aplicativo em todos os cenários e deixá-lo testar e garantir que o aplicativo funcione corretamente! É por isso que é mais confiável do que o teste manual! Além disso, é muito confiável porque é cumulativo, o que significa que o compilador também verifica todos os recursos existentes enquanto adiciona novos recursos. Todo o aplicativo será testado do início ao fim a cada alteração! E isso garante que o desenvolvimento atual não interrompa nenhum recurso existente.
Então, vamos dar uma olhada nos prós e contras do teste automatizado!
Prós
- Mostra a qualidade do desenvolvedor!
(algumas pessoas escrevem testes, mesmo que ninguém afirme isso. E isso os torna especiais e dignos de respeito!) - Melhora a qualidade do código e nos ajuda a escrever um código melhor
(Força-nos a escrever um código melhor, como Responsabilidade Única, Arquitetura em Camadas, Injeção de Dependência, Abstração, etc.) - Ajuda a pensar de forma clara e básica, não complexa!
(Por favor, ouse escrever código complexo e veja o que acontece ao escrever um teste de unidade) - Economiza muito tempo e dinheiro
(Nos ajuda a identificar bugs no estágio inicial) - Ajuda-nos a manter a nossa sanidade e evita frustrações
(Evita feedback desagradável de seu chefe e clientes!) - Evita bugs estranhos e inesperados
(Quando adicionamos um novo recurso ou corrigimos um bug ou refatoramos o código antigo, podemos quebrar as outras funcionalidades ou até mesmo o aplicativo inteiro!) - Evita que fiquemos para trás!
(Evita que fiquemos repetindo “antes estava funcionando!”) - A manutenção a longo prazo é mais fácil.
(Apenas olhando para o teste, podemos entender facilmente do que se trata.) - Refatore com confiança
(Você não precisa se preocupar em quebrar algumas coisas ao refatorar seu código. Mesmo se você quebrar, saberá qual e onde está o problema instantaneamente) - Torne a depuração ainda mais simples!
(podemos saber exatamente os casos que estão falhando e causando o bug.)
Contras
- Pode parecer um pouco demorado
(Mas, não totalmente, porque mesmo que pareça retardar o tempo de desenvolvimento, pelo contrário, acelera totalmente porque reduz muitos bugs que ocorrerão no futuro)
E aqui estão alguns dos casos que testamos em uma unidade.
- Verifique se os valores iniciais são verdadeiros
- Verifique se o valor foi atualizado conforme o esperado
- Verifique se o resultado do teste é o esperado
- Verifique se a unidade lida com os erros conforme o esperado
- Verifique se o teste de unidade funciona, mesmo se chamar mais de uma vez
Também
- Verifique os casos nulos
- Verifique se os tipos de dados são verdadeiros
(Graças ao sistema Dart’s null e type safety, não precisamos deles! Contanto que não usemos variáveis dinâmicas e anuláveis.)
Testando no Flutter
(Unit Test) Teste de Unidade — Teste a Lógica
- Para testar uma única classe ou um único método/função para verificar uma unidade de lógica em condições definidas
(execute o método e espere que funcione conforme o esperado)
(Widget Test) Teste de widget — Teste a interface do usuário
- Para testar um único widget de interface do usuário e seu comportamento
(clique no botão e espere que funcione conforme o esperado)
Golden Test — Teste a adaptabilidade e capacidade de resposta da interface do usuário
- Os testes de ouro são basicamente testes de widgets, mas para verificar se a imagem “dourada” gerada e o widget são os mesmos.
(Integration Test) Teste de Integração — Teste a Experiência
- Para testar grandes partes do aplicativo da perspectiva do usuário
(como, preencher os campos de texto e clicar no botão de login e esperar a página inicial de roteamento, etc.)
(End-to-End (E2E) Test) Teste de ponta a ponta — Teste todo o sistema (front-end + back-end)
- Para testar toda a experiência.
https://docs.flutter.dev/testing
Vamos ver um pouco de código!
Vou apenas mostrar os recursos que você pode fazer por enquanto!
Mas abordarei isso em profundidade nos próximos artigos, portanto, fique atento!
// You can define global rules using annotations! // we have lots of platform options indeed! // vm, chrome, firefox, safari, node, dart-vm, browser, js, mac-os, linux, android, ios... @Tags(['browser', 'android']) @TestOn('ios') @Skip('currently failing (see issue 1234)') @Timeout(Duration(seconds: 45)) @OnPlatform({'windows': Timeout.factor(2)}) void main() { late HttpServer server; // inits just before the tests getting started setUp(() async { server = await HttpServer.bind('localhost', 0); }); // Disposes when all the tests over tearDown(() async { await server.close(force: true); server = null; }); // Creates a test test('description', () { // write your test here }); // you can group your tests in a scope like that! group( 'description', () { test('test1', () {}); test('test2', () {}); test('test3', () {}); }, skip: 'reason', ); // Also you can define tests specific rules too! test( 'description', () {}, // you can also define specific rules to specific tests! tags: 'chrome', // or ['chrome', 'firefox'], skip: 'reason', // skips the test timeout: const Timeout.factor(2), // slows down time by 2x retry: 3, // runs the test 3 times to make sure it's ok testOn: 'browser && !chrome', // Every browser but Chrome // platform specific rules! onPlatform: { 'windows': const Timeout.factor(2), 'browser': [const Skip('add browser support')], }, ); // and yeah we can expect anything as a result! // thanks to matchers package, we have lots of methods to match the results! expect(text.trim(), equals('foo')); // sync expect('foo,bar,baz', allOf([contains('foo'), isNot(startsWith('bar')), endsWith('baz')])); // sync expect(await Future.value(10), equals(10)); // async expectLater(actual, matcher); // async expect(Future.value(10), completion(equals(10))); // async expect(Future.error('oh no'), throwsA(equals('oh no'))); // on error expect(Future.error(StateError('bad state')), throwsStateError); // on error expect(() => int.parse('X'), throwsFormatException); // on error expect(stream, emitsInOrder(['ready.', emitsAnyOf(['succeeded', 'failed']), emitsDone])); // stream }
Para mais informações clique aqui.
Algumas informações aleatórias sobre o teste!
- Os testes devem ser rápidos, simples, independentes, determinísticos, repetíveis, focados em apenas uma coisa e fáceis de entender!
(Arrange-Act-Assert) - Repetição de código em testes é aceitável.
(Um teste deve se concentrar mais na simplicidade do que nas boas práticas de codificação.) - Usar classes abstratas facilita nossa vida!
- Os testes devem ser escritos durante a codificação! Não quando o aplicativo terminar completamente! (NA MINHA HUMILDE OPINIÃO)
- O teste de serviço é questionável!
(Na maioria das vezes, você não precisa escrever testes para os serviços que usa, mas se você não confia no cara do back-end, acho que você também deve escrever testes de serviço em seu aplicativo!) - Mocking é apenas uma simulação de dependências. Nada mais nada menos!
- Os arquivos devem ser nomeados com o sufixo “_test.dart” em Dart Lang
- TDD: Primeiro escreva seu teste, depois escreva seu código! (Falha-Refator-Sucesso)
11 Test Driven Development Best Practices – Tests That Think!
- BDD: Escreva seus testes em uma linguagem legível por humanos (Given-When-Then)
BDD Example Feature: Counter Scenario: Increase and decrease the value of the counter Given Counter's initial value is 0 And increase and decrease buttons are available When User click on the increase button. Then the counter's value should be 1.
- Cobertura significa quão extensivamente testado é o seu código.
https://tech.andpad.co.jp/entry/2020/11/17/170000
Por último
Ninguém manda você escrever seus testes, mas os testes mostram a qualidade das pessoas! — Um cara sábio