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:

iex break!
iex break!

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:

iex whereami
iex whereami

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?

2 KOMENTARZE

  1. Ja poczekam co powiesz, jak zajmiesz się tracingiem i podobnymi elementami dostępnymi w ERTS / OTP w temacie “introspekcji”. ;)

Comments are closed.