2016/10/18 21:06:36

DockerでPHPのテスト環境を構築 PHPUnitコンテナをがんばって使ってみる

dokcer
目次(クリックするとジャンプします)
  • 1:PHPでテストするのもDockerで楽になるね
  • 2:Docker導入は計画的に
  • 3:PHPunitコンテナを使う
  • 3.1:手順1
  • 3.2:手順2
  • 3.3:手順3
  • 3.4:テスト結果
  • 4:補足・ハマりポイント
  • 4.1:説明の通りだと動かないぞ?
  • 4.2:composerが使えるよ
  • 4.3:PHP7環境です
  • 4.4:カレントディレクトリが面倒な場合は
  • 4.5:コンテナがいっぱいできちゃうから
  • 5:まとめ

PHPでテストするのもDockerで楽になるね

dockerサマサマやで。

いろいろプログラミングを覚えてきた中で、テストの重要性に気がついてきたのです。その経緯は別の記事で書くとして、今回はPHPでのユニットテスト(単体テスト)でよく使われていると噂のPHPunitを、イケメンと噂のDocker上で使ってみました。

Dockerを使うことでテスト環境を開発環境と別に用意することが可能になるので、ホストをなるべく汚さずに導入ができます。

テストに限らずですが、Dockerの利用範囲とその恩恵はなかなかsugoiものがありますな〜。

Docker導入は計画的に

Dockerの導入については、以下の記事等を参照してください。

docker公式のインストールガイド(英語)

以下のurlから左側のメニュー→Docker Engine →install→各OSの説明 Mac、WindowはもちろんLinuxは主要ディストリビューションのほとんどのインストール方法解説を網羅しています。英語ドキュメントですが簡単です。@MINOのTOEIC200点並の英語力でも読めたくらいなの。

docker日本語マニュアルプロジェクト

以下のurlから左側のメニュー→Docker Engine →インストール こちらは有志の方が英語ドキュメントを日本語訳してくれているプロジェクトです。こちらもMac、Window、Linuxの主要ディストリビューションのインストール方法解説があります。

PHPunitコンテナを使う

以下はDockerの導入および、DockerHubの登録が済んでいる前提で進めていきます。 またコマンドはdockerグループにユーザを登録済みとしています(つまりsudo不要状態)。

PHPUnitのdocker用imageが置いてあるdockerHub上のurlは以下です。PHPUnit開発者謹製のようです。

phpunit/phpunit

PHPUnitの導入は以下のように説明されています。@MINOのTOEIC200点並の英語力で翻訳してみたの。

手順1

1.Install the phpunit/phpunit container:

phpunit/phpunitコンテナをインストールしてください。
$ docker pull phpunit/phpunit

この段階ではコンテナの元になるimageをpull(ローカルにダウンロード)しています。バージョンを指定していない場合、自動的に「: latest」(最新バージョンを意味する)が付与され最新バージョンのimageがpullされますデス。

普通に使うには最新をもってくることで問題ないと思うのだけど、もし最新バージョン以外を使いたいということだったら、明示的にバージョンを指定する必要があります。例えば5.0.4を使いたいなら

$ docker pull phpunit/phpunit:5.0.4

としてpullすればOKデス。

手順2

2.Create a phpunit.xml defining your tests suites.

あなたのテスト群を定義するphpunit.xmlを作ってください。

Dockerコンテナに限らずですが、PHPUnitはテスト対象になるディレクトリ(フォルダ)にphpunit.xmlが入っているとそれを元にテストを始めてくれます。対象のファイルやディレクトリをphpunit.xmlに定義しましょう。

phpunit.xmlの書き方については公式ドキュメントの記事などを参考にしてください。

XML 設定ファイルを用いたテストスイートの構成

手順3

※@MINOの環境ではこの説明どおりでは動きませんでした。次の章でつまずいたポイントを説明しています。

3.Run PHPUnit through the PHPUnit container:

PHPUnitコンテナを介しテストします。
$ docker run -v $(pwd):/app phpunit/phpunit run

