DEV Community

Elixir UTFPR (por Adolfo Neto)
Elixir UTFPR (por Adolfo Neto)

Posted on • Edited on

TDD com Elixir

Alt Text
Uma das coisas mais legais em Elixir é a facilidade para criar e executar testes automatizados (testes que são escritos como código).

Com isso, você pode fazer TDD (Test-Driven Development ou Desenvolmento Guiado por Testes) com facilidade. Não sabe o que é TDD? Leia o livro do Maurício Aniche!

O que vou mostrar aqui é o passo-a-passo para fazer TDD em Elixir.

Passo 1: Criar o projeto

Uma vez tendo o Elixir instalado, você vai num terminal (no meu caso, um Ubuntu 20.04 dentro do WSL do Windows 10), e digita mix new <nome do projeto>. No caso abaixo, o nome do projeto é calculadora.

elixir@utfpr:~/DevTo$ mix new calculadora * creating README.md * creating .formatter.exs * creating .gitignore * creating mix.exs * creating lib * creating lib/calculadora.ex * creating test * creating test/test_helper.exs * creating test/calculadora_test.exs Your Mix project was created successfully. You can use "mix" to compile it, test it, and more: cd calculadora mix test Run "mix help" for more commands. 
Enter fullscreen mode Exit fullscreen mode

Pronto. O mix criou a pasta calculadora e dentro desta as pastas lib e test. Ou seja, o mix já separou para você o código que tem funcionalidades (pasta lib) do código de testes (pasta test). Além disso ele criou 5 arquivos. Os arquivos relevantes para nosso exemplo simples são apenas lib/calculadora.ex e test/calculadora_test.exs.

Passo 2 - Rodar os Testes

Veja na imagem acima que o mix sugere que você, logo após a criação do projeto, vá para a pasta do novo projeto, calculadora, e execute os testes. Sim, o mix já cria testes para você.

Vamos primeiro então rodar os testes que o mix criou:

elixir@utfpr:~/DevTo$ cd calculadora elixir@utfpr:~/DevTo/calculadora$ mix test Compiling 1 file (.ex) Generated calculadora app .. Finished in 0.08 seconds 1 doctest, 1 test, 0 failures Randomized with seed 652059 elixir@utfpr:~/DevTo/calculadora$ 
Enter fullscreen mode Exit fullscreen mode

Olha que legal! Passou em todos os testes! OK, só tem dois testes: um doctest e um teste normal.

Passo 3: Remover o doctest

Vamos dar uma espiada nos arquivos gerados? Importante: estou usando o Elixir 1.11.2. Diferentes versões podem ter conteúdos diferentes nos arquivos gerados.

Arquivo lib/calculadora.ex:

defmodule Calculadora do @moduledoc """ Documentation for `Calculadora`. """ @doc """ Hello world. ## Examples iex> Calculadora.hello() :world """ def hello do :world end end 
Enter fullscreen mode Exit fullscreen mode

Como aqui estamos tratando do básico, eu vou apagar o doctest, ou seja, tudo que está entre @doc """ e """.

Arquivo lib/calculadora.ex passa a ser:

defmodule Calculadora do @moduledoc """ Documentation for `Calculadora`. """ def hello do :world end end 
Enter fullscreen mode Exit fullscreen mode

Rodemos os testes de novo:

elixir@utfpr:~/DevTo/calculadora$ mix test Compiling 1 file (.ex) . Finished in 0.03 seconds 1 test, 0 failures Randomized with seed 900374 elixir@utfpr:~/DevTo/calculadora$ 
Enter fullscreen mode Exit fullscreen mode

Pronto. Agora só temos um teste.

Passo 4: Escrever o seu primeiro teste

Vamos dar uma olhada no teste? Está em test/calculadora_test.exs.

Isto é importante! O arquivo deve estar na pasta test/ e seu nome deve terminar em _test.exs. Se não for assim, o arquivo contendo os testes não vai ser encontrado pela biblioteca que roda os testes.

Arquivo test/calculadora_test.exs:

defmodule CalculadoraTest do use ExUnit.Case doctest Calculadora test "greets the world" do assert Calculadora.hello() == :world end end 
Enter fullscreen mode Exit fullscreen mode

Como vemos acima, o teste gerado pelo mix tem descrição "greets the world" (tradução: "cumprimenta o mundo").

O único comando deste teste é um assert. Ele afirma (a tradução do Google Translate para assert) que se eu chamar a função hello() do módulo Calculadora, o resultado vai ser igual (==) ao átomo :world.

O teste que escreveremos simplesmente afirma que 2 + 2 = 4:

 test "2+2 é 4" do assert Calculadora.soma(2,2) == 4 end 
Enter fullscreen mode Exit fullscreen mode

