PHPUnit require_once地獄からの脱出 1 まずはrequire_onceでテスト元のファイルをどう読み込むか編

前回、PHPUnit require_once地獄から脱出したい!という理由で、autoloadについて紹介しました。

まぁ、まだあわてるような時間じゃない。( ˊᵕˋ )  本題のPHPUnitで使うのがどうやるかって話をゆっくりとしていきます。

ということで、そもそもPHPUnitというかPHPでのファイル読み込みがどうなっているかを書いておきたいと思います。

require_once地獄は、結局はファイルが思うように読み込みできずに 次のエラーが出てしまう地獄です。

Warning: require_once(class/Monkey.php): failed to open stream: No such file or directory in...

なぜこうなってしまうのかをサンプルを使って紐といていきます。

というわけで、まずは、前回の「PHP require_onceを使わない、 autoloadを使ってクラスを読み込む方法」で使ったのと同じサンプルを使います。

下記に、tests/MonkeyTest.phpというディレクトリとphpファイルを置きました。

MonkeyTest.phpの中身は下記の通り。

<?php

use PHPUnit\Framework\TestCase;

require_once "../class/Monkey.php";

class MonkeyTest extends TestCase
{

    public function testScream()
    {
        $monkey = new Monkey();
        ob_start();
        $monkey->scream();
        $actual = ob_get_clean();
        $expected = 'ウキー!!!';
        $this->assertEquals($expected, $actual);
    }
}

require_once “../class/Monkey.php”;

にご注目ください。MonkeyTest.phpから見て、テスト元のファイルである、Monkey.phpを相対パスで指定しています。

テスト元のファイル、Monkey.phpは次の通りです。

<?php
namespace MonkeyWorld;

class Monkey
{

    public function scream(){
        echo "ウキー!!!";
    }
}

で、Webサーバーにインストール済みのPHPUnitを走らせます。
PHPStormのPHPUnitを走らせる設定は、下記の場所にあります。 
ファイル→Settings→Languages&Frameworks→PHP→Test Frameworks

ここでは、私はWindows10でXamppを使って開発してますんで、ここにすでにインストールしてあったphpunitのpharファイルを使います。

D:\xampp\php\phpunit.phar

pharファイルとは、かみ砕いていうと、Windowsで言うexeファイルみたいなものです。これを実行するとPHPUnitが実行できるというわけです。

PHPStormからは、下記の赤丸の部分にある、再生みたいな緑の三角のボタンをクリックで、テストがメソッド単位で実行できます。(PHPStorm使ってないよ!という方は後でコマンドプロンプトからやる方法書いてますので、スルーしてください。)

クリックすると下記のような画面が開いて、MonkeyTest.testScream の実行の設定をしてください、と出ます。

Interpreterとは、PHPの実行環境です。

ここではサンプルなので、次のように指定しておきます。

Use alternative configuration fileを指定しないと、
Error:Path to conficuration file should be specified in … というエラーが出てダメだったので、図の下にあるように、phpunit.xmlを適当に作ります。

下記がphpunit.xmlです。ちなみに、このファイルはPHPUnitをどう実行するかを決めるとても大切なファイルです。あとでちゃんとやりますが、ここではもうこれ以上設定をなくせないぐらいのミニマムな設定で、とりあえずおいておきます。

<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
</phpunit>

phpunit.xmlはディレクトリのトップにおきます。

やっと、MonkeyTestのtestScream()を実行することができます!

(;゚∀゚)=3ハァハァ、ここまで長かった…。

Shift+F10でテストが実行できます。

すると、残念!

Warning: require_once(../class/Monkey.php): failed to open stream: No such file or directory in D:\xampp\htdocs\autoloadSample\tests\MonkeyTest.php on line 7
Call Stack:
0.0087 898656 1. {main}() D:\xampp\php\phpunit.phar:0
0.0965 10543104 2. PHPUnit\TextUI\Command::main() D:\xampp\php\phpunit.phar:660
0.0965 10551968 3. PHPUnit\TextUI\Command->run() phar://D:/xampp/php/phpunit.phar/phpunit/TextUI/Command.php:69
0.0986 10557432 4. PHPUnit\TextUI\TestRunner->getTest() phar://D:/xampp/php/phpunit.phar/phpunit/TextUI/Command.php:81
0.0992 10595224 5. PHPUnit\Framework\TestSuite->addTestFiles() phar://D:/xampp/php/phpunit.phar/phpunit/Runner/BaseTestRunner.php:81
0.0992 10595224 6. PHPUnit\Framework\TestSuite->addTestFile() phar://D:/xampp/php/phpunit.phar/phpunit/Framework/TestSuite.php:340
0.0992 10595224 7. PHPUnit\Util\FileLoader::checkAndLoad() phar://D:/xampp/php/phpunit.phar/phpunit/Framework/TestSuite.php:267
0.0992 10595432 8. PHPUnit\Util\FileLoader::load() phar://D:/xampp/php/phpunit.phar/phpunit/Util/FileLoader.php:40
0.0994 10623056 9. include_once('D:\xampp\htdocs\autoloadSample\tests\MonkeyTest.php') phar://D:/xampp/php/phpunit.phar/phpunit/Util/FileLoader.php:49

