Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso TDD em Flutter: desenvolvimento orientado a testes

TDD em Flutter: desenvolvimento orientado a testes

Testes de unidade e TDD - Apresentação

Olá, meu nome é Matheus, sou instrutor aqui da Alura.

Audiodescrição: Matheus se identifica como uma pessoa branca. Possui cabelos castanhos escuros e curtos. No corpo, usa uma camiseta azul com o logo "Alura". Ao fundo, um dos estúdios da Alura, com uma parede lisa iluminada em tons azuis, e no canto direito, uma estante com vários artefatos geek.

Neste curso, vamos trabalhar no aplicativo chamado AnyBank.

O AnyBank é um internet banking e vamos implementar duas funcionalidades: a funcionalidade de transferência e uma funcionalidade de cálculo de juros baseado no valor que temos disponível na conta.

Para implementar essas duas funcionalidades, vamos:

No final, teremos um aplicativo completamente testado e menos propenso a erros.

Pré-requisitos

Para acompanhar este curso, é muito importante que você já tenha conhecimentos prévios de Dart, conhecimentos básicos de Flutter e saiba também sobre testes: o que são testes, para quê eles servem e como escrever testes em Flutter.

Gostou? Então, te espero na primeira aula!

Testes de unidade e TDD - Testando a aplicação

É importante manter nossa aplicação testada.

Testes ajudam a manter a integridade do nosso código e também auxiliam na prevenção de possíveis erros de sistema ou de pessoas usuárias.

Vamos trabalhar em um projeto chamado AnyBank. Trata-se de um projeto de Internet Banking.

Alguns trechos e componentes desse código já foram desenvolvidos por outra parte da equipe. Nós vamos trabalhar nele para adicionar novas funcionalidades.

Implementaremos duas funcionalidades: funcionalidade de realizar transferências, ou seja, enviar dinheiro. E funcionalidade de calcular juros sobre um valor que temos em nossa conta.

Criando o modelo de conta bancária

Vamos criar nosso modelo de conta bancária. No Visual Studio Code, vamos criar uma nova pasta dentro da pasta "lib" chamada "models". Dentro de "models", vamos criar um novo arquivo chamado account.dart.

E account.dart, podemos criar nossa classe:

class Account {
  final int id;
  final String name;
  final String cpf;
  double balance;
}

Importante ressaltar que o balance foi o único que não teve final, porque esse valor precisa ser modificado ao longo das transferências realizadas ou até mesmo nos juros aplicados.

Para gerar o construtor dessa classe, vamos usar um plugin chamado Data Class Generator (Gerador de Classe de Dados)

É uma extensão do Visual Studio Code. Na atividade "Preparando Ambiente" deixei instruções de como baixar esse plug-in.

Com esse plugin instalado, vamos clicar na palavra Account, pressionar "Command + Ponto" ou "Ctrl + Pronto" se estiver no Windows, e abrirá o menu de refatoração.

Vamos selecionar a opção "Generate Constructor" (Gerar Construtor).

Ele vai gerar automaticamente todas as propriedades dentro do nosso construtor.

E abaixo do construtor, vamos começar a construir nossa funcionalidade.

Função transferência

A função de transferência será um void, não retornará nada para nós, ela será transfer, e agora vamos passar um amount para dentro dela.

class Account {
  final int id;
  final String name;
  final String cpf;
  double balance;

  Account({
    required this.id,
    required this.name,
    required this.cpf,
    required this.balance,
  });
    
