ディレクトリごとにテストが回せるMakefileが作りたくて

## はじめに
みなさん、テスト書いてますか？

プロジェクトが大きくなってくると、
今変更しているディレクトリとは全く関係のないテストが実行されるの煩わしいと感じることありませんか？

今まで、Makefileで全部のテストを実行した後pushするようなMakefileは使っていたのですが、
今変更しているディレクトリだけテスト回せないのかなーと思い、試してみた記録を残したいと思います。

よかったら参考にしつつアレンジしてみていただけたらと思います。

## この記事の対象者

- vitest使用者
- Makefile使ったことある人

です。

## 前提条件

以下のようなディレクトリ構造を前提とします

```
web
├── src
    ├── Service1
    │   ├── components
    │       ├── hoge1.test.tsx
    │       └── fuga1.test.ts
    ├── Service2
    │   ├── components
    │       ├── hoge2.test.tsx
    │       └── fuga2.test.ts    
    ├── Service3
    略
```

:::note info
開発を行なっていて、例えば、`Service1`の作業を行っているだけの変更している時に`test`を実行するとして、全く変更を行っていない、Sevice2, 3 のテストを無駄に回して時間を浪費するのは勿体無くね？というところから、Makefileを改良したいと思い立った人の記事になります。
:::

## まず結果系

package.jsonのscripts抜粋
```json
{
  "scripts": {
    "test": "vitest --watch=false",
    "test:service1": "vitest --watch=false src/Service1/**",
    "test:service2": "vitest --watch=false src/Service2/**",
    "test:service3": "vitest --watch=false src/Service3/**"
  }
}
```

webディレクトリ直下のMakefile

```makefile
.PHONY: test test-service1 test-sevice2 test-service3

test:
	npm run test

test-service1:
	npm run test:service1

test-service2:
	npm run test:service2

test-service3:
	npm run test:service3
```

ルート直下のMakefile
(本来ならバックエンド側のテストなども含まれるが割愛)

```makefile
.PHONY: submit submit-service1 submit-servic2 submit-service3

CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)

submit:
	make -C web test
	git push origin $(CURRENT_BRANCH)

submit-service1:
	make -C web test-service1
	git push origin $(CURRENT_BRANCH)

submit-service2:
	make -C web test-service2
	git push origin $(CURRENT_BRANCH)

submit-service3:
	make -C web test-service3
	git push origin $(CURRENT_BRANCH)
```

## ざっくり説明

基本的には、package.jsonに記述しているscriptsのコマンドでどのディレクトリのテストを実行するか定義しています。


package.jsonのscripts再掲
```json
{
  "scripts": {
    "test": "vitest --watch=false",
    "test:service1": "vitest --watch=false src/Service1/**",
    "test:service2": "vitest --watch=false src/Service2/**",
    "test:service3": "vitest --watch=false src/Service3/**"
  }
}
```

`test`コマンドを実行した場合は、全てのテストが実行されます。
`test:service1`などのコマンドの場合、`src/Service1/**`のように、Service1のディレクトリ内のみのテストを実行するので、Service1のコードを修正している時は関係ないService2, 3のテストは実行されなくなるので時間短縮につながるという寸法です。

あとは、webディレクトリの直下にMakefileを記述し、`make`コマンドでそれぞれのscriptを呼び出せばいいので、

```makefile
.PHONY: test test-service1 test-sevice2 test-service3

test:
	npm run test

test-service1:
	npm run test:service1

test-service2:
	npm run test:service2

test-service3:
	npm run test:service3
```

このような形でMakefileを記述しました。

ルート直下のMakefileでは、テストを実行したあとそのままpushしたいので、

```makefile
.PHONY: submit submit-service1 submit-servic2 submit-service3

CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)

submit:
	make -C web test
	git push origin $(CURRENT_BRANCH)

submit-service1:
	make -C web test-service1
	git push origin $(CURRENT_BRANCH)

submit-service2:
	make -C web test-service2
	git push origin $(CURRENT_BRANCH)

submit-service3:
	make -C web test-service3
	git push origin $(CURRENT_BRANCH)
```

このように`make submit`で全てのテストを実行しつつpushするのか、`make submit-service1`のように、Service1のテストだけ実行してpushするのか？などを選択できるようにしています。

## 補足

ルート直下のMakefileですが、
`git push`する際、どのブランチにpushするべきかを取得してコマンド内に流し込めるよう、
`CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)`で、現在のブランチ名を取得して
`git push origin $(CURRENT_BRANCH)`のコマンドで動的に与えることで、mainブランチ以外で作業していても同様にコマンドを使うことができるという工夫が入っています。

また、`make -C web test`でも見慣れない`-C`オプションが入っていますが、
`-C`の後ろのディレクトリ内に入った状態でどのmakeコマンドを実行するか？という記述をすることができ、
この場合の`make test`はwebディレクトリ内で実行した時の内容と同じコードが実行されることを意味しています。

このオプションを知らないと、
`cd web && make test`のようなコマンドを記述することになり、正しくディレクトリが移動された状態で`make test`が実行されるのか保証されないらしい(!?)ので、できる限り-Cオプションを使うようにするのが得策のようです。

## まとめ

ディレクトリを絞ってテストを実行する場合は、まずpackage.jsonに対象とするディレクトリのオプションを与えたものを準備し、そのスクリプトをMakefileから実行するとやりたいことができそうです。
Makefileの取り扱い方については自分自身まだまだ初心者の域を出ませんが、上手に使いこなせるようになりたいものです。

それではみなさま良きコードライフを。