2024.08.20

Apexテストの並列実行について

Just a moment... (33432)

はじめに

こんにちは
今回はSalesforceのApexクラスの並列処理について解説します。

本番組織へApexクラスをリリースする際は、Apexテストを実行し、カバレッジ率が75%を超える必要があることは、この記事の読者であればご存知の方は多いでしょう。

※早速脱線ですが、この75%もリリースのオプションによってどの75%なのか変わってくるのですが、それについては別の機会に触れたいと思います。

本番組織にリリースをする際に、Sandbox環境の設定から事前にApexテストを実行し、カバレッジ率が75%を超えていること、またApexテストが問題なく完了することを確認されているかと思います。
しかしながら、リリースする際のApexテスト実行とSandbox環境の設定から実行するApexテストは微妙に挙動が異なることをご存知でしょうか。

Apexテスト実行の比較

Sandboxから本番組織へ変更セットを用いてリリースする際は、円グラフと1/100のような分数が表示され、カウントが1つずつ進むのは、Salesforceのリリースをしたことがある方なら見たことはあるかと思います。

このことからも分かるように、リリースをする際のApexテスト実行については並列処理ではなく、逐次実行なされているものと推察ができます。
一方、Salesforceの設定からApexテストを行う際はデフォルトでは並列実行されます。
(※開発者コンソールからApexテストを行う際も並列実行されます)

このことによって、エラーが発生する可能性がありますが、よくあるエラーとして「UNABLE_TO_LOCK_ROW」 エラー が挙げられます。
Salesforceヘルプによると、以下のようなケースで発生するようです。
・複数のテストで同じレコードを同時に更新する場合。同じレコードが更新されるのは、通常、テストが独自のデータを作成せず、データの分離をオフにして組織のデータにアクセスする場合です。

・並列して実行しているテストで、インデックス項目値が重複しているレコードを作成しようしてデッドロックが発生する場合。デッドロックが生じるのは、実行中の 2 つのテストが相互にデータのロールバックを待機している場合です。2 つのテストが、一意のインデックス項目値が同じレコードを挿入したときにこのような待機が発生します。
上記の引用に加えて、私見を述べます。このエラーがよく発生するパターンとしては、ユーザーのテストデータ作成時です。複数のテストクラスで同一DeveloperNameのロールを作成すると、「UNABLE_TO_LOCK_ROW」エラーが発生する経験したことがあります。

並列実行の無効化

さて、思わぬ挙動の違いでApexテストが失敗する可能性があることはお伝えできたかと思いますが、次に回避策をお伝えします。

解決策として、「UNABLE_TO_LOCK_ROW」 エラー が発生しないようにテストコードを作成・修正する方法もありますが、手っ取り早いのは「並列 Apex テストを無効化」オプションを有効化することです。

このオプションは「設定」→「カスタムコード」→「Apex テスト実行」→「オプション」とクリックすると表示されます。

このオプションを有効化することで、設定からのApexテスト実行が逐次処理になるうえ、開発者コンソールからApexテストを実行した場合でも逐次処理になります。

また補足ですが、Apexテストクラスのアノテーションに「@IsTest(IsParallel=true) アノテーション」というものがあります。
このアノテーションを付与することで、「並列 Apex テストを無効化」オプションを有効化していても、強制的に並列実行にすることが可能になります。

あまり適当なユースケースは思いつかないのですが、 組織内のApexテストクラスで、逐次処理が必要なテストクラスと、並列処理が可能なテストクラスがある時にテスト実行を早く終了させたい時には有効なのではと思います。(特に組織内に大量にテストクラスがある場合には実行時間の短縮に有効と思われます)

おわりに

Apexテスト実行に並列実行と逐次実行の2通りがあることは意外だったのではないでしょうか。
私自身、本文中に記載したエラーに遭遇するまで意識したことはありませんでした。
この記事がApexテストクラスについて悩む方の参考になれば幸いです。
14 件
     
  • banner
  • banner

関連する記事