1 of 9

Circuits.GPIOは

いかにテストされているか

2022/07/23 NervesJP #27

2 of 9

What’s Circuits.GPIO?

  • Linux のGPIO(General-purpose input/output), 汎用入出力ピンを�操作するElixirのライブラリ
  • NervesでLチカをやったことがあれば使ったことがあるはず
    • だけど、Nerves 専用のライブラリというわけではなく、�LinuxのGPIOを持ったマシンであれば、ピュアElixirプロジェクトからも使用することができます。

iex> alias Circuits.GPIO

iex> {:ok, pin} = GPIO.open(1, :output)

iex> :ok = GPIO.write(pin, 1)

3 of 9

Circuits.GPIOの構成

  • lib/gpio.ex
    • ユーザ向けAPI用モジュール
  • lib/gpio_nif.ex
    • nif用モジュール
  • src/*
    • gpio操作の低レイヤ実装
  • test/cicuits_gpio_test.exs
    • テスト用モジュール、mix test で実行される
    • ユーザ向けAPI用モジュールのテストを行う

ちょっとだけ中身をのぞこう(時間あるかな?

4 of 9

Circuits.GPIOをテストするには?

  • Linuxマシン固有のテストは�実機でなければできない

なので、

  • 実機でなければテストできない部分
  • 実機でなくてもテストできる部分

に分けてやれば、�後者はどんな環境でもテストを回すことができる

どのように分け、後者のテストをしているか興味あり!!

5 of 9

ユーザのAPIコールからGPIO操作までの流れ

Circuit.GPIO

Circuit.GPIO.Nif

gpio_nif.c

gpio_nif.h

hal_sysfs.c

/sys/class/gpio/* を操作

iex> alias Circuits.GPIO

# /sys/class/gpio/1/direction を “out”

iex> {:ok, pin} = GPIO.open(1, :output)

# /sys/class/gpio/1/value を “1”

iex> :ok = GPIO.write(pin, 1)

6 of 9

/sys/class/gpio/* なしでテストするために

Circuit.GPIO

Circuit.GPIO.Nif

gpio_nif.c

gpio_nif.h

hal_sysfs.c

hal_stab.c

テスト用実装

7 of 9

ポイント

Circuit.GPIO

Circuit.GPIO.Nif

gpio_nif.c

gpio_nif.h

hal_sysfs.c

hal_stab.c

テスト用実装

インタフェースを定義

sysfs非依存の�ロジックを実装

sysfsをシミュレートするのではなく、テストに必要な応答のみをする薄い実装にする

テスト範囲は

ユーザ向けAPIの関数から、�インタフェース関数の呼び出しまで

操作実装の切り替えはMakefile

8 of 9

このパターンは?見覚えが、、

  • そう、Moxでやることと同じ
    • Mox: Elixir のテストサポートライブラリ�https://github.com/dashbitco/mox

NervesJP.Behabiour

NervesJP.Impl

NervesJP.Mock

ビヘイビアで各関数の入出力、�インタフェースを定義する

OSのファイル操作や外部のWeb APIなど�応答をコントロールできない関数を�まとめたモジュール

応答をコントロール可能なMockに切り替え、�このインタフェースを呼び出す�ロジックのテストを可能にする

9 of 9

まとめ

  • Circuits.GPIOがどのようにテストされているかを紹介しました
  • POINT: インタフェースを定義して、�その内部実装を切り替える方法はテストに限らず有効!なことを理解しました
    • Cならヘッダファイルがインタフェースとして使える
    • ElixirならBehaviourがインタフェースとして使える

Have nice Nerves days!!!�Thank you!!