Com este teste, o arquivo test/calculadora_test.exs passa a ser:

defmodule CalculadoraTest do use ExUnit.Case doctest Calculadora test "greets the world" do assert Calculadora.hello() == :world end test "2+2 é 4" do assert Calculadora.soma(2,2) == 4 end end 
Enter fullscreen mode Exit fullscreen mode

Uma das práticas de TDD é rodar os testes mesmo quendo você espera que eles falhem, como será o caso abaixo pois sequer criamos a função Calculadora.soma/2.

Rodemos os testes de novo:

elixir@utfpr:~/DevTo/calculadora$ mix test warning: Calculadora.soma/2 is undefined or private test/calculadora_test.exs:10: CalculadoraTest."test 2+2 é 4"/1 . 1) test 2+2 é 4 (CalculadoraTest) test/calculadora_test.exs:9 ** (UndefinedFunctionError) function Calculadora.soma/2 is undefined or private code: assert Calculadora.soma(2,2) == 4 stacktrace: (calculadora 0.1.0) Calculadora.soma(2, 2) test/calculadora_test.exs:10: (test) Finished in 0.3 seconds 2 tests, 1 failure elixir@utfpr:~/DevTo/calculadora$ 
Enter fullscreen mode Exit fullscreen mode

Os testes falharam? Ótimo. Era o esperado.

Passo 5: Fazer o teste passar usando Passos de Bebê.

A técnica Passos de Bebê (Baby Steps) sugere que você escreva o mínimo necessário para passar no teste. Neste caso, o mínimo necessário é escrever a função Calculadora.soma/2 ignorando seus parâmetros e retornando 4:

 def soma(_,_), do: 4 
Enter fullscreen mode Exit fullscreen mode

Arquivo lib/calculadora.ex passa a ser:

defmodule Calculadora do @moduledoc """ Documentation for `Calculadora`. """ def hello do :world end def soma(_,_), do: 4 end 
Enter fullscreen mode Exit fullscreen mode

Rodemos os testes de novo:

elixir@utfpr:~/DevTo/calculadora$ mix test Compiling 1 file (.ex) .. Finished in 0.03 seconds 2 tests, 0 failures Randomized with seed 371832 elixir@utfpr:~/DevTo/calculadora$  
Enter fullscreen mode Exit fullscreen mode

Passo 6: Escrever o seu segundo teste

O segundo teste que escreveremos afirma que 3 + 3 = 6:

 test "3+3 é 6" do assert Calculadora.soma(3,3) == 6 end 
Enter fullscreen mode Exit fullscreen mode

Com este teste, o arquivo test/calculadora_test.exs passa a ser:

defmodule CalculadoraTest do use ExUnit.Case doctest Calculadora test "greets the world" do assert Calculadora.hello() == :world end test "2+2 é 4" do assert Calculadora.soma(2,2) == 4 end test "3+3 é 6" do assert Calculadora.soma(3,3) == 6 end end 
Enter fullscreen mode Exit fullscreen mode

Rodemos os testes de novo:

elixir@utfpr:~/DevTo/calculadora$ mix test .. 1) test 3+3 é 6 (CalculadoraTest) test/calculadora_test.exs:13 Assertion with == failed code: assert Calculadora.soma(3, 3) == 6 left: 4 right: 6 stacktrace: test/calculadora_test.exs:14: (test) Finished in 0.06 seconds 3 tests, 1 failure Randomized with seed 966924 elixir@utfpr:~/DevTo/calculadora$ 
Enter fullscreen mode Exit fullscreen mode

Vejam que agora a mensagem de erro é diferente. O teste esperava 6 mas a função retornou 4.

Como fazer o teste passar?
Agora basta implementar de fato a função Calculadora.soma/2:

 def soma(num1, num2), do: num1 + num2 
Enter fullscreen mode Exit fullscreen mode

Arquivo lib/calculadora.ex passa a ser:

defmodule Calculadora do @moduledoc """ Documentation for `Calculadora`. """ def hello do :world end def soma(num1, num2), do: num1 + num2 end 
Enter fullscreen mode Exit fullscreen mode

Rodemos os testes de novo:

elixir@utfpr:~/DevTo/calculadora$ mix test Compiling 1 file (.ex) ... Finished in 0.03 seconds 3 tests, 0 failures Randomized with seed 498106 elixir@utfpr:~/DevTo/calculadora$ 
Enter fullscreen mode Exit fullscreen mode

Passou em todos os testes!

OK, acho que por hoje é só. Daqui vocês já podem continuar.

Vejam que não deu tempo de falar de refatoração nem das diversas formas de afirmar/refutar usando ExUnit, o arcabouço (framework) de testes de unidade do Elixir.

E então, o que vocês querem saber mais sobre Elixir?

PS: um vídeo relacionado

Top comments (0)