コマンドの意味は以下のようになります。

コマンド 意味
docker run コンテナを作成し起動
-v ボリュームをマウントするよ。
$(pwd):/app $(pwd)で指定したディレクトリが/appにマウントされます
phpunit/phpunit イメージ名
run なんだろこれ?つまずいたところなので後述します

テスト結果

コマンドが成功すると、指定したとおりに、テストが行われテスト結果が標準出力にでます。


PHPUnit 5.1.2 by Sebastian Bergmann and contributors.

ES                                                                  2 / 2 (100%)

Time: 104 ms, Memory: 3.25Mb

There was 1 error:

1) DbTest::testCheckplaceHolder
PDOException: could not find driver

/app/classes/Db.php:18
/app/test/DbTest.php:9

FAILURES!
Tests: 1, Assertions: 0, Errors: 1, Skipped: 1.

ぎゃーテストに受かってない!!(PDOエクステンションが無いから)

補足・ハマりポイント

説明の通りだと動かないぞ?

$ docker run -v $(pwd):/app phpunit/phpunit run

と説明されているのだけれど、このままだと最後の「run」がファイルとして認識されるようで(つまりrun.phpとして認識される)テストが起動しない。このrunってなんのrunなんだ?もしかして例文なの?

一応以下のようにして、明示的にxmlを指定してあげれば@MINOの環境では動きました。

$ docker run -v $(pwd):/app phpunit/phpunit --configuration phpunit.xml

もしくはマウントしたディレクトリを指定しちゃう。これでも動いた。

$ docker run -v $(pwd):/app phpunit/phpunit /app

一応動くし、用は果たすので問題はないのだけど、説明どおりにいかないってことはなにかまちがっているのかな?でも手順も少ないし間違えそうなところってどこだろ?

知っている人教えてください。

composerが使えるよ

今回のphpunitは「composer/composer」をベースimageに使用しています。そのためcomposerの機能を活用することが可能です。もちろんautoloadができます。便利でんな〜。

PHP7環境です

最新版のコンテナはphp7環境での稼働なので、もし5.6環境でテストを行いたいなら、composer/composer:5.6を使うべく、Dockerfileを書き換えるのが早いかもしれま10。ただPHPUnitのバージョンとPHPのバージョンの依存性は@MINOには到底わかんねっす。

カレントディレクトリが面倒な場合は

必ずしも$(pwd)と書かなクてはいけないわけではありません。コンテナをrunstartした時のカレントディレクトリにphpunit.xmlが置いてないならテストが起動しないので、開発環境によってはphpunit.xmlhがある場所にいる必要があるのが逆に面倒な場合もあるかもしれません。

以下のような感じでphpunit.xmlを置いてあるディレクトリを絶対パスや相対パスで指定でも大丈夫ですyo。

$ docker run -v /home/user/project/test:/app phpunit/phpunit run

コンテナがいっぱいできちゃうから

@MINOはDockerコマンドに誤解をしていました。runは「コンテナを起動させる」コマンドだと思っていたのだけど、正確には「コンテナを作って起動する」コマンドです。

なので、runを連発しているとコンテナがボッコボッコできます。あとでまとめて消すこともできるけど、今回のケースでは永続的なコンテナである必要はないから、一回一回消えてくれても便利かもしれないです。

run毎にコンテナを消すには名前を以下のようなオプションを付けます。(一応公式の通り最後はrunとしていますが、動かないなら明示的にディレクトリ、xml指定してみてください)

$ docker run -v $(pwd):/app --rm phpunit/phpunit run
コマンド 意味
–rm 起動後、処理が終わったらコンテナ消すオプション

これでコンテナ無駄に増えません。

まとめ

意外と簡単にテスト環境がそろっちゃった…。Dockerおそるべし。

ただ今回の例はかなりプリミティブな状態なので、実質的にはエクステンションの導入とかDBUnitとかデータベースとの連携とかは必要になってくると思います。

それらは別な記事にて書きます。