Entre para a LISTA VIP da Black Friday

00

DIAS

00

HORAS

00

MIN

00

SEG

Clique para saber mais
Alura > Cursos de Mobile > Cursos de iOS > Conteúdos de iOS > Primeiras aulas do curso iOS: testes de unidade e TDD

iOS: testes de unidade e TDD

Começando com testes - Apresentação

Olá, boas-vindas à Alura. Esse é o curso de Testes de Unidade TDD para iOS. Eu sou o Andriu, instrutor do curso, e tenho certeza que você, assim como eu, em algum momento já subiu algum PR com algum bug que pode até ocasionar algum crash no aplicativo em produção, e é uma coisa bem inconveniente.

A discussão é, por que isso ocorre com tanta frequência? E uma das coisas que nos vêm à mente é que programador, muitas vezes, não gosta de testar seu código.

Nós, muitas vezes, testamos o caminho feliz, achamos que está funcionando, mas o método pode ter várias possibilidades de input de dados, enfim, e isso muitas vezes é margem para bugs.

Um dos possíveis caminhos é testarmos isso manualmente, mas ao longo do tempo você vai ver que isso é muito custoso, muito caro, porque, imagine, a cada alteração, a cada refatoração você ter que testar todo o fluxo do seu projeto, todas as possibilidades do seu aplicativo manualmente. Então, é muito trabalhoso.

Nós começamos a entender que a solução para testarmos o nosso código não é só utilizar humanos para testar o nosso software, mas ensinar o nosso computador a rodar os testes de forma automatizada.

Então, é aí que entramos com o assunto de testes automatizados. Testes automatizados nada mais são do que métodos que testam a nossa classe. Podemos ter diversos métodos de testes para testar várias regras de negócio da nossa classe e a cada alteração que fizermos no nosso sistema, basta rodarmos de forma automatizada todos esses testes novamente e verificamos se o nosso código continua funcionando.

Vamos utilizar, durante o curso, o framework XCTest nativo do iOS para criarmos os nossos testes. Vamos falar no início sobre testes de unidade e depois vamos começar a falar um pouco também sobre TDD.

Vamos falar sobre fluxo de trabalho do TDD, onde primeiro começamos escrevendo um teste com falha, que é a etapa “Red”, e é um teste com falha porque a classe de produção ainda não tem essa lógica para fazer o teste passar.

Depois, vamos escrever um teste minimamente para o nosso teste realmente passar, ou seja, da forma mais simples possível. E depois, a última etapa do TDD é a parte de “Refactor”, onde nós voltamos o nosso código de reprodução e fazemos uma refatoração, já que já temos um teste para garantir que o nosso código vai funcionar.

Essa etapa do TDD que também vamos ver e, por último, vamos falar sobre a qualidade dos nossos testes. Da mesma forma que é importante mantermos a qualidade do nosso código nas classes de produção, também é importante mantermos os nossos testes bem escritos, bem legíveis para entendermos de fato o que a classe faz.

Esse é o conteúdo que vamos estudar durante esse curso e eu espero você.

Começando com testes - Por que utilizar testes automatizados?

Provavelmente, em algum momento da sua carreira, você já deve ter passado por alguma dessas situações: você subir alguma coisa para a loja e o aplicativo passar a dar crash, ou então você desenvolver uma nova funcionalidade e parar de funcionar alguma coisa que já estava funcionando.

Ou então você se comprometer a refatorar a parte de código que ninguém gosta de pôr a mão, você melhorar a qualidade do código, porém, passa a ocorrer bugs nessa refatoração.

Isso é comum, todo mundo, em algum momento, já passou por isso, mas a discussão é: por que às vezes isso acontece com tanta frequência? E uma das possíveis respostas é porque nós não testamos corretamente o nosso código, nós não verificamos se tudo que fizemos está funcionando.

Então, a empresa poderia, por exemplo, contratar um time de pessoas para testar todas as nossas entregas, mas vamos analisar isso com mais calma.

Eu tenho aqui um aplicativo de leilão em que nós podemos escolher um produto, um “Playstation 4”, um “Nintendo Switch”, um “MacBook Pro” e um “Apple Watch”, e podemos dar lances em cima desses produtos.

O aplicativo vai avaliar qual foi o maior lance, qual foi o menor lance, e assim conseguimos ver quem ganhou esse leilão. Tenho aqui algumas regras de negócio e vou pedir a sua ajuda para testar isso junto comigo.

