1.Nimbleのデフォルトのテスト実行手順
(1)パッケージディレクトリの初期化
以下のコマンドを実行して、nimbleでパッケージディレクトリを初期化
# 任意の場所で、パッケージディレクトリを作成。例は、sampleパッケージを作成
mkdir sample
cd sample
# パッケージ関連ファイルを作成
nimble init
(2)テストディレクトリを作成
Windows、かつ、nimbleのバージョンが0.13.1で実行した場合、「tests」ディレクトリは作成されなかったので、「tests」ディレクトリを作成。
mkdir tests
(3)パッケージモジュールのインポートパスを簡易化する設定
testsディレクトリ内に、「nim.cfg」ファイルを作成し、以下の内容を記載。
cd tests
echo --path:"../src/" > nim.cfg
ファイルは以下のようになる。
--path:"../src/"
これでテストコードでimportした際に、「../」などの相対パスを記載する必要がなくなる。
# import ../src/sample のようにする必要なし
import sample
(4)テストコード作成
テスト対象となるコードをパッケージのメインソースに作成する。
# 外部から呼び出しができるように「*」をつける。
func equalsOne*(val: int): bool =
val == 1
when isMainModule:
echo("Hello, World!")
testsディレクトリ直下に、上記のコードを検証するテストコードを作成する。
テストには、「std/unittest」モジュールを利用する。
import std/unittest
# nim.cfgにパスを設定したので、以下のような簡易な形式で呼び出せる
import sample
suite "sample":
test "equalsOne: invalid case":
assert equalsOne(2) == false
test "equalsOne: valid case":
assert equalsOne(1) == true
ここまでのパッケージ内のファイル構成は以下の通り。
📦sample
┣ 📂src
┃ ┗ 📃sample.nim(パッケージメインコード)
┣ 📂tests
┃ ┣ 📃nim.cfg
┃ ┗ 📃test_sample.nim
┗ 📃sample.nimble
(5)Nimbleのコマンドにてテストを実行
パッケージルートで以下のコマンドを実行する。
nimble test
結果は以下の通り。
sample>nimble test
Verifying dependencies for sample@0.1.0
Compiling [配置ルート]/sample/tests/test_sample (from package sample) using c backend
[Suite] sample
[OK] equalsOne: invalid case
[OK] equalsOne: valid case
Success: Execution finished
Success: All tests passed
2.testsディレクトリ内の多階層テストコードの実行(testamentの利用)
(1)nimbleのデフォルトでは多階層のテストコードは実行されない
nimbleのデフォルトでは、testsディレクトリ直下のコードしか実行されない。
たとえば、以下のように配置した「sample/tests/util/test_checker.nim」は実行されない。
📦sample
┣ 📂src
┃ ┣ 📂util
┃ ┃ ┗ 📃checker.nim
┃ ┗ 📃sample.nim
┣ 📂tests
┃ ┣ 📂util
┃ ┃ ┗ 📃test_checker.nim
┃ ┣ 📃nim.cfg
┃ ┗ 📃test_sample.nim
┗ 📃sample.nimble
(2)標準のテストランナー「testament」
tests以下のネストされたディレクトリ内のテストを実行する方法はいくつかある。ここでは、標準機能である「testament」というテストランナーを使った方法で実行する。「testament」は標準機能なので追加でインストールする必要はない。
ちなみに、「testament」は「unittest」モジュールと比べると、テストコードを書くというよりも、細かい調整をしてテスト実行するテストランナーとしての性質が強い。
確かに、「testament」を使うことで、チェックメソッドが変わるのでテストの書き方も変わるが、「unittest」モジュールと併用もできるため、純粋にテストランナーとして使うこともできる。
個人的には、「unittest」の「suite、test」などの記述がRubyの「RSpec」のように、コードがテストドキュメントのようになるのでよいと思う。
「testament」と「unittest」の併用については、以下の記事に詳しく書かれている。
(3)testamentにより多階層のテストコードを一括実行
以下のようにテスト対象のコードを「src/util/checker.nim」に作成する。
func equalsTwo*(val: int): bool =
val == 2
上記のテストコードを、「tests/util/test_checker.nim」に作成する。
import std/unittest
import util/checker
suite "util/checker":
test "equalsTwo: invalid case":
assert equalsTwo(1) == false
test "equalsTwo: valid case":
assert equalsTwo(2) == true
(4)testamentによりすべてのテストを実行
以下のコードをパッケージディレクトリの直下で実行。
testament c /
結果は以下の通り。
PASS: tests/test_sample.nim C ( 3.26 sec)
PASS: tests/util/test_checker.nim C ( 3.26 sec)
p(または、pattern)コマンドもあるが、この場合、階層ごとにパターンを書く必要があるため、手間が増える。
c(または、cat/category)コマンドの場合、1つのコマンドすべて実行できる。
以下の記事にこれに関する記載がある。
(5)nimble testをオーバーライド
testamentコマンドは長いし、どうせならnimbleで実行したいので、「nimble test」をnimbleのtaskとして定義して、オーバーライドする。
以下のようにnimbleファイル(例の場合、sample.nimble)の下の方に記載。
task test, "run all tests":
exec "testament cat /"
パッケージディレクトリの直下にて以下のコマンドを実行。
nimble test
以上で、多階層のテストを一括で実行できる。