Calendarの23日目の記事です。昨日はtoradukaさんのJavaのクラスファイルをjavapとバイナリエディタで読むでした。明日はsmogamiさんです。Calendarの18日目の記事の予告通りMavenでまっさらなマスター/スレーブ構成のMySQLクラスタを構築し、そのデータベースに対して結合テストを実行する方法について解説します。サンプルのリポジトリはこちらです。Boot版作ってました。Springな方はこちらもぜひ参考にしてみてください!jcabi-mysql-maven-plugin今回のキモはこのjcabi-mysql-maven-pluginです。このプラグインはMavenリポジトリにアップロードされたMySQLをmaven-dependency-pluginでダウンロードして起動するプラグインです。対応している環境は、linux-amd64linux-x86mac-x86_64windows-amd64windows-x86と一般的な環境は揃っているようです。このようにclassifierを指定することでMavenの実行環境に合ったMySQLを自動的にダウンロードできます。<plugin><artifactId>maven-dependency-plugin</artifactId><version>2.8</version><executions><execution><phase>pre-integration-test</phase><goals><goal>unpack</goal></goals><configuration><artifactItems><artifactItem><groupId>com.jcabi</groupId><artifactId>mysql-dist</artifactId><version>5.6.14</version><classifier>${mysql.classifier}</classifier><type>zip</type><overWrite>false</overWrite><outputDirectory>${project.build.directory}/mysql-dist</outputDirectory></artifactItem></artifactItems></configuration></execution></executions></plugin>通常MySQLはポート3306で起動しますが、このプラグインはbuild-helper-maven-pluginで予めMySQLが使うポートを予約して使うことを推奨しています。<plugin><groupId>org.codehaus.mojo</groupId><artifactId>build-helper-maven-plugin</artifactId><version>1.8</version><executions><execution><goals><goal>reserve-network-port</goal></goals><configuration><portNames><portName>mysql.port</portName></portNames></configuration></execution></executions></plugin>こうすることでmvnコマンド実行時に開いているポートが予約され、<plugin><groupId>com.jcabi</groupId><artifactId>jcabi-mysql-maven-plugin</artifactId><version>0.9</version><executions><execution><id>mysql-test</id><goals><goal>classify</goal><goal>start</goal><goal>stop</goal></goals><configuration><port>${mysql.port}</port><data>${project.build.directory}/mysql-data</data></configuration></execution></executions></plugin>このように待ち受けるポートを指定します。テストなどで使用する場合は<plugin><artifactId>maven-failsafe-plugin</artifactId><version>2.16</version><executions><execution><goals><goal>integration-test</goal><goal>verify</goal></goals></execution></executions><configuration><systemPropertyVariables><javax.persistence.jdbc.url>jdbc:mysql:replication://localhost:${mysql.master.port},localhost:${mysql.slave.port}/it</javax.persistence.jdbc.url></systemPropertyVariables></configuration></plugin>このようにシステムプロパティで渡すか、プロパティファイルをMavenのリソース置換で書き換えて渡してもいいでしょう。このbuild-helper-maven-pluginのポート予約はMySQLにかぎらず結合テストで使うアプリケーションサーバーのポート予約などにも応用できます。ポートが使用中でテストが失敗、といったリスクが無くなるので活用しましょう。マスター/スレーブ構成にしてみよう起動させるbuild-helper-maven-pluginではマスター用とスレーブ用のポートを予約します。jcabi-mysql-maven-pluginはexecutionを増やし、こちらもマスター用とスレーブ用を定義します。マスター用<execution><id>mysql-master</id><goals><goal>classify</goal><goal>start</goal><goal>stop</goal></goals><configuration><port>${mysql.master.port}</port><data>${project.build.directory}/mysql-master</data><options><option>server-id=${mysql.master.port}</option><option>log-bin=mysql-bin</option></options></configuration></execution>スレーブ用<execution><id>mysql-slave</id><goals><goal>classify</goal><goal>start</goal><goal>stop</goal></goals><configuration><port>${mysql.slave.port}</port><data>${project.build.directory}/mysql-slave</data><options><option>server-id=${mysql.slave.port}</option><option>relay-log=mysql-relay-bin</option></options></configuration></execution>configuration/options/optionでMySQLの起動オプションを渡せます。server-idにはユニークな値を渡す必要があるので予約したポート番号を渡します。レプリケーションの設定としてマスターにはlog-bin=mysql-binを渡しスレーブ側にはrelay-log=mysql-relay-binを渡して起動させます。レプリケートさせるさて、MySQL5.5からは起動オプションでmaster-hostやmaster-user、master-passwordを指定してスレーブを起動することができなくなっています。masterを発行しなければなりません。masterを発行します。status;</sqlCommand></configuration></execution></plugin>dependenciesで利用するJDBCドライバを指定し、configurationでドライバのFQCNや接続するユーザー情報を指定します。slaveを実行することでレプリケーションを開始しています。jcabi-mysql-maven-pluginの罠これでおしまい、晴れてマスター/スレーブ構成のMySQLをMavenで起動できました。なればいいのですが、そうは問屋が卸さないようでして。実はjcabi-mysql-maven-pluginは起動時にご丁寧にも作成するデータベースに対して–binlog-ignore-dbオプションを付けて起動します。jcabi-mysql-maven-pluginが用意してくれるデータベースはbinlogが出力されずレプリケーションができません。そのためデータベースの作成も独自に行います。databaseを発行します。it</sqlCommand></configuration></execution></executions></plugin>これで無事itというレプリケーションされるデータベースが作成されました。あとはこちらのエントリの通り煮るなり焼くなり好きにマスター/スレーブ構成のMySQLを弄くり倒せます。まとめいかがでしたでしょうか。いちいちMavenでMySQLとか起動せずに別サーバーにMySQLを起動しておいてそれ使えばいいじゃない、という方も多いかもしれませんが私は極力どのようなテストにおいてもMySQLをはじめとしたミドルウェア込みのテスト環境を提供できるプロジェクトのポータビリティを重視しています。(Arquillianの結合テストも基本的にEmbedded派です)Mavenだけでどのような環境でもすぐにテストを実行できると、開発チームへ新たにメンバーが追加された際などにいちいち接続用アカウントの作成やデータベースの作成、テストデータの流し込みなどといった煩雑な作業をすることがなくなり、やれアカウントが分かりませんやら、テストデータが足りないといった対応などのストレスから開放されることがとても大きいと感じています。ミドルウェアのログファイルもローカルで読み込めるので、MySQLで言えば正しくインデックスが使われているか、クエリの内容は問題ないかなどの確認やテストを行うこともできます。統合的に”固い”テストを行う方法の一つとしてこういったアプローチもぜひ頭の片隅に入れておいてください。言え、ぶっちゃけプラグインをこねくり回さずに、maven-docker-pluginとかを使ってDockerでMySQLクラスタを用意してMaven実行時に環境構築して使う今風ベストプラクティスなんじゃないでしょうか。コメントをキャンセルメールアドレスが公開されることはありません。