Tenho a primeira regra que diz o seguinte “RN01 – O aplicativo não deve avaliar leilões sem nenhum lance dado”. Vamos testar isso juntos? Vou escolher algum produto, como, por exemplo, o “MacBook Pro”, e a regra diz que o aplicativo não deve avaliar leilões sem nenhum lance.

Então, tenho aqui uma lista vazia, não tenho nenhum lance, e vou clicar em “Avaliar proposta”. Clico aqui e ele me dá um alert falando que não é possível avaliar um leilão sem lances. Então, aparentemente, essa regra está ok.

Vamos vir aqui e vamos colocar um “Ok”. Vamos para a próxima regra: “RN02 – O aplicativo não deve aceitar mais do que 5 lances do mesmo usuário”. Vamos testar isso.

Vou incluir um novo lance, “Maria 100”, a Maria deu um lance de R$ 100,00; vou colocar o “Fernando” que deu um lance de “R$ 130,00”; aí a Maria vem e dá mais um lance de “R$ 200,00”.

A “Beatriz” vem e dá um lance de “R$ 280,00”; depois, temos a “Maria” novamente, ela vai dar um lance de “R$ 340,00”; depois vem o “Bruno” e dá um lance de “R$ 500,00”; depois vem a “Maria” novamente e dá um lance de “R$ 600,00”.

Temos aqui a “Maria” quatro vezes. A regra diz o seguinte: o aplicativo não deve aceitar mais do que cinco lances do mesmo usuário, então ela pode dar mais um lance.

Agora vem o “Felipe” que vai dar um lance de “R$ 1.000,00”, e vem a “Maria” novamente e dá um lance de R$ 2.500,00”. Agora temos cinco lances da Maria. A regra não deve aceitar mais do que cinco lances, então vou vir mais uma vez com “Felipe”, vou colocar um lance de “R$ 3.000,00”.

E vamos ver se conseguimos cadastrar mais um lance da Maria. “Maria”, “R$ 4.000,00”. Repara que o lance não foi incluído com o valor de R$ “4.000,00”, ou seja, a Maria deu cinco lances. Então, essa regra também, aparentemente, está ok.

Aqui diz o seguinte, “RN03 – O aplicativo não deve aceitar dois lances seguidos do mesmo usuário”. O último lance que eu dei foi do Felipe, vamos ver se eu consigo dar mais um lance do Felipe.

Vou adicionar mais um lance do “Felipe” com o valor de “R$ 3.600,00”. Cliquei em “Adicionar” e repara que não adicionamos o lance do Felipe, ou seja, essa regra que diz “o aplicativo não deve aceitar dois lances seguidos do mesmo usuário” também está ok.

Então, aqui nós testamos três regras de negócio do nosso aplicativo de leilão e todas elas, aparentemente, estão funcionando. Isso é só um exemplo de como essa equipe que iria testar o nosso código iria trabalhar. Eles analisam as regras e testam manualmente no aplicativo.

Suponha que nós precisamos fazer alguma alteração no nosso código. Agora, eu quero mudar o design, quero mudar alguma regra. O que garante que, com essa alteração que vamos fazer, vão continuar funcionando as regras que já estavam?

Essas três regras estão ok, porém, meu time vai lá e faz uma alteração no código. Depois dessa alteração, como faço para verificar se tudo isso ainda está funcionando? Eu tenho que, novamente, pegar as regras, testar uma por uma e verificar se ainda estão funcionando.

Então, repara como é custoso todas as alterações que fizermos nós passarmos para uma pessoa, para um humano testar, porque é comum no dia a dia de uma empresa de desenvolvimento de software, nós subirmos várias correções, várias entregas, novas funcionalidades, refatorações.

São muitas coisas que subimos em um dia e não temos uma garantia de que vai continuar funcionando da forma que estava. Então, é isso que vamos tratar nesse curso através de testes automatizados.

A ideia não é pessoas testarem o nosso código, e, sim, implementarmos testes automatizados para o próprio computador testar todas as regras do nosso aplicativo.

Assim, cada alteração que fizermos, nós vamos lá, rodamos os testes e o computador vai verificar se essas regras estão sendo válidas, mesmo após as alterações.

Repare que o computador não vai achar chato testar, não vai demorar, porque testes de unidade é questão de segundos para ele rodar, e temos uma garantir de que o nosso código vai continuar funcionando.

Começando com testes - Começando com testes

