Gradle SSH PluginやGroovy SSHはどのようにテストしているか
G*Advent Calendar 2015の18日目です。
昨日は某社の方をゲストに迎えて闇の話をしていたためAdvent Calendarの公開が遅れました。大変申し訳ございません。
本記事では、Gradle SSH PluginやGroovy SSHをどのようにテストしているか説明します。GradleのプラグインやGroovyのツールを公開している方の参考になれば幸いです。
プロダクトの構成
Gradle SSH Pluginは、GradleのビルドスクリプトからSSHを利用するためのプラグインです。AP/DBサーバの再起動やデプロイなどの自動化を想定しています。詳細な仕様は割愛しますが、独自のDSLでコマンド実行やファイル転送を記述します。DSLの処理はGroovy SSHというライブラリに委譲しています。すなわち、Gradle SSH PluginはGradleとGroovy SSHをつなぐ薄いラッパーといえます。
Groovy SSHは、SSHでコマンド実行やファイル転送を行うためのライブラリです。JSchを利用しています。GroovyでJSchを簡単に使うためのラッパーといえます。ライブラリではなくコマンドラインツールとして利用することも可能です。
Gradle SSH PluginとGroovy SSHの関係は下図のようになります。
テストの考え方
基本的には、SSHサーバと結合した状態で、DSLの仕様に対する振る舞いをテストします。例えば、 execute 'ls'
というDSLを実行したらリモートホストで ls
コマンドが実行されることを確認します。
最終的にはOSと結合したテストが必要です。これはOpenSSHやUNIXコマンド(sudoなど)と実際に結合してみないと動作が分からない場合があるためです。このテストを行うには想定通りにOSが設定された環境が必要になります。OS上にuser100が存在して公開鍵認証でログイン可能なことといった環境を開発者に強いるのは無理ですよね。なので、Travis CIやDockerなどでテストを行います。
ただし、開発環境で気軽にテストを実行できないと開発効率が落ちてしまいます。JVMだけで基本的なテストを実行できるようにしておきます。
Gradle SSH Pluginはテスト済みのGroovy SSHを組み込んで出荷します。そのため、Gradle SSH Pluginのテストは最小限に留めます。
JSchはドキュメントに仕様が詳しく書かれていないため、不安を解消するために必要以上にテストを書いているところもあります。JSchは幸いにもオープンソースなので中を読みながら仕様を調べていますが、動かしてみないと分からないことが多いです。
これらを踏まえて、以下のテストを設けています。
ユニットテスト
接続のリトライや設定の継承といった複雑で間違えやすい処理については個別にユニットテストを書きます。特に難しいところはないです。
SSH server integration test
JVM上で動作するSSHサーバ(Apache MINA SSHD)をテストダブルにして、Groovy SSHの振る舞いを確認します。JVM上で動作するSSHサーバを利用することで、IDEAなどの開発環境で簡単に動作を確認できる、Windowsでも動作を確認できるといったメリットがあります。
このテストではDSLの仕様に対する振る舞いを確認します。Apache MINA SSHDはコマンド実行に対する戻り値や標準入出力なども細かく指定できるので、仕様に対する振る舞いを網羅的に確認できます。
OS integration test
想定通りに設定されたLinux環境に対して、Groovy SSHの振る舞いを確認します。まっさらな環境にシェルスクリプトを流して設定を行います。例えば、sudoers
, useradd
, sshd_config
, authorized_keys
などを設定していきます。
このテストではOSに依存する動作を確認します。例えば、sudoプロンプトでパスワードを要求された場合の動作、OpenSSH SFTP subsystemの動作、ECDSA鍵の認証などを確認します。現状ではOSに依存する部分を網羅的に洗い出せていないので、不安な部分やおかしいなと思った部分を少しずつ挙げていっています。
このテストを実行するには自由に設定できる環境が必要です。現状ではTravis CI上のLinuxからEC2上のLinuxにSSHして動作を確認しています。EC2のコストが。。。
コマンドラインツールとしてのテスト
Groovy SSHはコマンドラインツールとして提供します。そのため、コマンドラインツールとしての振る舞いを確認しておく必要があります。コマンドライン引数のテストはSpockで書いています。また、ツールにスクリプトを与えてちゃんと動作するかどうかは、ビルド済みのJARファイルを実際に実行して確認します。これもシェルスクリプトで自動化しています。
実際にユーザの立場になって使ってみることで見えてくる課題もあります。ログが見づらいとか。新しい機能を追加する時は使い勝手を必ず確認するようにしています。
Gradle integration test
Gradle SSH PluginにGroovy SSHを組み込んで振る舞いを確認します。基本的なシナリオが通ればOKとしています。また、Gradle SSH Pluginだけの機能もここで確認します。
GradleにバンドルされているGroovyのバージョンは突然変わることがあります。先日のGradle 2.8ではGroovyのバージョンが2.4.4になりました。Groovyのバージョンが変わっても動作に影響がないこともここで確認しておきます。
まとめ
Gradle SSH PluginやGroovy SSHのテストをどのような考え方で行っているか説明しました。これからGradleプラグインを開発する方の参考になれば幸いです。まとめ直してどこか勉強会で発表しようかな。