上記のようなエラーが出て、../class/Monkey.php が読み込めませんでした、と出ますね。

これは、コマンドプロンプトでPHPUnitを次のように走らせた場合と同じです。

D:\xampp\htdocs\autoloadSample>phpunit testScream tests/MonkeyTest.php

( テストをメソッド単位で走らせるには、メソッド名をファイル名の前に置きます。)

つまり、PHPUnitはプロジェクトのトップ(ここではD:\xampp\htdocs\autoloadSample)で実行されているので、MonkeyTest.phpで指定するテスト元のファイルの指定は一番最初に実行されるので、Monkey.phpの読み込み指定は、プロジェクトのトップから行わないといけないわけですね。

それでは、次のようにMonkeyTest.phpを変更します。


<?php

use PHPUnit\Framework\TestCase;

require_once "class/Monkey.php"; //書き換え

class MonkeyTest extends TestCase
{

    public function testScream()
    {
        $monkey = new Monkey();
        ob_start();
        $monkey->scream();
        $actual = ob_get_clean();
        $expected = 'ウキー!!!';
        $this->assertEquals($expected, $actual);
    }
}

Shift + F10で実行します。


Testing started at 12:37 …
D:\xampp\php\php.exe D:\xampp\php\phpunit.phar --configuration D:\xampp\htdocs\autoloadSample\phpunit.xml --filter "/(MonkeyTest::testScream)( .*)?$/" --test-suffix MonkeyTest.php D:\xampp\htdocs\autoloadSample\tests --teamcity
PHPUnit 8.5.8 by Sebastian Bergmann and contributors.
Error : Class 'Monkey' not found
D:\xampp\htdocs\autoloadSample\tests\MonkeyTest.php:12
Time: 98 ms, Memory: 12.00 MB
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
Process finished with exit code 2

エラーですね…。

「結局、Class ‘Monkey’ not found って出ますけど!なんなんですか!!!」

まぁまぁ、まだあわてるような時間じゃないって冒頭に言いましたね。( ˊᵕˋ )

テスト元のファイル、Monkey.phpをよく見てみると

<?php
namespace MonkeyWorld;

class Monkey
{

    public function scream(){
        echo "ウキー!!!";
    }
}
namespace MonkeyWorld;

ってなってるんですよね。前回の投稿、PHP require_onceを使わない、 autoloadを使ってクラスを読み込む方法 で、MonkeyクラスはMonkeyWorldというnamespaceの中のクラスになっていたのでした。

というわけで、次のようにMonkeyTest.phpを書き換えます。

<?php

use MonkeyWorld\Monkey; //追加
use PHPUnit\Framework\TestCase;

require_once "class/Monkey.php";

class MonkeyTest extends TestCase
{

    public function testScream()
    {
        $monkey = new Monkey();
        ob_start();
        $monkey->scream();
        $actual = ob_get_clean();
        $expected = 'ウキー!!!';
        $this->assertEquals($expected, $actual);
    }
}

Shift+F10で実行します。

Time: 97 ms, Memory: 12.00 MB
OK (1 test, 1 assertion)
Process finished with exit code 0

となって、やっとOKが出ました!⊂(^-^)⊃

コマンドプロンプトからも実行します。

OKです!!

しかし、上記は上記のようにやって事なきを得ましたが、実際は例えばクラスからほかのクラスを読み込んだり、実際に動作するプログラムでの実行時に読み込まれるファイルがいっぱいあったりして、それらをrequire_onceでファイルパスを考えてどうにかするのはかなり大変なのです。

そこで、autoloadが活躍します。が、長くなったので続きます…。

間違いなどありましたら、お気軽にご指摘ください。

秋の山って気持ちいいですね!

次回はこちら↓

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です