Agora que já compreendemos a problemática sobre esses testes manuais, vamos iniciar os nossos estudos com testes automatizados utilizando o aplicativo de leilões como base do nosso aprendizado.

Tenho aqui um template desse projeto que já vem com algumas classes, como a classe lance, usuario e leilão, mas, antes de começarmos a implementar uma nova funcionalidade nesse aplicativo de leilão, eu queria mostrar para você como nós configuramos o nosso projeto para trabalharmos com testes de unidade.

Se eu vir aqui em “File > New Project”, que é a mesma coisa de eu clicar no XCode, se eu não tiver nenhum projeto aberto. Ele me traz algumas opções de criação do nosso projeto com o XCode, geralmente escolhemos essa opção “App”.

O importante é ticar essa caixa do “Include Tests”. Se você quer trabalhar com testes automatizados, tanto testes de unidade quanto testes de interface do usuário que você vai gravando as telas, vai montando o fluxo, é bom você marcar essa opção “Include Tests”.

Como o nosso projeto já tem essa opção selecionada, ele já traz por default, por padrão esses dois targets, essas duas etapas do nosso projeto que são “LeilaoTests” e esse “LeilaoUITests”. Então, quando você marca aquela opção, ele já vem com essas duas estruturas para trabalharmos.

Esse projeto, com essas classes, vai estar disponível nessa seção do curso para você fazer download, então você pode baixar e continuar seguindo junto comigo.

A ideia é implementarmos uma nova funcionalidade nesse projeto de leilão. E o que vamos fazer? Nós já temos essas classes, lance, usuario e leilao, só que ainda não temos uma classe que avalia qual foi o maior lance dado de um determinado usuário.

Então, vamos criar essa classe avaliador para fazer essa verificação. O que vou fazer? Vou criar uma nova classe, então botão direito em cima da pasta “Model”, vou vir aqui em “Novo Arquivo” e vou escolher essa opção “Swift File” que já vem selecionada.

Vou dar um “Next” e vou criar a classe “Avaliador”. Vou dar um “Create” e ele traz um arquivo vazio onde vamos criar uma nova classe. O que essa classe vai ter? Essa classe vai ter um método chamado avalia que recebe um leilão.

Vou criar o método avalia, onde vou receber um leilao: Leilao, e vou então trabalhar com esse método. O que vou fazer aqui? Vou primeiro precisar dos lances desse leilão. Então, se eu vir aqui em leilão.lances, ele é uma lista de lances opcionais.

Tenho aqui vários lances. E o que vou começar fazendo? Para não trabalhar com essa variável opcional, eu vou criar um guard let, vou chamar de lances = leilão.lances. Se ele não conseguir extrair esse valor, eu retorno a minha função sem fazer nada.

Como isso é uma lista de lances, vou precisar percorrer toda a lista para saber qual é o maior e qual é o menor lance. Então, vamos fazer isso. Para cada lance na lista de lances, o que vou fazer? Vou verificar se é o maior ou o menor.

Vou fazer um if para verificar se o lance, que ele está percorrendo no momento, .valor é maior que > maiorDeTodos, que é uma variável que ainda não tenho.

Se o valor for maior, vou pegar a minha variável maiorDeTodos e vou falar que ela é igual ao lance.valor. Ele está reclamando porque ainda não temos essa variável maiorDeTodos, então vou cria-la aqui antes da função avalia.

Vou criar aqui um private var que vou chamar de maiorDetodos, é um Double, e vou pegar um método da própria classe, então dentro da API do Double, ele tem um método que inicializa com o menor valor que é permitido dentro desse tipo, que é o Double.

Por que o menor valor? Porque, assim, a primeira vez que ele passar, qualquer valor vai ser maior do que o menor valor que é permitido dentro da API do Double. Esse método é esse aqui, least.NonzeroMagnitude, então ele pega o menor número positivo que é permitido dentro dessa API do Double.

Tenho aqui uma variável maiorDeTodos, ele vai verificar se o valor do lance que ele está percorrendo no momento é maior que o maiorDeTodos; se for, ele pega o valor e seta dentro dessa variável.

Vou fazer outra verificação para verificar o menor. Então, lance.valor < menorDeTodos, assim eu consigo saber qual foi o maior lance e qual foi o menor lance.

Se entrar nessa condição, eu pego o menorDeTodos, que é uma variável que ainda não temos, e falo que ela é igual ao lance.valor.

