最終的なディレクトリ構成
dockerコンテナ起動
詳細は割愛しますが、以下でコンテナ起動まで可能です。
git clone https://github.com/masayan1126/docker-phpunit.git
cd docker-phpunit
docker-compose up -d
以下のように表示されたら、コンテナ起動完了です。
Creating nginx ... done
Creating php ... done
composerインストール
以下の1.もしくは2.の方法でDockerでcomposerをインストールします。
今回は2.の方法をdocker\php\Dockerfileに記載しているので、ビルドの際にcomposerがインストールされます。
Composer 公式 のインストール方法
※ハッシュ値の部分はComposer はバージョンアップごとに変更されるので、都度Dockerfile も変更する必要があるため後述の2.の方法がおすすめです。
FROM php:7.3-fpm
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php \
&& php -r "unlink('composer-setup.php');" \
&& mv composer.phar /usr/local/bin/composer
マルチステージビルドでインストール(Docker 17.05以上)
Dockerのマルチステージビルドを活用すると、以下のように1行で書ける。
FROM php:7.3-fpm
COPY --from=composer /usr/bin/composer /usr/bin/composer
バージョン指定したい場合は以下のように指定できる(未指定なら最新版)
COPY --from=composer:1.8.6 /usr/bin/composer /usr/bin/composer
Dockerのmulti-stage buildsは17.05以降で利用できるビルド方法で、一つのDockerfileの中でビルド用イメージの作成とデプロイ用イメージを作成できます。ビルド用のイメージ中でプログラムをコンパイルし、実行ファイルだけをデプロイ用のイメージに取り込むことでデプロイ用のイメージサイズを減らすことができます。
コンテナが起動後、以下でコンテナ内に入ります。
docker-compose exec app bash
composer.jsonの作成
コンテナ内で以下を実行してcomposerで管理するプロジェクトを初期化します
root@eb351c5a0b16:/var/www# composer init
そうするとコマンドライン上でいろいろと確認されますが、
以下のパッケージ名の箇所はvendor/appで指定(特に指定はないので、任意の名称でOK)しています。
Package name (<vendor>/<name>) [root/www]: vendor/app
それ以外はデフォルトの設定で問題ないので、すべてEnter(もしくはnのこうもくも)を押します。そうすると、ルートディレクトリにcomposer.jsonとsrcディレクトリ、vendorディレクトリが作成されます
{
// パッケージ名
"name": "vendor/app",
"autoload": {
"psr-4": {
// srcディレクトは以下にある、名前空間がVendor\Appで指定されているクラスがオートロードの対象
"Vendor\\App\\": "src/"
}
},
"scripts": { "test": "vendor/bin/phpunit" },
"require-dev": {
"phpunit/phpunit": "^9.5"
}
}
psr4というコーディング規約を指定すると、以下のルールを守る必要があります。
- クラスファイルはnamespaceが必須。
- namespaceとディレクトリ構成、名称は一致させる。
- namespace名は大文字からはじめる。
phpunitをインストールしテストを実行する
phpunitをインストール
コンテナ内のcomposer.jsonのあるディレクトリで、以下を実行
root@eb351c5a0b16:/var/www# composer require --dev phpunit/phpunit
composer.jsonに以下のように追記されます。これで、開発用パッケージにphpunitを導入することができました。
"require-dev": {
"phpunit/phpunit": "^9.5"
}
phpunit.xmlの作成
vendorディレクトリと同じ階層にphpunit.xmlを作成し以下のように記載
※vendor/autoload.phpでは、マップファイル(クラスやネームスペースが定義されている配列が記述されたファイル)をrequireしています。(この場所のみrequireでの読み込みが必要)
<!-- テストの実行結果を着色する -->
<!-- テスト実行前に各ファイルをオートロード -->
<phpunit colors="true" bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Sample">
<!-- テスト用のクラスがあるディレクトリを指定 -->
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
PHPUnitでは複数のテストケースをテストスイートというグループ単位に分けることができ、定義したスイートごとにユニットテストを実行することが可能となります。また、ディレクトリの指定ではなく、以下のようにファイル単位で指定することも可能。
<testsuites>
・・・
<testsuite name="Sample">
<file>test/Sample1Test.php</file>
<file>test/Sample2Test.php</file>
</testsuite>
</testsuites>
テストケースの作成
testsディレクトリを作成し、その直下にGreetTest.phpというファイル名で簡単なテストケースを作成して実行してみます。
※メソッド名は test で始める必要がある
root@eb351c5a0b16:/var/www# mkdir tests
<?phpnamespace Vendor\App; use PHPUnit\Framework\TestCase;use Vendor\App\Greet;
class GreetTest extends TestCase
{
/**
* @test
*/
public function testMultiple()
{
$greet = new Greet();
$expected = "hello";
$this->assertEquals($expected, $greet->sayHello());
}
}
テスト対象のクラス(Greet.php)をsrcディレクトリ直下に作成する
<?php
namespace Vendor\App;
class Greet
{
public function sayHello()
{
return "hello";
}
}
テストを実行する
vendor/bin/phpunit tests
※毎回上記のコマンドを打つのは面倒なので、composer.jsonに以下のようにscriptとして登録すると、"composer test" と打つだけでテストが流れる
"scripts": {
"test": "vendor/bin/phpunit"
},
以下のようにテストが通っていればOK
root@eb351c5a0b16:/var/www# composer test
PHPUnit 9.5.8 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:00.168, Memory: 4.00 MB
OK (1 test, 1 assertion)
以上になります。
次回はこの環境を用いて、GitHub ActionsでCI/CDを構築してみたいと思います。
まとめ
いかがでしたでしょうか。本記事では、docker環境でcomposerをインストールしてphpunitを使用する手順について紹介しています。composer.jsonの基本的な設定方法からテストの実行方法まで最低限知っておく必要のある事項をベースに書いています。