こんにちは、テクマトリックスの監物です。

コードの変更に関連するテストを機械学習で提示してくれる Launchable を使ってみましたのでご紹介します。

Launchableとは

機械学習によってコードの変更に関連するテストを提示してくれるプラットフォームです。OSSのCIツール Jenkinsの生みの親である川口氏がCo-CEOを務めるLaunchable, Inc.が提供しています。
これにより、開発者はコードを少し変更しただけで、全てのテストを実行しなければいけないということから開放されます。変更に関連しない無意味なテストを実行する必要がなくなるためテスト時間は短縮され、開発者は早いフィードバックを得ることができます。機械学習に必要なデータは、コードの変更に関連するメタデータのみなので、実際のコードを外にだす必要がないというのは安心です。

アーキテクチャは、次のようになっています。

  1. コードの変更についてのメタデータをLaunchableに送信
  2. Launchableに変更に関連するテストを要求
  3. Launchableから返されたテスト一覧を既存のツールで実行
  4. 機械学習のモデルを訓練するためにテストについてのデータをLaunchableに送信

Launchableを使ってみた

Gitで管理している次のJavaサンプルプロジェクトにLaunchableを使ってみました。
言語固有のツールではないため、様々な言語、ビルドツール、テストフレームワークをサポートしています。サポートの幅が広いのは嬉しいです。

  • 言語:Java
  • ビルドツール:Apache Maven
  • テストフレームワーク:JUnit

Launchable CLIをインストール

Launchable CLIは、Launchableとのデータのやり取りに使います。Launchable CLIは、Python3パッケージなので次のコマンドでインストールします。
稼働要件として、Python 3.5以降とJava 8以降をインストールしておく必要があります。

pip3 install --user --upgrade launchable~=1.0

環境変数LAUNCHABLE_TOKENにLaunchableのAPIキーを設定後、次のコマンドで接続確認をします。

launchable verify || true

CIツールに組み込んで実行

CIツールのJenkinsにLaunchableを組み込んでテストを実行します。
以下はJenkinsのパイプラインコードです。テストの成功/失敗に関わらずテストのデータがLaunchableに送信されるように、送信処理はpostセクションで常に実行されるようにしました。

stage('Launchable') {
  steps {
    withCredentials([string(credentialsId: 'launchable-api-key-creds', variable: 'LAUNCHABLE_TOKEN')]) {
      //コードの変更についてのメタデータをLaunchableに送信
      bat "launchable record build --name ${env.BUILD_TAG} --source src=."
      //Launchableにコードの変更に関連するテストを要求して、テスト一覧をlaunchable-subset.txtに保存
      bat "launchable subset --build ${env.BUILD_TAG} --confidence 90%% --rest launchable-remainder.txt maven src/test/java > launchable-subset.txt"
      //Launchableから返されたテスト一覧をMavenで実行
      bat "mvn test -Dsurefire.includesFile=launchable-subset.txt"
    }
  }
  post {
    always {
      withCredentials([string(credentialsId: 'launchable-api-key-creds', variable: 'LAUNCHABLE_TOKEN')]) {
        //機械学習のモデルを訓練するためにテストについてのデータをLaunchableに送信
        bat "launchable record tests --build ${env.BUILD_TAG} maven target/surefire-reports"
      }
    }
  }
}

コードの変更についてのメタデータをLaunchableに送信

パイプラインの5行目でコードの変更についてのメタデータをLaunchableに送信しています。

>launchable record build --name jenkins-launchable-master-1 --source src=. 
Launchable recorded build jenkins-launchable-master-1 to workspace tmx-corp/demo with commits from 1 repository:

| Name   | Path   | HEAD Commit                              |
|--------|--------|------------------------------------------|
| src    | .      | c5e31828c3c759d5b5f85928a6d4cc312aec6c77 |

Launchableに変更に関連するテストを要求

パイプラインの7行目でLaunchableにコードの変更に関連するテストを要求して、返されたテスト一覧をlaunchable-subset.txtに保存しています。
テストの要求時、次の3つの観点でテストを要求することができるため、Confidence(–confidence) 90%のテストを要求しました。Confidence 90%でテストを要求すると、コードの変更に関連していて90%の割合で失敗するテストの一覧が返されます。今回は、Launchableから実行するべきテスト一覧として1つのテストクラスが返されました。

  • Confidence (–confidence):指定した割合で失敗する、コードの変更に関連するテストを要求
  • Fixed duration (–time):コードの変更に関連するテストを指定した時間分要求
  • Percentage duration (–target):コードの変更に関連するテストを指定した時間割合分要求
>launchable subset --build jenkins-launchable-master-1 --confidence 90% --rest launchable-remainder.txt maven src/test/java  1>launchable-subset.txt 
Your model is currently in training
Launchable created subset 109586 for build jenkins-launchable-master-1 (test session 862780) in workspace tmx-corp/demo

|           |   Candidates |   Estimated duration (%) |   Estimated duration (min) |
|-----------|--------------|--------------------------|----------------------------|
| Subset    |            1 |                  14.2857 |                1.66667e-05 |
| Remainder |            6 |                  85.7143 |                0.0001      |
|           |              |                          |                            |
| Total     |            7 |                 100      |               14.2858      |

Launchableから返されたテスト一覧を既存のツールで実行

パイプラインの9行目でLaunchableから返されたテスト一覧(launchable-subset.txt)をMavenで実行しています。
Launchableから提示された1つのテストクラスのみ実行されました。コードの変更とは関係のないテストが実行されましたが、きちんと機械学習のモデルを訓練していないため妥当な結果です。訓練には数週間ほどかかり、時間の経過と共にどんどん賢くなっていくようです。

>mvn test -Dsurefire.includesFile=launchable-subset.txt 
...
...
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running examples.junit.NaiveStringBuilderParameterizedTest
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 s - in examples.junit.NaiveStringBuilderParameterizedTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

機械学習のモデルを訓練するためにテストについてのデータをLaunchableに送信

パイプラインの16行目で機械学習のモデルを訓練するためにテストについてのデータをLaunchableに送信します。

>launchable record tests --build jenkins-launchable-master-1 maven target/surefire-reports 
Launchable recorded tests for build jenkins-launchable-master-1 (test session 862780) to workspace tmx-corp/demo from 1 files:

|   Files found |   Tests found |   Tests passed |   Tests failed |   Total duration (min) |
|---------------|---------------|----------------|----------------|------------------------|
|             1 |             4 |              4 |              0 |                      0 |

ダッシュボードの確認

Launchableの様々なダッシュボードからテストの結果や傾向などを確認することもできます。
次のダッシュボードではテストの平均実行時間、実行頻度、失敗頻度などのテストの傾向を確認できます。グラフに着目するとテストの平均実行時間が減少しているため、これがLaunchableの効果だと考えられます。

まとめ

Launchableを使うとコードの変更に関連するテストに絞って実行することができるため、テストの実行時間を短縮できます。テスト時間が短縮されるのは、開発者さらにはビジネスの観点でも嬉しいことではないでしょうか。簡単にセットアップでき、サポートする環境も幅広いため導入のハードルも低く感じました。