Mamy już napisane kodowanie i rozszyfrowywanie danych za pomocą Bencode. Warto więc przysiąść i upewnić się, że to co mamy to jest to co chcemy mieć – czyli, przetestować kod. Dziś więc zajmiemy się testowaniem kodu w elixir – a dokładniej dlaczego dokumentacja w elixir nie należy do czegoś czego trzeba unikać, a nawet można za pomocą niej ułatwić sobie znacznie życie.

W elixir możemy wyróżnić dwa rodzaje testów, testy pisane przez nas – tak jak to robimy normalnie w każdym innym projekcie. Jak i testy wykonywane automatycznie przez mix za pomocą przykładów. Tak nie przewidziało się wam. W elixir możemy testować nasz kod, za pomocą pisania przykładów wykorzystania danej metody. Fajne? BARDZO.

Testowanie za pomocą przykładów

W elixirze, dokumentacja jest typem pierwszoklasowym. To oznacza, że jest nie ona zbędnym nudnym komentarzem, który po X interakcjach nadaje się tylko do tego by zostać usunięty. Nie, dokumentacja jest żyjącym albo dokładnie mówiąc weryfikującym bytem, który może zagwarantować nam to, że nasz kod działa tak jak zakładamy to w przykładach. I robi to ona całkowicie automatycznie z wykorzystaniem narzędzia mix.

Jak pewnie pamiętacie w kodzie do kodowania i deszyfrowania załączyłem dwa takie o to komentarze:

@doc """
Decode bencoded into Elixir data structures
## Examples

    iex> Bencode.decode("i1e")
    {:ok, 1}

    iex> Bencode.decode("4:test")
    {:ok, "test"

    iex> Bencode.decode("li1e4:teste")
    {:ok, [1, "test"]}

    iex> Bencode.decode("d4:testi1ee")
    {:ok, %{"test" => 1}}
"""
#...

@doc """
Encode Elixir data structure into bencode
## Examples

    iex> Bencode.encode(1)
    {:ok, "i1e"}

    iex> Bencode.encode("test")
    {:ok, "4:test"}

    iex> Bencode.encode([1, "test"])
    {:ok, "li1e4:teste"}

    iex> Bencode.encode(%{"test" => 1})
    {:ok, "d4:testi1ee"}
"""
#...

Całość możecie jak zawsze pobrać z github.

Jak łatwo się domyślić te przykłady które tutaj są napisane mogę służyć i służą jako testy naszych metod. Jest to najprostszy sposób powiedzenia takie polecenie zwraca taką wartość. To jest cały nasz test – tak jak zresztą przeważnie testujemy metody – wykonanie i porównanie z wynikiem. W tym wypadku wykonujemy kod który rozpoczyna się od iex> i który musi dać wynik taki sam jak linijka pod iex>.

To co jest ważne to, że iex> musi być oddalone o 4 spacje. Jeżeli zaś chcemy wykonać coś wielo-linikowego to wystarczy, że nasza nowa linijka rozpocznie się od ...>.

Jako, że Bencode został stworzony z wykorzystaniem mix new, jedyną rzeczą jaką potrzebujemy do wykonania tych testów to polecenie:

$ mix test
==> bencode

Compiling 1 file (.ex)

==> bencode
........

Finished in 0.09 seconds
8 tests, 0 failures

Randomized with seed 288000

Jak widać, 8 testów zostało odpalonych i wszystkie działają. Jeżeli chcemy się więcej dowiedzieć na temat testów (jakie zostały odpalone, to możemy wykonać polecenie:

$ mix test --trace
==> bencode

BencodeTest
  * test doc at Bencode.encode/1 (6) (0.00ms)
  * test doc at Bencode.decode/1 (3) (0.00ms)
  * test doc at Bencode.encode/1 (8) (0.00ms)
  * test doc at Bencode.decode/1 (4) (0.00ms)
  * test doc at Bencode.encode/1 (7) (0.00ms)
  * test doc at Bencode.decode/1 (2) (0.00ms)
  * test doc at Bencode.encode/1 (5) (0.00ms)
  * test doc at Bencode.decode/1 (1) (0.00ms)

Finished in 0.09 seconds
8 tests, 0 failures

Randomized with seed 255000

Jednak w tym wypadku nazwa metody testu nam nic za bardzo nie powie.

Jeżeli mamy test który nie zgadza się z wartością oczekiwaną (albo wartość oczekiwana jest błędna) to dostaniemy wynik:

$ mix test
==> bencode
...

  1) test doc at Bencode.encode/1 (5) (BencodeTest)
     test/bencode_test.exs:3
     Doctest failed
     code: Bencode.encode(1) === {:ok, "i2e"}
     lhs:  {:ok, "i1e"}
     stacktrace:
       lib/bencode.ex:95: Bencode (module)

....

Finished in 0.1 seconds
8 tests, 1 failure

Randomized with seed 227000

Dzięki możliwości odpalenia testów z przykładów mamy zagwarantowane to, że nasza dokumentacja przynajmniej będzie poprawna do poziomy przykładów – zakładając, że naprawiamy błędy/testy :)

Gdybyśmy nie tworzyli zaś naszego projektu za pomocą mix new, to by odpalić testy musimy wykonać jedną małą rzecz. Musimy stworzyć plik testów i poinformować, że ma on wykorzystywać testy z wykorzystaniem dokumentacji. W tym celu tworzymy moduł, który wykorzystuje za pomocą use ExUnit.Case i wywołuje makro doctest Bencode:

defmodule BencodeTest do
  use ExUnit.Case
  doctest Bencode

end

I to tyle co jest potrzebne by wykonać unit testing naszego kodu za pomocą przykładów i mix test.

Podsumowanie

Dzisiaj opisałem najprostszą wersję testowania kodu, za tydzień skoncentrujemy się na pisaniu własnych testów oraz na tym co dokładnie daje nam ExUnit.Case i co robi doctest oprócz tego, że umożliwia nam testowanie naszego kodu za pomocą przykładów.

1 KOMENTARZ

Comments are closed.