App::Ikaros解説ドキュメント

Masaaki Goshima edited this page Nov 7, 2013 · 4 revisions

はじめに

本モジュールを使うと、テスト実行時間を劇的に短くすることができます。
ですが、テスト単体の実行時間を短くする類いのものではありません。

本モジュールが適しているのは以下のような場合です

  • テストの数がとにかく多すぎて、一台のテスト実行サーバだと限界がある
  • forkproveを使って高速化したいのだけれど、一部どうしても失敗するテストがあって、全部に対しては適用できない

概要

このモジュールは、テスト実行リクエストが届いたノードから多数のノードに
テスト実行要求を出し、テスト時間の短縮率をノード数でスケールできるようにしたものです。
ようは、テストを処理するノードを足せば足すほど実行時間が短くなります。
また、本モジュールはJenkinsと併せて使用することにより、より効果を発揮します。
既にJenkinsサーバがあることを前提として動作の流れを説明します。

  1. JenkinsサーバにBuildリクエストが投げられる
  2. JenkinsサーバからApp::Ikarosがinstallされているノード(Masterノードとする)にテスト実行要求を投げる
  3. Masterノードから、n台にテスト実行要求を投げる
  4. n台でbuild
  5. 結果をMasterに集約
  6. MasterからJenkinsに結果を渡す
  7. Jenkins上で結果表示

使い方

  • モジュールをinstall
    cpanm -l extlib git@github.com:goccy/p5-App-Ikaros.git

  • n台にビルド要求を出すためのスクリプトを書く

use strict;
use warnings;
use App::Ikaros;

my $status = App::Ikaros->new({
    config         => 'config/ikaros.conf'
    config_type    => 'dsl',
    config_options => [] ※後述
})->launch(sub {
    my $failed_tests = shift;
    my $status = (@$failed_tests) ? 1 : 0;
    return $status;
});

exit($status);

これがkickスクリプトの雛形になります(ikarosという名前で保存したとする)。
Jenkinsの「実行するシェルスクリプト」の項目に、
perl -I/path/to/extlib/lib/perl5 /path/to/ikaros
などとしてたたけば、分散実行が始まります。
ですが、まだ何も設定していないので動きません。
設定を記述するのは、App::Ikarosのコンストラクタで指定したconfigファイルになります。

  • configファイルを記述する(config/ikaros.conf) configファイルの中身は以下のような感じになります
use strict;
use warnings;
use App::Ikaros::DSL;
use App::Ikaros::Helper qw/
    exclude_blacklist
    load_from_yaml
/;

# App::Ikarosの引数に渡したoptionsをGetopt::Longを使ってparseして返す
# configファイルにオプション等を渡したいときに有効
my $options = get_options;

my $all_tests = [ 't/sample01.t', 't/sample02.t', 't/sample03.t' ];
my $blacklist = [ 't/sample02.t' ];

# proveで実行するテストのリストを作る
my $prove_tests = $blacklist; # [ 't/sample02.t' ]

# forkproveで実行するテストのリストを作る
my $forkprove_tests = exclude_blacklist($all_tests, $blacklist); # [ 't/sample01.t', 't/sample03.t' ]

# remote hostに関する設定を読み込む
my $conf = load_from_yaml('config/hosts.yaml'); 

# 設定を適用
hosts $conf;

# リモートで実行するコマンド、テストのリストを設定する
plan {
    prove_tests     => $prove_tests,
    forkprove_tests => $forkprove_tests,

    # メインコマンドを実行するときにディレクトリを移動したい場合は、workdirからの相対パスを記述する
    chdir => 'work', 

    # proveコマンドを実行するときの引数などを指定
    # $proveと書くと、いい感じにproveへのパス解決をしてくれる。しかもリモートにproveをinstallする必要もない)
    prove_command     => [ 'perl', '$prove', '-Ilocal/lib/perl5', '-Ilib' ],

    # forkproveの場合も同様。別途リモートにApp::ForkProveをinstallしていなくてもApp::Ikarosがいい感じに
    # パス解決してくれるので、使用できる
    forkprove_command => [ 'perl', '$forkprove', '-Ilocal/lib/perl5', '-Ilib' ],

    # メインのコマンドを実行する前に環境構築等の処理を行いたい場合はここでコマンドを指定
    # 記述されたコマンドはリモートサーバ上で実行される
    before_commands   => [
        'if [ -d cover_db ]; then rm -rf cover_db; fi;',
        'if [ -f junit_output.xml ]; then rm junit_output.xml; fi;',
        'git clone https://github.com/user/target-app.git work',
    ],

    # メインコマンドが終了した後にcleanup処理などを行いたい場合は、ここでコマンドを指定する
    after_commands => []
};
  • config/hosts.yamlの中身は以下のように記述します。
# 全ホストのdefaultパラメータを指定する
default:
  user: goccy
  private_key: $HOME/.ssh/id_rsa
  coverage: true
  perlbrew: true
  runner: forkprove
  workdir: $HOME/ikaros_workspace

# ホスト毎の設定を個別に設定する
hosts:
  - remote1 # ホスト名
  - remote2:
      workdir: $HOME/ikaros_workspace_2  # workdirを上書き
  - remote3:
      runner: prove # テスト実行の際にproveを選択する
      workdir: $HOME/ikaros_workspace_3
  - remote4:
      runner: prove
      workdir: $HOME/ikaros_workspace_4

大きく、defaulthostsに対してパラメータを設定します。
設定値の優先順位は、hosts > defaultで、hostsで個別に設定した値があればそちらが優先されます。

設定できる値は、以下の6つです。

  • user : ssh接続する際のuser名
  • private_key : ssh接続する際のprivate_key
  • workdir : working directoryの名前を指定
  • runner : テスト実行の際にproveを使うかforkproveを使うかを指定
  • coverage : Devel::Coverを使ったcoverage結果を取得するか指定
  • perlbrew : コマンド実行時のperlバイナリのパス解決のために、$HOME/perl5/perlbrew/etc/bashrcを読み込むかを指定

実行結果のハンドリング

各ホストでのテスト実行結果は、非同期にMasterノードへ送られます。
また、並列度を上げるとDBの競合が起こりやすくなり、FAILするテストが増えることが予想されるため、
各ホストの最終結果を受け取った後、Masterノードで再度失敗したテストに対してテストを走らせます。
そのとき、並列度を1にし、かつproveを用いてテストを実行します。
その結果がテスト実行の最終結果となり、FAILしたテストのリストが$ikaros->launchの引数に与えた無名関数の引数として渡ってきます。

テスト結果は、Jenkinsで表示できるよう、JUnit形式のXMLで生成されます。デフォルトの名前はikaros_output.xmlです。
また、あわせて各テストの実行結果を記録した.proveも生成されます。
.proveは、次回App::Ikarosを用いてテストを実行する際に利用され、
テスト時間のかかっているものどうしが同一のテストクラスタに割り当てられないように配慮されます。
テストクラスタの最適化を自分で行いたいという要求があるかもしれませんが、現バージョンでできません。

今後

今後実装予定の機能としては、テストクラスタを最適化するためのプロファイリング機能や、
テストクラスタを自分でカスタマイズできるようにするための機能などを考えています。

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.