こんにちは、Web系エンジニアのナカガワです。
皆さん、エンジニアtypeに掲載された私の雄姿(><)は見て頂けましたか?
「技術探求型」で新しい受託開発を実現してきたアクロクエストが有する“組織技術力”とは? - エンジニアtype
まだの人はいますぐチェック!!
さて、前回はRestfuseを使ったテストの手順を説明しました。今回はそのテストをJenkinsで自動化するまでの手順を紹介したいと思います。
Jenkinsを使ってどのような自動試験にするか
まずはEclipseプロジェクトやJenkinsプロジェクトをどのような構成にするかを考えます。
前回の手順では「アプリケーション本体(=テスト対象)」と「結合テスト」を別のEclipseプロジェクトにしました。そのため、Jenkinsプロジェクトでも同様に、この2つに分けて構築しました。
2つのプロジェクトに分けることで、アプリケーション本体側のテストコードと、結合テスト側のテストコードを分けることができます。たとえば実際の業務では、アプリケーション本体側をシンプルなユニットテストにして、結合テスト側をAPサーバやDBサーバを利用した結合テストにしていました。
つまり、Jenkinsで以下のように処理することになります。
- アプリケーション本体をビルドしてwarファイルを作成する
- warファイルを、テスト用プロジェクトにコピーする
- APサーバを起動する
- テストを実行する
- APサーバを停止する
それでは、実際に設定する手順を説明します。
Jenkinsの自動試験用の設定
1. プロジェクトの作成
まずはJenkinsを起動して、プロジェクト作成します。
※Jenkinsインストールは割愛しますね。
アプリケーション本体も、結合テスト用プロジェクトも、いずれもMavenプロジェクトなので、ビルドは「Maven2/3プロジェクトのビルド」を選択します。
※今回は業務の都合上、Mavenは3系ではなく2.2.1を使いました。
アプリケーション本体用と、結合テスト用プロジェクトのそれぞれについて、Jenkinsプロジェクトを作りました。
どちらもMavenの実行において、clean installを指定しておきます。
※結合テスト用のプロジェクトはinstallでなくてもintegration-testが実行されるものであれば構いません。
2. アプリケーション本体のビルドとwarファイルの保存
Jenkinsのパイプライン機能を使って「アプリケーションのビルド」→「テストプロジェクトの実行」の順に実行します。
ここでアプリケーションの「ビルド後の処理」に成果物の保存処理を追加しました。
アプリケーションのビルドの成果物であるwarファイルを保存しておくことで、他のプロジェクトにコピーすることができるようになります。
以下の通りですね。
次は保存した成果物を結合テスト用プロジェクトにコピーします。
3. アプリケーション本体のwarファイルのコピー
結合テスト用プロジェクトに、先ほど作成・保存したwarファイルをコピーします。
今回はJenkinsプラグインの「Copy Artifact Plugin」を使います。当該プラグインは、Jenkinsの管理ページからインストールしました。
上記プラグインを追加すると、Jenkinsプロジェクト内での「前処理」に「他のプロジェクトから成果物をコピー」が追加されます。
これを使えば、warファイルのコピーが可能になります。
ちなみに今回は、「ディレクトリ構造を無視」というチェックボックスにチェックを入れておきます。
このチェックを入れないと、コピー時にディレクトリ構成までコピーされてしまい、想定と違う場所にwarファイルが置かれてしまうからです。
これでworkを指定すればwork直下にwarファイルが配置されます。
後はwarファイルを起動するだけですね。
4. アプリケーションの起動
warファイルを起動する方法はいくつかありますが、今回はMavenで簡単に起動できるjetty pluginを使います。
integration-testフェイズを利用し、pre-integration-testでJettyを起動し、post-integration-testでJettyを停止します。
※integration-testフェイズでテストを実施するのはsurfire-pluginを利用しました。
以下がテスト実行用のpom.xmlに追加した内容です。
<!-- Jettyの設定 --> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>8.1.14.v20131031</version> <configuration> <war>./work/restsample-1.0.0.war</war> <webApp> <contextPath>/restsample</contextPath> </webApp> </configuration> <executions> <!-- integration-test の 事前準備 (Jettyの起動) --> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>run-war</goal> </goals> <configuration> <scanIntervalSeconds>0</scanIntervalSeconds> <daemon>true</daemon> </configuration> </execution> <!-- integration-test の 事後処理 (Jettyの停止) --> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> <configuration> <stopKey>stop</stopKey> <stopPort>9999</stopPort> </configuration> </execution> </executions> </plugin> <!-- integration-testの実行 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- integration-test にて実行する --> <executions> <execution> <id>selenium-test</id> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> <configuration> <includes> <include>**/*Test*.java</include> </includes> </configuration> </execution> </executions> </plugin>
ところで、Jenkinsを8080番ポートで起動している場合は、Jettyを8080番ポートで起動すると、ポートが重複してしまってエラーになります。
というか、私自身、よくやってしまいます orz
JenkinsかJettyの利用するポートを変更する必要があります。
Jetty側のポートを変更するには、Jetty起動時のオプションに-Djetty.port=18080などをつけてください。その場合、結合テスト用のテストコードに記載しているURLも18080に変更する必要がある点に注意してください。
5. テストの実施
改めて実行してみたところ、Jenkinsのビルドには成功するものの、途中でテスト失敗のメッセージが出ていました。
結果ログをよく見ると、JUnitが3回起動していました。
どうやら上に書いた設定のままだと、Jetty起動前に2回JUnitが起動し、それがテスト失敗となっているようです。
Jetty起動前の試験は不要なので、スキップする設定を加えます。
<!-- integration-testの実行 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- integration-test にて実行する --> <executions> <execution> <id>selenium-test</id> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> <configuration> <includes> <include>**/*Test*.java</include> </includes> </configuration> </execution> <!-- ★追加設定 default-test, unit-test をSKIPする --> <execution> <id>default-test</id> <configuration> <skip>true</skip> </configuration> </execution> <execution> <id>unit-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> <configuration> <skip>true</skip> </configuration> <!-- ★追加設定終わり --> </execution> </executions> </plugin>
上記設定でもう一度ビルドすると、無事、JUnitは1回しか実施されず、JUnitのテスト成功のみ残りました。
あとはJenkinsが毎日自動で統合テストを実施してくれるので、安心感があります。
まとめ
2回に分けて紹介してきましたが、最後に簡単にまとめです。
- Restfuseを使うと検証に集中してテストケースが書ける!
- アプリケーション本体と統合テスト用のJenkinsプロジェクトを分けたほうが管理しやすかった!
- みんな大好き、Jenkins + Jettyの組み合わせは、やっぱり鉄板だった!
- 8080番ポートを重複させるのは、素人(><)。
- Jenkinsで自動試験を常に動かすと安心感ある!
そんなわけで、REST APIの自動試験が必要な時には、Restfuse + Jenkinsも試してみてください!
Acroquest Technologyでは、キャリア採用を行っています。
- 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
- 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
- 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
- OSSの開発に携わりたい。
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
キャリア採用ページ