Dobra, wracamy do testowania! :) oj jak dobrze. Dziś trochę o konfiguracji – czyli co możemy zrobić z tymi testami i do jakich potrzeb możemy je nagiąć jeżeli trzeba :)

Konfiguracja

ExUnit przypomina mi trochę nUnit dając możliwość określenia dwóch metod setup jak i metody tear down – on_exit. Z dwóch dostępnych metod setup jedna jest wykonywana raz na wszystkie testy w danym module, druga co każde wykonanie testu. Dzięki czemu możemy skonfigurować testy lub przekazać zunifikowane wartości do wszystkich testów.

Metody setup

Obydwie metody setup mają takie same przeciążenia:

  • Mogą nie przyjmować żadnego parametru
  • Przyjmują parametr context
  • Mogą w prosty sposób delegować wykonanie do innej metody

Trzy przypadki:

setup do
end

setup context do
end

setup: my_setup

defp my_setup do
end

Także parametry zwracane są takie same w obu przypadkach:

{:ok, [ lista_keywords ]}

Gdzie lista keywords jest opcjonalna, ale wszystko to co zostanie w niej zwrócone zostanie dodane do context. Czyli:

{:ok, [my_num: [1,2,3]]}

Doda do context klucz :my_num który zwróci nam listę [1,2,3].

Jednak, lista keywords jest opcjonalna i równie dobrze, możemy zwrócić z metod :ok. Pozostawienie metod setup bez zwracania niczego, lub zwrócenie czegoś innego niż :ok czy lista keywords spowoduje automatyczny fail wszystkich testów. Więc jak już korzystacie z uprzejmości metod setup, to pamiętajcie o tym małym fakcie.

Jak możemy skorzystać z danych kontekstowych?

Do każdej metody test, przekazywany jest context jeżeli tego chcemy. Każdy test możemy napisać tak:

test "NAME" do
  assert true
end

Jak i:

test "NAME", context do
  assert true
end

Do context zaś dopieramy się tak jak do listy słów kluczowych:

context[:one]
context[:two]

on_exit

on_exit umożliwia nam czyszczenie czegokolwiek co chcemy wyczyścić w po każdym teście lub po wszystkich testach. Jest on definiowany jako callback w metodzie setup lub setup_all i jest on zawsze wykonany niezależnie od tego czy metody setup się wywalają.

setup do
  on_exit fn ->
    IO.puts "setup_on_exit"
  end
end

setup_all do
  on_exit fn ->
    IO.puts "setup_on_exit"
  end
end

Grupowanie testów i filtrowanie

describe

Testy, możemy pogrupować sobie w logiczną całość za pomocą bloku describe który wygląda mniej więcej tak:

describe "moje super testy" do
  test "moj super test 1" do
  end

  test "moj super test 2" do
  end
end

Oprócz wizualnego podziału umożliwia nam posiadanie odrębnych metod setup. Dodatkowo może być wykorzystane w trakcie uruchamiania testów do ich filtrowania. Na przykład możemy odpalić tylko testy z danego describe:

mix test --only describe:"NAME"

Tagowanie metod

Inna forma targetowania testów lub ich grupowania to tagowanie. Każdy test może zawierać tag – tak to takie key, value. Zarówno umożliwia nam filtrowanie, jak i dodaje dane wartości do context:

@tag key: 1
test "setup" do
end

Teraz nasz kontekst będzie zawierał klucz :key o wartości 1 i będziemy mogli to wykorzystać w testach albo w setup. Ale też możemy to filtrować:

mix test --include key:1

Tagowanie modułów

Możemy też grupować cały moduł pod @moduletag. Działa to dosłownie tak samo jak w przypadku tagów dla testów, tylko, że zamiast być określane co metodę, jest raz, per cały defmodule.

Tagowanie modułów ma mniejszy priorytet niż tagowanie metod. Czyli jeżeli ten sam klucz zostanie użyty to wartość jego z poziomu metody będzie miała pierwszeństwo.

Parametry wywołania

Oprócz już wspomnianych opcji --include i --only mamy jeszcze opcję --exclude, kóra umożliwa nam wyłączenie pewnych testów z wykonania.

Dokładnie mówiąc, jeżeli robimy opcję --only to wykonujemy polecenie:

mix test --include ONLY --exclude test

Gdzie ONLY to tag/fitlr który chcemy by był wykonany.

Odpal tylko te testy które się zmieniły

Osobny punkt, bo jest to dość ważna opcja. Kiedy piszemy duże aplikacje testów możemy mieć setki albo tysiące. Jeżeli za każdym razem byśmy odpalali wszystkie testy to prędzej czy później moglibyśmy pewnie iść na kawę.

Dlatego też mix wprowadził opcję --stale, która generuje za pierwszym razem manifest dzięki któremu później mix patrzy czy ma wykonać test czy też nie. Jedyny minus tego, wystarczy dodać spację do pliku i już ponownie testy zostaną wykonane.

Ale opcja jest, i to się liczy :)

Podsumowanie

Czy to wszystko? Nie! mix test umożliwia nam podłączenie code coverage, ma kilka ciekawych opcji przy przechwytywaniu logów i testowaniu czy logi zostały zapisane tak jak chcieliśmy. Ogólnie API jest pokaźne i można się z nim zapoznać tutaj.