Então, precisamos criar essa variável menorDeTodos e vamos usar a mesma lógica. private var menorDeTodos = Double, e aqui nós vamos usar um método que é esse greatestFiniteMagnitude, que na verdade é o maior número que ele pode representar nesse tipo, que é o Double.

Por que o maior? Porque assim, qualquer valor que entrar a primeira vez vai ser menor que o maior valor. Então, tenho aqui duas variáveis e aqui temos a nossa validação.

Vou criar aqui dois métodos para expormos esse valor que está aqui private, então vou criar um método chamado maiorLance que vai devolver um Double. Aqui eu dou um return maiorDeTodos.

E a mesma coisa com o método para expormos essa variável menorDeTodos. func menorLance, ele vai retornar um Double, e eu dou um return menorDeTodos.

Então, temos aqui um método que vai avaliar esses lances, agora podemos testar para vermos se isso está funcionando. Outra forma de expor essa variável private maiorDeTodos e private menorDeTodos é colocarmos essa palavra reservada set.

Conseguimos ter acesso a essa variável somente para leitura fora da classe, não conseguimos setar nenhum valor. Mas temos aqui, então, o nosso método maiorLance e menorLance.

Como eu disse no começo do vídeo, estamos trabalhando com esse projeto do leilão, mas estamos nos preocupando apenas com a parte das regras nesse momento. Nós não temos nenhuma parte visual do nosso projeto.

Se eu entrar, por exemplo, no “Storyboard”, eu tenho uma tela vazia. Então, não vamos nos preocupar nesse momento com a parte visual, e sim em testar as nossas regras.

Por isso que estou vindo no “ViewController”, porque é uma forma que nós já conhecemos que é inicializada quando rodamos o aplicativo, então ele cai nesse método ViewDidLoad. Vamos fazer alguns testes para verificar se o método avalia está funcionando.

Vou começar criando alguns usuários, temos a classe Usuario, vou utilizar essa classe para criar alguns cenários. Vou criar o joao é um Usuario, onde vou passar o nome – o ID nesse momento não precisa –, (nome: Joao).

Vou criar também jose = usuario(nome: Jose), e vou criar aqui a maria = usuario(nome: Maria). Tenho aqui três usuários. Agora vou criar um novo leilão, ou seja, vou criar um leilão de algum produto para esses usuários participarem.

Vou criar aqui um leilão, vou utilizar essa classe que já vem nesse template que eu vou disponibilizar para vocês, vamos utilizá-la para criar um novo Leilao.

Vou passar aqui a descrição do leilão que vai ser, por exemplo, descricao: “Macbook pro 16 – M1”, e agora o que vamos fazer? Vamos propor alguns lances.

Então, leilão.propoe, vou propor alguns lances, que é essa classe Lance que estamos utilizando, onde precisamos passar um usuario e um valor.

O usuario vai ser o joao e vou passar um lance de 300 reais. Vou utilizar essa linha para ganharmos tempo e vou criar mais um leilão, só que dessa vez não vai ser o joao, vai ser o jose.

jose, vou dar um lance de 400 reais, e agora vai ser a maria que vai dar um lance de 250 reais. Então, temos aqui alguns usuários, criamos um leilão, temos alguns lances, e isso já nos permite utilizar o método avalia da nossa classe “Avaliador”.

Temos tudo que precisamos: temos usuários e temos o leilão. Então, vamos lá, o que vamos fazer? Vou criar aqui a instância da nossa classe, vou criar uma constante chamada leiloeiro que vai ser a classe Avaliador, e aqui posso invocar o nosso método avalia.

Vou passar aqui um leilao, o leilao nós já temos, vou passá-lo aqui embaixo, e agora vou criar algumas condições para verificarmos se isso está funcionando.

Na verdade, vou imprimir o valor do maior lance e do menor lance. Então, print(leiloeiro.maiorLance) e aqui print(leiloeiro.menorLance). Vou escolher qualquer simulador, vou rodar o projeto, vamos testar e ver se isso está funcionando.

Subimos aqui o simulador, ele imprimiu o valor de 400.0 como o maiorLance e o valor de 250.0 como o menorLance. Vamos ver se isso é verdade? O maior lance realmente foi o de 400.0 e o menor lance foi o de 250.0.

Será que essa implementação funciona em outros cenários? Vamos ver a seguir.

Sobre o curso iOS: testes de unidade e TDD

O curso iOS: testes de unidade e TDD possui 116 minutos de vídeos, em um total de 41 atividades. Gostou? Conheça nossos outros cursos de iOS 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 iOS acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas