"BOKU"のITな日常

62歳・文系システムエンジニアの”BOKU”は日々勉強を楽しんでます

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

PHPUnitをComposerでインストールして「phpunit」だけ打ち込んだらテストが実行されるようにするにはどうしたらよいのか?を整理してみました。

f:id:arakan_no_boku:20190922143447p:plain

 

はじめに

 

Laravel6.0をインストールして動作確認をしたときに「.\vendor\bin\phpunit」とうつだけでテストが実行できました。

流しておけばよいのですけど、性分として、どうも「仕組」というか、composerでインストールしたPHPUnitをどのように使えば、そんな感じにできるのか?・・が気になって仕方がありません。

ということで。

今回は素のPHPで、ComposerでインストールしたPHPUnitの使い方を確認することにしました(笑)

 

まず、適当なローカルプロジェクトを作る

 

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に教える

 

まず、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.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には欠かせないもので、実際Laravel6.0のドキュメントを見ても、そこら中で「名前空間」という単語がでてきます。

ここもちゃんと理解しておかないといけないな・・と思って、自分なりに整理してみたのですが、それについて書くと長くなりすぎるので、次回にします。 

 

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')
        );
    }
}

    

以上です。 

ではでは。