https://engineering.mercari.com/blog/entry/how_to_use_t_parallel/
この記事は、Merpay Tech Openness Month 2020 の6日目の記事です。
メルペイでBackendエンジニアをしている柴田(@yoshiki_shibata)です。この記事では、Go言語のtesting
パッケージに用意されている並列化の機能について説明します。
Go言語では、テストコードを作成するためのtesting
パッケージが用意されています。一般に開発するソフトウェアの規模が大きくなるに従って、作成されるテストコードの量も多くなり、すべてのテストが終了するまでの時間も長くなっていきます。特に、データベースへアクセスするようなテストでは、データベースへの通信時間がテスト時間の多く占めますので、テストコードを逐次実行するよりは並列実行することで、テスト時間を短縮できます(厳密には用語「並行」ですが、t.Parallel()
メソッドの説明なので、この記事では用語「並列」を使っています)。
この記事では、*testing.T
のParallel()
メソッドについて解説します。
testing
パッケージを使ったテストコードの実行は、デフォルトでは逐次的です。ただし、逐次的なのは、ある特定のパッケージ内のテストに対してです。
複数のパッケージのテストを指定した場合、パッケージ単位でテストが並列に実行されます。たとえば、a
パッケージとb
パッケージがあった場合、a
パッケージ内のテストコードは逐次実行され、b
パッケージ内のテストコードも逐次実行されます。しかし、a
パッケージとb
パッケージのテストは並列に実行されます。この場合、どのようにして並列に実行されているかを次に説明します。
複数のパッケージを指定した場合(あるいは、./...
とすべてのパッケージを指定した場合)、いくつのパッケージが並列にテストが実行されるかは、go test
コマンドで指定する-p
フラグ(実際には、build
フラグ)で決まります。go help build
で-p
フラグの説明を表示すると、次のように表示されます。
-p n
the number of programs, such as build commands or
test binaries, that can be run in parallel.
The default is the number of CPUs available.
並列に実行可能なbuildコマンドあるいはテストバイナリといったプログラムの数。デフォルトは利用可能なCPUの数。
つまり、テストに関しては、-p
フラグで指定された値のプロセス数までテストバイナリーを複数プロセスとして(並列に)実行します。-p
フラブを指定しなければ、CPUの数がその値となります。また、どのパッケージをテストするかは自動的に割り振られます。つまり、各プロセス内では、逐次的に一つのパッケージのテストが実行されていることになります。仮に-p=1
と指定すると、テストを実行しているプロセスは一つだけですので、すべてのテストがパッケージごとに逐次実行されることになります。
補足:
-p
フラグで1より大きな値を指定して、複数のパッケージを指定(あるいは、./...
)してテストを実行して、テスト実行中に別のターミナルからps
コマンドを実行すれば、パッケージごとのテスト用バイナリが作られながら、パッケージごとにテストが行われているのが分かります。
p
フラグで大きな値を指定すれば、その指定した値の個数分のテストプロセスが生成されてテストの並列性は向上します。しかし、それは複数のパッケージのテストが並列に実行されるだけであり、個々のパッケージ内のテスト群が並列に実行されることにはなりません。パッケージ内のテストできめ細かな並列性を向上を行うためには、t.Parallel()
メソッドを使います。t.Parallel()
メソッドtesting.T
にはParallel()
メソッドがあります。t.Parallel()
メソッドの使い方は、少し分かりにくいですが、正しく使うにはきちんと理解する必要があります。Parallel()
メソッドの仕様は、次の通りです。
func (t *T) Parallel()
Parallel signals that this test is to be run in parallel with (and only
with) other parallel tests. When a test is run multiple times due to use of
-test.count or -test.cpu, multiple instances of a single test never run in
parallel with each other.