Nixで単体テスト

2023/04/16に公開

はじめに

Nix は非常に強力なパッケージマネージャであり、Nix (言語) を利用してパッケージマネージャの枠にとらわれないコトを実現できます。styxのようにSSGを作成することも可能です。

そんなNixですが、昨今の実用言語の中では開発体験が厳しく、型の支援はほとんど得られず、静的解析も限界があります。また記述の自由度の高いのも相俟ってVimとEmacsが入った配列のキーがsで始まる要素に1を足すような間違った記述も簡単にできてしまいます。型起因のバグの場合、大量のエラーメッセージが出力されるため原因の特定も困難です。

Nixを利用して、込み入った処理を行なうのであれば単体テストを実施して安心を得るのがゴールへの近道です。

単体テストの方法

Nixに単体テストを利用する際には runTestsnixtpythonix の3つの方法が選択できます。nixtはまだ枯れておらず、pythonixはアーカイブ化されているため今回はrunTestsを採用します。

flakes

Nixを利用する上で事実上標準となっているflakesのchecksを利用してテストを実行するようにします。
checksに drv を記述すると nix flake check でチェックを走らせることが可能です。記述できる drv に制限は無いのでフォーマッタやリンター、Nixに限らないテストの実行などが可能です。
https://github.com/ttak0422/oboro-nvim/blob/fed2c0fdbc0374ce2574ce8de60a2c9e2fe32d25/flake.nix#L105-L119

fizzbuzzとut

Nixでfizzbuzzをする簡単なコードを記述してutを実施してみます。

https://github.com/ttak0422/fizz-buzz-nix/blob/987d7a710068e5758f911562f18f467847553458/flake.nix#L19-L27

runTests は AttributeSets を引数に受け付けます。キーはテスト名、値は expr と expected を要素に持つ AttributeSets です。テスト名は test で始まる必要があります。

https://github.com/ttak0422/fizz-buzz-nix/blob/987d7a710068e5758f911562f18f467847553458/flake.nix#L32-L49

runTests をどう実行するのが良いのかについては得に明言されていないため runCommand 経由で実行するようにします。Nixの思想に従って失敗すれば失敗に関するファイルへのリンクを示すようにします。
https://github.com/ttak0422/fizz-buzz-nix/blob/987d7a710068e5758f911562f18f467847553458/flake.nix#L50-L62

十分にテストされたfizzbuzzするappの完成です。

$ nix flake check

$ echo $?
0

$ nix run
[
  "1",
  "2",
  "fizz",
  "4",
  "buzz",
  "fizz",
  "7",
  "8",
  "fizz",
  "buzz",
  "11",
  "fizz",
  "13",
  "14",
  "fizzbuzz",
  "16",
  "17",
  "fizz",
  "19",
  "buzz"
]

参考

Discussion