1. OverView
どもども、うん、アドベントカレンダーの完走賞狙いなんだ、すまない。
さて、hexdocにあるデバッグ方法を順を追って調べようと言う話題です。
IO.inspect/2
dbg/2
Pry
Breakpoints
Observer
Other tools and community
順を追ってPryを…と思ったけど、これ、コードの変更が必要ですし。
すごい良い解説がネットにあふれてるので、お前書く必要ある?と言われると自信がない。
なので、次、Breakpointsに行きたいと思います。
え?Observer...起動したけど、理解が追いつかんかったw
2. break!
2.1 hexdocで確認
さて、ブレークポイントが設定出来るくらいで、特に面白くも無かろうと思ってたんですが、
h()を見てたら、意外と機能が豊富なので改心しました。
• break!/2 - sets a breakpoint at Module.function/arity
• breaks/0 - prints all breakpoints to the terminal
• c/0 - a shortcut for continue/0
• continue/0 - continues execution of the current process
• n/0 - a shortcut for next/0
• next/0 - goes to the next line of the current breakpoint
• remove_breaks/0 - removes all breakpoints and instrumentation from all
modules
• whereami/1 - prints the current location and stacktrace in a pry
session
作業の流れは、
- ブレークポイントを決めて、break!/2 でブレークポイントを設定します。
break! Example.double_sum/2で関数に入るところで止まる様にしております。
(base) C:\Users\nanbu\example>iex.bat -S mix
Erlang/OTP 27 [erts-15.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.18.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> break! Example.double_sum/2
1
そして、モジュールの実行です。
iex(2)> Example.double_sum( 2, 4 )
Break reached: Example.double_sum/2 (lib/example.ex:3)
1: defmodule Example do
2: def double_sum(x, y) do
3: hard_work(x, y)
4: end
5:
6: defp hard_work(x, y) do
iex(3)>
プログラムが実行され、double_sumで止まっている事がわかりました。
さて、いろんなコマンドを使ってみましょう。
- whereami
自分の位置やスタックとレースを表示してくれます。
iex(3)> whereami
Location: lib/example.ex:3
1: defmodule Example do
2: def double_sum(x, y) do
3: hard_work(x, y)
4: end
5:
(example 0.1.0) Example.double_sum/2
(elixir 1.18.0) lib/module/parallel_checker.ex:120: Module.ParallelChecker.verify/1
- Breakpointの操作
プログラムの実行の前に、remove_breaksとbreaksを紹介しましょう。
breaksはbreak pointの一覧を表示します。
remove_breaksはbreak pointを削除します。
以下、 break!でExample.double_sum/2でbreak pointを三回分設定、
breksで確認後、remove_breaksでbreak pointを削除しています。
iex(19)> break!(Example.double_sum/2, 3)
1
iex(20)> breaks
ID Module.function/arity Pending stops
---- ----------------------- ---------------
1 Example.double_sum/2 3
iex(21)> remove_breaks
:ok
iex(22)> breaks
No breakpoints set
iex(23)>
- プログラムの実行を継続
nextとcontinueがあります。
nextは一行だけ実行、次の行に移動します。continueは、そのまま処理を続けます。
next: 次の行を実行し、次のブレークポイントまたは次の行で停止します。
continue: プログラムの実行を再開し、次のブレークポイントで停止します。
nextはn, continueはcとリンクが定義されてます。
次の関数に入る、step-inがないみたいですねぇ、まぁ、以下の様にブレークポイントを設定すりゃいいだけだけど
iex(9)> breaks
ID Module.function/arity Pending stops
---- ----------------------- ---------------
1 Example.double_sum/2 2
2 Example.hard_work/2 1
iex(10)> Example.double_sum( 2, 4 )
Break reached: Example.double_sum/2 (lib/example.ex:3)
1: defmodule Example do
2: def double_sum(x, y) do
3: hard_work(x, y)
4: end
5:
6: defp hard_work(x, y) do
iex(11)> next
Break reached: Example.hard_work/2 (lib/example.ex:7)
4: end
5:
6: defp hard_work(x, y) do
7: x = 2 * x
8: y = 2 * y
9:
10: x + y
nextを実行していくと、どんどん行が進むのがおわかりでしょうか?
iex(11)> next
Break reached: Example.hard_work/2 (lib/example.ex:7)
4: end
5:
6: defp hard_work(x, y) do
7: x = 2 * x
8: y = 2 * y
9:
10: x + y
iex(12)> next
Break reached: Example.hard_work/2 (lib/example.ex:8)
5:
6: defp hard_work(x, y) do
7: x = 2 * x
8: y = 2 * y
9:
10: x + y
11: end
iex(13)> next
Break reached: Example.hard_work/2 (lib/example.ex:10)
7: x = 2 * x
8: y = 2 * y
9:
10: x + y
11: end
12: end
こんな感じで、ゆっくりとデバッグが出来ます。
- 変数を調べるのは、はい、binding()で
昨日の今日なので、ハイ、binding()ですね。
以下の様に、ローカル変数xとyが表示されるのがわかるでしょうか?
iex(14)> binding()
[x: 4, y: 8]
iex(15)>
以上です。
意外と便利ですね。