0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPUnit で標準入力のテストをしたい(STDIN を使った関数のテスト・サンプル)

Last updated at Posted at 2020-04-26

標準入力を取得するユーザー関数やメソッドを作りたい場合のテストをしたい。

問題の関数
function getContentsFromStdin()
{
    $contents = \file_get_contents('php://stdin');

    if ($contents === false) {
        throw new \RuntimeException('Failed to read contents from STDIN.');
    }

    return $contents;
}

ここ1年以内に作成 or 更新された Qiita 記事で「phpunit 標準入力 テスト」に絞ってググっても、ピンポイントに欲しい記事がなかったので自分のググラビリティとして。

TL; DR

php ストリーム にラッパーを登録し、php://STDIN にテストデータを書き込んでテストする。

TS; DR

テストしたい対象の関数

<?php
declare(strict_types=1);

namespace KEINOS\Sample;

function getContentsFromStdin()
{
    $contents = \file_get_contents('php://stdin');
    if ($contents === false) {
        throw new \RuntimeException('Failed to read contents from STDIN.');
    }

    return $contents;
}

テストの内容

getContentsFromStdinFunctionTest.php
<?php
declare(strict_types=1);

namespace KEINOS\Tests;

final class FunctionGetContentsFromStdinTest extends \PHPUnit\Framework\TestCase
{
    public function testRegularInput()
    {
        $result_expect = 'World!';

        // ラッパー "MockPhpStream" を "php://" ストリームに登録する
        $existed = in_array('php', \stream_get_wrappers());
        if ($existed) {
            \stream_wrapper_unregister("php");
        }
        \stream_wrapper_register("php", '\\KEINOS\Tests\MockPhpStream');

        // "STDIN" にデータを書き込む
        \file_put_contents('php://stdin', $result_expect);

        // テストしたい関数(getContentsFromStdin())からデータを取得
        $result_actual = \KEINOS\Sample\getContentsFromStdin();

        // ラッパーの解放
        \stream_wrapper_restore("php");

        // アサーションの実行
        $this->assertSame($result_expect, $result_actual);
    }
}

テストに使うラッパー・スクリプト "MockPhpStream"

MockPhpStream.php
<?php
declare(strict_types=1);

namespace KEINOS\Tests;

/**
 * REF: http://news-from-the-basement.blogspot.com/2011/07/mocking-phpinput.html
 */
class MockPhpStream
{
    protected $index  = 0;
    protected $length = null;
    protected $data   = 'hello world';

    public $context;

    public function __construct()
    {
        if (file_exists($this->buffer_filename())) {
            $this->data = file_get_contents($this->buffer_filename());
        } else {
            $this->data = '';
        }
        $this->index  = 0;
        $this->length = strlen($this->data);
    }

    protected function buffer_filename()
    {
        return sys_get_temp_dir(). DIRECTORY_SEPARATOR . 'php_input.txt';
    }

    public function stream_open($path, $mode, $options, &$opened_path)
    {
        return true;
    }

    public function stream_close()
    {
    }

    public function stream_stat()
    {
        return array();
    }

    public function stream_flush()
    {
        return true;
    }

    public function stream_read($count)
    {
        if (is_null($this->length) === true) {
            $this->length = strlen($this->data);
        }
        $length = min($count, $this->length - $this->index);
        $data = substr($this->data, $this->index);
        $this->index = $this->index + $length;

        return $data;
    }

    public function stream_eof()
    {
        return ($this->index >= $this->length ? true : false);
    }

    public function stream_write($data)
    {
        return file_put_contents($this->buffer_filename(), $data);
    }

    public function unlink()
    {
        if (file_exists($this->buffer_filename())) {
            unlink($this->buffer_filename());
        }
        $this->data   = '';
        $this->index  = 0;
        $this->length = 0;
    }
}

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?