"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

ComposerでインストールしたPHPUnitを素のPHPで使う方法/Windows10

f:id:arakan_no_boku:20190922143447p:plain

目次

ComposerでインストールしたPHPUnitを素のPHPで使う

PHPUnitをComposerでインストールして「phpunit」を素のPHPで使います。

動作確認のための、PHPのプロジェクトの名前は「prac」にします。

とりあえず、「prac」フォルダを作って、下に「src」と「tests」の2つのサブフォルダを作りました。  

PHPUnitをインストール

PHPUnitを「composer」でインストールします。

phpunit.de

テストツールは、グローバルにインストールするのはNGです。

pracフォルダをカレントフォルダにした状態で、CMDから以下を実行します。

composer require --dev phpunit/phpunit ^8

PHPUnitは最新版の「8」を選びました。

--dev はデフォルト動作なので、明示的につけなくてもよいのでは?・・と思ったのですが、いちおう、サイトにそう書いてあるので、そのままにしてます。

f:id:arakan_no_boku:20190922234325p:plain

実際、カレントフォルダに「vender」フォルダができて、その中にモジュールがダウンロードされています。

PHPUnitの設定

PHPUnitをComposerでインストールした場合は、composer.jsonで、テスト対象のソースコードがあるフォルダを教えてやる必要があります。

Pracフォルダの構成は以下のようにしました。

  • src : プログラムソース(クラス)の置き場所
  • tests : テストプログラムの置き場
PHPUnitの設定:テスト対象のソースの置き場所をPHPUnitに教える

まず、srcフォルダがテスト対象のクラスが置いてある場所であるということを、PHPUnitに教える必要があります。

composer.json に、autoloadというセクションを以下のように追加します。

{
    "autoload": {
        "classmap": [
            "src/"
        ]
    },
    "require-dev": {
        "mockery/mockery": "^1.2",
        "phpunit/phpunit": "8"
    }
}

これをcomposer.jsonに保存して、以下を実行します。

composer dump-autoload

こうすることで、autoload.phpに反映するので、PHPUnitがテスト対象のクラスを探せるようになります。

PHPUnitの設定:テストが置いてあるフォルダをPHPUnitに教える

今度は「テストフォルダ」をPHPUnitに教えてやります。

以下を「phpunit.xml.dist」という名前で、pracフォルダ直下に作ります。

phpunit.xml.dist

<?xml version="1.0" encoding="utf-8" ?>
<phpunit bootstrap="./vendor/autoload.php">

    <testsuites>
        <testsuite name="My Project - TestSuite">
            <directory>./tests</directory>
        </testsuite>
    </testsuites>

</phpunit>

これを保存したら、PHPUnitはテストソースとテスト対象のクラスの両方を探せるようになるということです。

PHPUnitサンプルテストの実行

サンプルのテストを作ってやってみます。

サンプルソースは、以下のPHPUnit8のページにあるものをそのまま使います。

phpunit.de

上記のサイトからコピーします。(一応、本記事の末尾にも引用しておきます)

なお。

このソースは規約チェックツールにかけると、名前空間(namespace)が定義されてないという警告になりますが、テストの実行はできるので無視しておきます。

さて、srcフォルダと、testsフォルダにサンプルソースが保存できたら、あとは pracフォルダをカレントフォルダにしたCMD上で

.\vendor\bin\phpunit

とたたいて、実行します。 

f:id:arakan_no_boku:20190923170130p:plain

おーー。

動きました。

なるほど、Laravelとかだと、こういう設定が(もちろん、もっと複雑な設定になっていましたけど)プロジェクトにあわせて自動的にされているということなんだな・・ということが理解できました。

なお、上記で名前空間の警告がでてきます。

名前空間はモダンPHPには欠かせないものですが、その説明は別記事にまとめてます。

arakan-pgm-ai.hatenablog.com

PHPUnitの動作確認につかったサンプルです

テスト対象のプログラムです。 

src/Email.php

<?php
declare(strict_types=1);

final class Email
{
    private $email;

    private function __construct(string $email)
    {
        $this->ensureIsValidEmail($email);

        $this->email = $email;
    }

    public static function fromString(string $email): self
    {
        return new self($email);
    }

    public function __toString(): string
    {
        return $this->email;
    }

    private function ensureIsValidEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                sprintf(
                    '"%s" is not a valid email address',
                    $email
                )
            );
        }
    }
}

テストプログラムです。 

tests/EmailTest.php

<?php
declare(strict_types=1);

use PHPUnit\Framework\TestCase;

final class EmailTest extends TestCase
{
    public function testCanBeCreatedFromValidEmailAddress(): void
    {
        $this->assertInstanceOf(
            Email::class,
            Email::fromString('user@example.com')
        );
    }

    public function testCannotBeCreatedFromInvalidEmailAddress(): void
    {
        $this->expectException(InvalidArgumentException::class);

        Email::fromString('invalid');
    }

    public function testCanBeUsedAsString(): void
    {
        $this->assertEquals(
            'user@example.com',
            Email::fromString('user@example.com')
        );
    }
}

    

以上です。 

ではでは。