W zeszłym tygodniu wspomniałem o debugowaniu elixir z wykorzystaniem IEx.pry/0 – metody umożliwiającej za pomocą edycji pliku z kodem ustawienie breakpointa. Taki brakpoint będzie za każdym razem wywołany jak metoda będzie wykonana. Do tego wymagane było dodanie require z iex na samym początku pliku. Ogólnie dużo zachodu z edytowaniem pliku którego lepiej nie mieć. Na szczęście o tym samym pomyśleli twórcy elixir i wraz z wersją 1.5 dali nam do dyspozycji szereg komend umożliwiających prawie to samo co IEx.pry/0.
Zanim więc będziecie mogli przetestować nową funkcjonalność trzeba zaktualizować elixir do najnowszej wersji. Jak? To zależy od platform i pozostawiam wam do zarobienia. Mając już wersje 1.5 zainstalowaną, możemy zacząć bawić się nowymi komendami.
Tylko, że…… nowe komendy działają, jeżeli nasz kod jest przekompilowany i plik beam dostępny. Najszybciej to się robi za pomocą…… mix :) Więc polecam stworzyć mały projekt i wrzucić tam po prostu nasz ukochany plik testowy Bencode.ex. Najlepiej jakby nie zawierał on modyfikacji z zeszłego tygodnia.
Możemy teraz odpalić nasz nowy projekt za pomocą:
iex -S mix
Wraz z nowym elixir mamy do dyspozycji makro break! Które ustawia nam breakpoint na danej metodzie. Na przykład w bencode możemy ustawić sobie breakpoint w następujący sposób:
break! Bencode.decode/1 break!(Bencode, :decode, 1, 1)
Obydwa makra zrobią to samo, ustawią nam breakpoint na wejściu do funkcji decode/1 i ustawią go tylko na jedno uruchomienie.
Możemy podejrzeć wszystkie dostępne breakpointy jakie mamy za pomocą polecenia breaks:
iex(2)> breaks ID Module.function/arity Pending stops ---- ----------------------- --------------- 1 Bencode.decode/1 1
Całość wygląda mniej więcej tak:

Jeżeli teraz byśmy chcieli przetestować breakpoint to wystarczy, że wywołamy naszą funkcję a elixir zwróci nam:
iex(3)> Bencode.decode("i15e")
Break reached: Bencode.decode/1 (lib/bencode.ex:31)
29:
30: """
31: def decode (input) do
32:
33: val = input |> do_decode |> elem(0)
pry(1)>
Jak widać pokarze on nam miejsce, w którym się zatrzymał nasz kod i odpali pry. A to już znamy :) możemy tutaj dowiedzieć się o wartościach itp. Jest jednak jedno, ale – nie możemy ustawić linii. Możemy jedynie ustawiać breakpointy na metodzie. Co ma swoje plusy i minusy.
Jak już jesteśmy w breakpoint to za pomocą whereami/1 możemy wypisać sobie X linii kodu przed i po naszym breakpointcie.
pry(5)> whereami 5
Location: lib/bencode.ex:31
26:
27: iex> Bencode.decode("d4:testi1ee")
28: {:ok, %{"test" => 1}}
29:
30: """
31: def decode (input) do
32:
33: val = input |> do_decode |> elem(0)
34:
35:
36: case val do
To wygląda mniej więcej tak:

Oczywiście, możemy sprawdzić wartość input jak chcemy. To działa jak działało. Powrót jest taki sam – respawn/0.
Jeżeli zaś mamy więcej breakpointów to możemy zrobić continue/0 i kod będzie działał aż do kolejnego breakpointa jeżeli jest. Jeżeli go nie ma to nam się iex zawiesi :)
Jeżeli zaś powróciliśmy do iex to możemy wykonać polecenie breaks jeszcze raz by zobaczyć, że wartość w kolumnie stop uległa zmianie. A to znaczy, że jak wykonamy naszą metodę a cyfra tam jest na 0 to nasz breakpoint nie zadziała.
Możemy wyresetować wartość stop za pomocą reset_break/1 gdzie wartością jest ID naszego breakpointa z listy breaks – jednak u mnie to nie działało.
Podsumowanie
Najlepszą rzeczą jaką daje nam ta cała funkcjonalność to testowanie i debugowanie już istniejącego kodu – kodu elixira. Na przykład interesuje nas co się stanie kiedy wykonamy IO.puts/1 ?
break! IO.puts/1
Teraz jak wpiszemy:
IO.puts "test"
To zatrzymamy się w danym kontekście. Fajne to i przydatne jak się nie wiemy co nie działa i może to być wina zewnętrznej biblioteki.
Fajnie, że takie opcje dodali twórcy do elixira bo mogą być one przydatne. Na pewno jest to lepsze niż IEx.pry/0 – nie ma edycji kodu za cenę breakpointa na metodzie a nie na konkretnej linijce.
A wy co o tym sądzicie?















Ja poczekam co powiesz, jak zajmiesz się tracingiem i podobnymi elementami dostępnymi w ERTS / OTP w temacie “introspekcji”. ;)
;) tez jestem ciekaw :)
Comments are closed.