PHPで標準入出力をテストする(改め)


目的

PHPで標準入出力をテストする
https://qiita.com/AraiKotaro/items/1280c40ad797931397bd
以前に書いた記事にコメントを頂きましたので、
改めてPHPでの標準入出力について模索してみました。

環境

macOS Mojave 10.14.2

$php --version
PHP 7.3.0 (cli) (built: Dec 16 2018 21:44:57) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.0, Copyright (c) 1999-2018, by Zend Technologies

PHPUnit環境作成(Composer)

Composerのインストール

公式サイトからダウンロードしインストールする手順

以前の記事ではdockerを使用しましたが、
今回はComposerでPHPUnitをインストールしました。

https://getcomposer.org/download/
にインストールコマンド例が載っています。
ここに記載されているコマンド例には、composerのインストールファイルのシグネチャの検査がハードコーディングされており、
このQiitaのように公開する記事に記載するには不向きです。

https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md
を参考にして、シグネチャをその場で取得して検査する方法を記載します。

install_composer.sh
#!/bin/sh

EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
then
    >&2 echo 'ERROR: Invalid installer signature'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT

このようなシェルを用意し実行することで、
composer.pharを作成できます。

homebrewからインストール

頂いたコメントで知りましたが、homebrewからインストールできました。

$brew install composer
$composer --version
Composer version 1.8.0 2018-12-03 10:31:16

指摘を頂く前は公式サイトからダウンロードしたcomposerをわざわざhomebrewの管轄下に移動する、
ちぐはぐな手順を記載してしまっていました。

PHPUnitのインストール

https://phpunit.de/getting-started/phpunit-7.html
を参考に

$cd ~
$cd phpunit
$composer require --dev phpunit/phpunit ^7
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 27 installs, 0 updates, 0 removals
  - Installing sebastian/version (2.0.1): Downloading (100%)         
  - Installing sebastian/resource-operations (2.0.1): Downloading (100%)         
  - Installing sebastian/recursion-context (3.0.0): Downloading (100%)         
  - Installing sebastian/object-reflector (1.1.1): Downloading (100%)         
  - Installing sebastian/object-enumerator (3.0.3): Downloading (100%)         
  - Installing sebastian/global-state (2.0.0): Downloading (100%)         
  - Installing sebastian/exporter (3.1.0): Downloading (100%)         
  - Installing sebastian/environment (4.0.1): Downloading (100%)         
  - Installing sebastian/diff (3.0.1): Downloading (100%)         
  - Installing sebastian/comparator (3.0.2): Downloading (100%)         
  - Installing phpunit/php-timer (2.0.0): Downloading (100%)         
  - Installing phpunit/php-text-template (1.2.1): Downloading (100%)         
  - Installing phpunit/php-file-iterator (2.0.2): Downloading (100%)         
  - Installing theseer/tokenizer (1.1.0): Downloading (100%)         
  - Installing sebastian/code-unit-reverse-lookup (1.0.1): Downloading (100%)         
  - Installing phpunit/php-token-stream (3.0.1): Downloading (100%)         
  - Installing phpunit/php-code-coverage (6.1.4): Downloading (100%)         
  - Installing doctrine/instantiator (1.1.0): Downloading (100%)         
  - Installing webmozart/assert (1.3.0): Downloading (100%)         
  - Installing phpdocumentor/reflection-common (1.0.1): Downloading (100%)         
  - Installing phpdocumentor/type-resolver (0.4.0): Downloading (100%)         
  - Installing phpdocumentor/reflection-docblock (4.3.0): Downloading (100%)         
  - Installing phpspec/prophecy (1.8.0): Downloading (100%)         
  - Installing phar-io/version (2.0.1): Downloading (100%)         
  - Installing phar-io/manifest (1.0.3): Downloading (100%)         
  - Installing myclabs/deep-copy (1.8.1): Downloading (100%)         
  - Installing phpunit/phpunit (7.5.1): Downloading (100%)         
sebastian/global-state suggests installing ext-uopz (*)
phpunit/php-code-coverage suggests installing ext-xdebug (^2.6.0)
phpunit/phpunit suggests installing phpunit/php-invoker (^2.0)
phpunit/phpunit suggests installing ext-xdebug (*)
Writing lock file
Generating autoload files

以前はcomposerのbinディレクトリにインストールする手順を記載していましたが、
頂いたコメントを受けまして、
https://phpunit.de/getting-started/phpunit-7.html
の記載通りにプロジェクトのディレクトリに配置するように修正しました。

テストコード作成

ファイル構成

.
├── phpunit.xml
├── src
│   └── Lines.php
└── tests
    └── LinesTest.php

テストコードの内容は、以前の記事に頂いたコメントを参考にしています。

Lines.php
<?php
class Lines
{
        /**
         * @param resource $input
         * @param resource $output
         */
        function targetFunc($input, $output): void
        {
                $contents = fgets($input);
                fwrite($output, $contents);
        }
}
LinesTest.php
<?php
require_once(__DIR__ . '/../src/Lines.php');
class LinesTest extends PHPUnit\Framework\TestCase
{
        /**
         * 
         */
        public function testSample():void
        {
                $this->stdAssert('test', 'test');
        }
        /**
         * @param string $input_content
         * @param string $assert_output
         */
        function stdAssert($input_content, $assert_output):void
        {
                $input = fopen('php://temp', 'rw');
                $output = fopen('php://temp', 'rw');

                fwrite($input, $input_content);
                rewind($input);

                $lines = new Lines();
                $lines->targetFunc($input, $output);

                rewind($output);
                $output_content = stream_get_contents($output);

                $this->assertSame($assert_output, $output_content);
        }
}

頂いたコメントを元に、
PHPDocの記載の誤りを修正しました。

phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<testsuites>
    <testsuite name="suite">
        <directory>tests/</directory>
    </testsuite>
</testsuites>
</phpunit>

頂いたコメントを元に、

<file>tests/LinesTest.php</file>

とファイル単位で記載していたのを、対象ファイルが増えてもメンテナンスが不要となるように

<directory>tests/</directory>

とディレクトリ単位にしました。

実行

$phpunit
PHPUnit 7.5.1 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 88 ms, Memory: 4.00MB

OK (1 test, 1 assertion)

以前よりはまっとうなやり方でできたと思います…。