Nimでtestsディレクトリ内の多階層テストファイルを一括実行

# １．Nimbleのデフォルトのテスト実行手順

## （１）パッケージディレクトリの初期化

　以下のコマンドを実行して、nimbleでパッケージディレクトリを初期化

```sh

# 任意の場所で、パッケージディレクトリを作成。例は、sampleパッケージを作成
mkdir sample
cd sample

# パッケージ関連ファイルを作成
nimble init
```

## （２）テストディレクトリを作成

　Windows、かつ、nimbleのバージョンが0.13.1で実行した場合、「tests」ディレクトリは作成されなかったので、「tests」ディレクトリを作成。

```sh
mkdir tests
```

## （３）パッケージモジュールのインポートパスを簡易化する設定

testsディレクトリ内に、「nim.cfg」ファイルを作成し、以下の内容を記載。

```sh
cd tests
echo --path:"../src/" > nim.cfg
```

　ファイルは以下のようになる。

```nim:nim.cfg
--path:"../src/"
```

　これでテストコードでimportした際に、「../」などの相対パスを記載する必要がなくなる。

```nim:test.nim
# import ../src/sample のようにする必要なし
import sample

```

## （４）テストコード作成

　テスト対象となるコードをパッケージのメインソースに作成する。

```nim:sample.nim

# 外部から呼び出しができるように「*」をつける。
func equalsOne*(val: int): bool =
  val == 1

when isMainModule:
  echo("Hello, World!")
```

　testsディレクトリ直下に、上記のコードを検証するテストコードを作成する。
　テストには、「std/unittest」モジュールを利用する。

```nim:test_sample.nim
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
```

　ここまでのパッケージ内のファイル構成は以下の通り。


```txt
📦sample
 ┣ 📂src
 ┃ ┗ 📃sample.nim（パッケージメインコード）
 ┣ 📂tests
 ┃ ┣ 📃nim.cfg
 ┃ ┗ 📃test_sample.nim
 ┗ 📃sample.nimble

```

## （５）Nimbleのコマンドにてテストを実行

　パッケージルートで以下のコマンドを実行する。

```sh
nimble test
```

　結果は以下の通り。

```sh
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
```

# ２．testsディレクトリ内の多階層テストコードの実行（testamentの利用）

## （１）nimbleのデフォルトでは多階層のテストコードは実行されない

　nimbleのデフォルトでは、testsディレクトリ直下のコードしか実行されない。
　たとえば、以下のように配置した「sample/tests/util/test_checker.nim」は実行されない。

```txt
📦sample
 ┣ 📂src
 ┃ ┣ 📂util
 ┃ ┃ ┗ 📃checker.nim
 ┃ ┗ 📃sample.nim
 ┣ 📂tests
 ┃ ┣ 📂util
 ┃ ┃ ┗ 📃test_checker.nim
 ┃ ┣ 📃nim.cfg
 ┃ ┗ 📃test_sample.nim
 ┗ 📃sample.nimble

```


## （２）標準のテストランナー「testament」


　tests以下のネストされたディレクトリ内のテストを実行する方法はいくつかある。ここでは、標準機能である「testament」というテストランナーを使った方法で実行する。「testament」は標準機能なので追加でインストールする必要はない。

　ちなみに、「testament」は「unittest」モジュールと比べると、テストコードを書くというよりも、細かい調整をしてテスト実行するテストランナーとしての性質が強い。

　確かに、「testament」を使うことで、チェックメソッドが変わるのでテストの書き方も変わるが、「unittest」モジュールと併用もできるため、純粋にテストランナーとして使うこともできる。
　個人的には、「unittest」の「suite、test」などの記述がRubyの「RSpec」のように、コードがテストドキュメントのようになるのでよいと思う。

「testament」と「unittest」の併用については、以下の記事に詳しく書かれている。

https://qiita.com/jiro4989/items/7ca0e6998e484bdc0a30



## （３）testamentにより多階層のテストコードを一括実行

　以下のようにテスト対象のコードを「src/util/checker.nim」に作成する。

```nim:src/util/checker.nim
func equalsTwo*(val: int): bool =
  val == 2
```

　上記のテストコードを、「tests/util/test_checker.nim」に作成する。

```nim: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

```

## （４）testamentによりすべてのテストを実行

　以下のコードをパッケージディレクトリの直下で実行。


```sh
testament c /
```

結果は以下の通り。

```sh
PASS: tests/test_sample.nim C                                      ( 3.26 sec)
PASS: tests/util/test_checker.nim C                                ( 3.26 sec)
```

p（または、pattern）コマンドもあるが、この場合、階層ごとにパターンを書く必要があるため、手間が増える。
c（または、cat/category）コマンドの場合、１つのコマンドすべて実行できる。
以下の記事にこれに関する記載がある。

https://dev.to/xflywind/how-to-use-testament-in-nim-1l0h

## （５）nimble testをオーバーライド

　testamentコマンドは長いし、どうせならnimbleで実行したいので、「nimble test」をnimbleのtaskとして定義して、オーバーライドする。
　以下のようにnimbleファイル（例の場合、sample.nimble）の下の方に記載。

```nim:sample.nimble
task test, "run all tests":
  exec "testament cat /"
```

　パッケージディレクトリの直下にて以下のコマンドを実行。

```sh
nimble test
```


　以上で、多階層のテストを一括で実行できる。