VSCodeで平行実行に対応したGoテストコードを自動生成する

この記事は、現在開催中のイベント「3000文字Tips - 知ると便利なTipsをみんなへ届けよう」の記事です。

https://qiita.com/official-events/d523df99d6479293ffa7

## この記事の内容
GoogleのGo言語開発チームがサポートしているVSCodeのGo言語拡張機能では、**関数・メソッドからTable Driven Testに対応したユニットテストの雛形を自動で作成してくれる機能**があります。（デフォルトだと、[対象の関数・メソッドで左クリック　or コマンドパレット] -> [Go: Generate Unit Tests For Function]）

https://marketplace.visualstudio.com/items?itemName=golang.go

このままでも十分便利なのですが、実際の業務では`t.Parallel()`を使って平行実行するテストを書くことが多いかと思います。   
都度`t.Parallel()`を書いても良いのですが、どうせなら自動生成できた方がいいです。
**この記事では、設定によって平行実行に対応したユニットテストの雛形を自動生成できるよ、というTipsです。**

## サブテストを平行実行に対応させる
サブテストを平行実行に対応させるには、VSCodeの設定を変更するだけで可能です。

1. 設定

2. [検索] -> [Go: Generate Test Flags]

3. [項目の追加] -> `-parallel`を追加

もしくは、settings.jsonに以下の項目を追加

```json:settings.json
  "go.generateTestsFlags": [
    "-parallel"
  ],

```
### 実際にやってみた
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261575/7ab1436f-2f7a-1fa0-01df-688329662985.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261575/bc3467ec-1114-0737-d391-1710fe1c0b1d.png" width=50%>

サブテスト関数に、`T.Parallel()`がちゃんと記述されていることがわかります。また、[一部のテストケースしか評価されない問題](https://qiita.com/sho-hata/items/19356a3525fa47cfd2b1)を防ぐためのループ変数の初期化(`tt := tt`)もされていることがわかります。

### 補足
Go拡張機能のユニットテストの雛形を自動で作成する機能は、内部で`cweill/gotests`を使用して実現しています。

https://github.com/cweill/gotests

```bash
$ gotests [options] PATH ...
```

これは上記のように、実行時オプションを付与することができます。

先程`-parallel`という項目を設定しましたが、この設定が実行時オプションとして渡され、平行実行に対応したコードが生成されるという仕組みです。
#### さらに補足
https://github.com/cweill/gotests のソースコードを読んでいくと、
自動生成用のテンプレートファイルがあり、有効にしたオプションによって生成されるテストコードが変わるということがわかります。
関数・メソッドのテンプレートは↓で、
https://github.com/cweill/gotests/blob/develop/templates/testify/function.tmpl

```function.tmpl
{{- if .Parallel}}tt := tt;{{end}}
```
実行時オプションテストコード`-paralell`オプションが渡されたときのみ有効化されるようです。

## トップレベルテストを平行実行に対応させる
`-parallel`オプションは、サブテスト関数を平行実行に対応させることができますが、トップレベルテストには対応してくれません。


ただ、https://github.com/cweill/gotests には`-template_dir`というオプションがあります。
自動生成されるテストコードの自作テンプレートを作り、

```bash
$gotest -template_dir {自作テンプレートが置いてあるパス}
```
のようにテンプレートファイルが置いてあるパスを教えてあげることで、自分好みのテストコードの雛形を作成することができます。

これを利用して、トップレベルテストを平行実行に対応させます。
### 方法
1 https://github.com/cweill/gotests/blob/develop/templates/testify/配下のテンプレートをローカルにコピーする

2 コピーしたテンプレート（functions.tmpl）を書き換える

やりたいのは、`-parallel`オプションが有効時にトップレベル関数の下に`t.Parallel()`を記述するという、非常にシンプルなことです。

```tmpl:function.tmpl
func {{.TestName}}(t *testing.T) {
	{{- if .Parallel}}t.Parallel(){{end}}
```
`function.tmpl`に、このような記述を追加すればOKです。
今回作成したテンプレートファイルはこちら
　
https://github.com/hatahata7757/gotest-template

3 [項目の追加] -> `-template_dir`・`テンプレートが置いてあるパス`を追加
![スクリーンショット 2021-06-22 9.35.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261575/6838a44b-eb1c-1073-6bf2-0a3cbfee86a8.png)

### 実際にやってみた
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261575/c1e429eb-f03f-c007-1c2d-fc956c76249b.png" width=50%>
トップレベル関数の下に`t.Parallel()`が反映されていることがわかります。

##終わりに
「自動生成されるテンプレを書き換えたりできないものかなぁ」とふと思って調べたことが始まりでしたが、比較的簡単にやりたいことが実現できました。
[こちらの方](https://magaming.hatenablog.com/entry/2020/03/24/221713)のように自作テンプレをカスタマイズして、もっと便利にできそうです。

## 参考資料

https://magaming.hatenablog.com/entry/2020/03/24/221713

https://github.com/cweill/gotests