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.TParallel()メソッドについて解説します。

複数パッケージのテストを並列に実行する

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コマンドを実行すれば、パッケージごとのテスト用バイナリが作られながら、パッケージごとにテストが行われているのが分かります。

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.