  void transfer(amount) {
   balance = balance - amount;
      }

Agora, temos nossa função de transferência. Nosso próximo passo agora será criar nosso primeiro teste de unidade.

Teste de unidade

Para isso, na raíz do projeto vamos criar uma pasta chamada "test" e dentro de "test", vamos criar um novo arquivo chamado account_test.dart.

A primeira coisa que vamos fazer dentro desse arquivo é importar nossa biblioteca de testes:

import 'package:flutter_test/flutter_test.dart';

O próximo passo agora será criar nossa função void main, e nosso primeiro teste:

void main() {

 test("Testa uma transferência", () {
   final Account account = Account (id: 123, name: "Beto", cpf: "123.123.123-22", balance: 100);

  account.transfer(100);

   expect(account.balance, 0);
 });
}

A descrição será "testa uma transferência". E agora o corpo da nossa função, o que vamos testar é uma função anônima. Temos que criar agora uma instância de account e nossa conta inicial para o teste terá 100 reais. Depois temos que fazer uma transferência, então vamos chamar nosso account e a função de transfer, passando um valor total de 100.

Por último, vamos usar o expect para comparar algo, vamos comparar agora o valor do nosso account.balance, e qual é o valor que esperamos? Se transferirmos 100 reais, o valor que teremos no final deve ser zero.

Salvamos nosso código, e agora podemos testar.

Vamos clicar em "Run".

No terminal do VS Code vamos acessar a aba "Test Results". Está sendo exibido o "Testa uma transferência", e ele passou com sucesso.

Próximo passo

Qual seria nosso próximo passo? Poderíamos criar mais testes em cima dessa função, como por exemplo, criar uma situação onde temos números negativos.

Nossa função não está adequada para receber números negativos, então teríamos que modificar nossa função, adicionar a capacidade de lidar com números negativos e depois criar um novo teste.

Ou seja, para cada nova funcionalidade, para cada teste que vamos fazer, precisamos ir na nossa função de transferência, modificá-la e depois voltar a fazer o teste.

Será que não há uma maneira melhor de escrever nossa função de uma forma mais clara e objetiva, onde possamos ter vários testes já pré-montados?

Vamos descobrir isso no próximo vídeo!

Testes de unidade e TDD - Citando casos

Vamos refletir sobre nosso processo de desenvolvimento até agora.

Primeiro, escrevemos uma funcionalidade e, em seguida, elaboramos um teste para essa funcionalidade.

Os testes podem passar ou não de primeira. Se eles não passam, precisamos retornar à nossa funcionalidade, e adaptá-la para que ela consiga fazer o teste passar.

Isso indica que nosso código não está suficientemente robusto.

Vamos fazer de uma maneira um pouco diferente.

Vamos pegar nossa funcionalidade de transferência dentro do nosso arquivo account.dart e vamos apagar a função de transferência (transfer).

Salvamos nosso arquivo account.dart. Agora, vamos retornar ao arquivo account_test.test e reescrever os testes que estão dentro desse arquivo.

Vamos começar do zero.

Primeiro, vamos pensar em todas as possibilidades que temos de trabalhar em cima daquela função de transferência. Nós podemos:

Pensando nessas possibilidades - devem existir outras, mas as que conseguimos pensar agora foram essas seis - Pensando nessas seis possibilidades, vamos escrever testes vazios, apenas o nome desses testes, pensando em cada uma dessas situações.

Para começar a escrever esses testes, vamos fazer de uma maneira um pouco diferente.

Vamos começar criando um grupo, e a descrição será "testes de transferência". O corpo dele será uma função anônima, e dentro dessa função anônima vamos colocar nossos testes.

import 'package:anybank/models/account.dart'; import 'package:flutter_test/flutter_test.dart';

void main() {
  group("Testes de transferência", (){
    test("Testa uma transferência", (){});
    test("Transfere valores negativos", (){});
    test("Transfere qualquer coisa que não seja números", (){});
    test("Transfere valor maior que disponível no balanço", (){});
    test("Transfere 0", (){});
    test("Transfere um valor nulo", (){});
  });
}

São todos os casos que citamos anteriormente.

Criamos todas as condições que pensamos antes e criamos os testes. Se rodarmos esse grupo de testes, vamos ver o que acontece? Colocamos para rodar. Todos os testes passsaram porque no Dart, quando rodamos os testes vazios, eles não têm com o que serem testados, então todos vão passar.

Agora, vamos escrever a nossa função de transferência no account.dart.

E agora, esse amount pode acabar vindo nulo. Então, temos que, de alguma forma, saber lidar com o valor nulo caso aconteça. Então, vamos usar o null safety, que é uma coisa do próprio Dart, para podermos receber, garantir que recebemos o valor nulo. E se ele for diferente de nulo, prosseguimos com a transferência.

O próximo empecilho que temos é se o amount for menor ou igual ao saldo, conseguimos transferir dinheiro. Então, pode prosseguir. Além disso, também é importante que o valor não seja zero e nem abaixo de zero. Para não receber valores negativos. Então, podemos colocar que amount tem que ser maior do que zero.

Se todas as condições forem aprovadas, passarem, podemos realizar a transferência, que aí é a mesma coisa que fizemos logo no começo. balance é igual a balance menos amount. E assim uma transferência é realizada.

  void transfer(double? amount) {
    if (amount != null) {
      if (amount <= balance && amount > 0) {
        balance = balance - amount;
      }

A nossa função de transferência agora ficou muito mais robusta. Ela está lidando com todos os casos que tínhamos escrito nos testes. Isso garante que temos mais segurança no nosso código.

Agora falta garantir que esses testes realmente estão cobrindo todos os casos!

E o processo que fizemos até aqui é um processo do TDD.

TDD significa Test Driven Development (Desenvolvimento Orientado a Testes). E o princípio dele é exatamente escrever primeiro os testes e depois escrever uma funcionalidade em cima desse teste.

Claro, tem outras coisas que compõem o TDD. E vamos ver essas partes durante o processo do curso!

Próximo passo

Na próxima aula, vamos pegar essa função que fizemos e colocar dentro do corpo dos nossos testes!

Sobre o curso TDD em Flutter: desenvolvimento orientado a testes

O curso TDD em Flutter: desenvolvimento orientado a testes possui 82 minutos de vídeos, em um total de 41 atividades. Gostou? Conheça nossos outros cursos de Flutter em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Flutter acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas