DEV Community

loading...

TDD com Elixir

Elixir UTFPR
Projeto de divulgação da linguagem de programação Elixir.Mantido por Adolfo Neto.
Updated on ・5 min read

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

Discussion (0)