環境を切り分けたテストがしたい時がある。
具体例を出すと、PHPにはmemcachedのエクステンションとしてMemcacheとMemcachedの2つがある。
PHPer以外には冗談みたいな話であるが、本当である。
そして、その2つの環境に対応したパッケージのテストをする場合、2つのエクステンションが個々に入った環境を作らなくてはならないので面倒くさい。
面倒くさい事はciにお任せしたいと思ったのでtravis-ciで環境を切り分けたテスト方法を調べて実行してみた。
同名env
travis-ciはバージョンごとにテストを実行してくれるのはよく知られていると思うが、
同名の環境変数ごとにもテストを実行してくれる。
つまり
php:
- 5.6
- 7.0
- hhvm
- nightly
env:
- EXT=none
- EXT=memcache
- EXT=memcached
だと、バージョン(3つ)×同名環境変数(3つ)で9個のテストが実行される。
あとは、環境変数を使用して環境を作るだけ。
環境変数を使用した環境切り分け
シェルのifで環境変数を見て実行するコマンドを切り分ける
before_install:
- if [[ $EXT = memcache ]]; then echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
- if [[ $EXT = memcached ]]; then echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
上記は$EXT
が
- memcacheであれば、Memcacheのエクステンションを有効にする
- memcachedであれば、Memcachedのエクステンションを有効にする
という処理を行っている
これで環境構築はできた。
テストしたくない環境を除外
PHP7はMemcacheエクステンションには対応していないのでMemcacheエクステンションを使用したテストでは実行時に
Error: Class 'Memcache' not found
と、エラーが出てしまう。
これはパッケージを作った側にはどうしようもないので、PHP7×Memcacheのテストは実行しないようにしたい。
こういう時はmatrixを使う。
matrix:
exclude:
- php: 7.0
env: EXT=memcache
- php: nightly
env: EXT=memcache
上記は
- バージョンが7.0で
$EXT
がmemcacheのテストを除外する - バージョンがnightlyで
$EXT
がmemcacheのテストを除外する(nightlyも7.0なので)
という処理になる。
matrixのexcludeに除外したい組み合わせを指定するとその組み合わせのテストを実行しないようにしてくれる。
excludeとは逆にincludeの設定もあって、例えば5.6だけMemcacheとMemcachedのテストがしたい場合は
php:
- 5.6
- 7.0
- hhvm
- nightly
env:
- EXT=none
matrix:
include:
- php: 5.6
env: EXT=memcache
- php: 5.6
env: EXT=memcached
となる。
参考:Customizing the Build #Build Matrix
まとめ
- 基本は同名envを設定してenvごとに環境設定を行う
- 実行したくないテストはmatrixのexcludeで除外
PHP以外にも環境を変えたテストを行いたい事はあると思うので覚えておくと楽かも。
おまけ
この記事のタイトルとは直接関係無いが、
MemcacheとMemcachedに対応させたテストをtravis-ciで実行するときに重要なポイントがあったので記しておく。
phpunitのグループ機能
PHPはphpunitでテストを実行するのだが、
今回の場合、Memcache用とMemcached用のテストを用意して環境別に実行したかった。
なのでphpunitのグループ機能を活用することにした。
/**
* @group memcache
*/
public function testMemcache()
{
// ...
}
/**
* @group memcached
*/
public function testMemcached()
{
// ...
}
上記のようにgroupアノテーションをつけて
$ vendor/bin/phpunit --group memcache
のように実行すればmemcacheグループであるtestMemcache()
だけが実行される。
travis-ciで実行する場合はコマンドを環境変数によって切り分ける
script:
- if [[ $EXT = none ]]; then vendor/bin/phpunit --group none; fi
- if [[ $EXT = memcache ]]; then vendor/bin/phpunit --group memcache; fi
- if [[ $EXT = memcached ]]; then vendor/bin/phpunit --group memcached; fi
あるいは、グループ名と環境変数の中身が同じならば
script:
- vendor/bin/phpunit --group $EXT
でも良いかもしれない。
HHVMのMemcacheエクステンションとMemcachedエクステンション
HHVMの事はあまり詳しくないのだが、HHVMには最初からMemcacheエクステンションとMemcachedエクステンションが入っているようだった。
逆にHHVMで
before_install:
- if [[ $EXT = memcache ]]; then echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
とエクステンションを有効にしようとすると、
/home/travis/build.sh: line 45: /home/travis/.phpenv/versions/hhvm/etc/php.ini: No such file or directory
のようにphp.ini
が無いとエラーが出る。
なので、HHVMではエクステンションの有効化をしないようにした。
before_install:
- if [[ $EXT = memcache && $TRAVIS_PHP_VERSION != hhvm ]]; then echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
- if [[ $EXT = memcached && $TRAVIS_PHP_VERSION != hhvm ]]; then echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi