k-holyのPHPとか諸々メモ

Webで働くk-holyがPHP(スクリプト言語)とか諸々のことをメモしていきます。ソースコードはだいたいWindowsで動かしてます。

Composerでプロジェクトグローバルに Stagehand_TestRunner + PHPUnit をインストール

久々にお仕事でroot権限のあるLinuxサーバ (CentOS 6.5)を使えることになったのでComposerで Stagehand_TestRunner(3.6.2) + PHPUnit(3.7.37) をインストールしたメモ。

Composerをインストール

作業用ユーザー(application)のホームディレクトリ以下にプロジェクト単位のディレクトリを作成し、その下にソースコードやWeb公開ファイルを配置してます。

つまり /home/application がプロジェクトグローバルのホームという位置付けなので、ここにcomposerコマンドをインストールします。

$ su - application
$ cd ~
$ curl -sS https://getcomposer.org/installer | php
#!/usr/bin/env php
All settings correct for using Composer
Downloading...

Composer successfully installed to: /home/application/composer.phar
Use it: php composer.phar

~/bin が PATH 環境変数に定義されているか確認します。

$ vi ~/.bash_profile
PATH=$PATH:$HOME/bin

export PATH

composer.phar をcomposerコマンドで呼ぶためにリネーム。

$ mkdir ~/bin
$ mv composer.phar ~/bin/composer

composer コマンド打ってみる。

$ composer
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 0c85ca426d6e8235366340f29ad0e6aab1747b83 2014-05-19 10:17:07

OKです。

ComposerでStagehand_TestRunnerをインストール

Stagehand_TestRunnerもComposerを使ってプロジェクトグローバルにインストールします。

これまではPHPUnitやStagehand_TestRunnerはPEARでインストールしてたんですが、PEAR離れが加速する中、Symfonyコンポーネントを利用されているStagehand_TestRunnerもいずれはそうなるのかなーと…。

(開発中のStagehand_TestRunner v4ではPEARチャネルのサポートは継続されるようです)

composerでPEAR離れするには composer global コマンドを使います。

こちらを参考

$ cd /home/application
$ composer global require piece/stagehand-testrunner:3.6.*
Changed current directory to /home/application/.composer
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing symfony/yaml (v2.4.4)
    Downloading: 100%

  - Installing symfony/process (v2.4.4)
    Downloading: 100%

  - Installing symfony/finder (v2.4.4)
    Downloading: 100%

  - Installing symfony/dependency-injection (v2.4.4)
    Downloading: 100%

  - Installing symfony/console (v2.4.4)
    Downloading: 100%

  - Installing symfony/filesystem (v2.4.4)
    Downloading: 100%

  - Installing symfony/config (v2.4.4)
    Downloading: 100%

  - Installing symfony/class-loader (v2.4.4)
    Downloading: 100%

  - Installing piece/stagehand-componentfactory (v1.0.1)
    Downloading: 100%

  - Installing piece/stagehand-alterationmonitor (2.0.0)
    Downloading: 100%

  - Installing piece/stagehand-testrunner (v3.6.2)
    Downloading: 100%

symfony/dependency-injection suggests installing symfony/proxy-manager-bridge (Generate service proxies to lazy load them)
symfony/console suggests installing symfony/event-dispatcher ()
piece/stagehand-testrunner suggests installing phpunit/phpunit (>=3.6.0)
Writing lock file
Generating autoload files

色々入りました。

composerでインストールしたライブラリの実行ファイルは ~/.composer/vendor/bin 以下にリンクとして作成されるようなので…。

$ ls -l ~/.composer/vendor/bin
total 0
lrwxrwxrwx 1 application application 44 May 21 13:06 testrunner -> ../piece/stagehand-testrunner/bin/testrunner

ここをPATH環境変数に追加します。

$ vi ~/.bash_profile
PATH=$PATH:$HOME/bin:$HOME/.composer/vendor/bin
$ source ~/.bash_profile

testrunnerコマンドを実行してみると…

Warning: require_once(Stagehand/TestRunner/Core/Bootstrap.php): failed to open stream: No such file or directory in /home/application/.composer/vendor/piece/stagehand-testrunner/bin/testrunner on line 52

このようなエラーが。おそらくPEAR形式の include_path 前提でファイルを読み込もうとしてエラーが発生しているものと思われます。

該当ソースを読んだところ -p FILE または --preload-script=FILE オプションを付けて呼ぶことで、テストランナーの実行前に任意のスクリプトを読み込めるようなので、これでComposerのオートロードスクリプトを読ませてみます。

$ testrunner -p ~/.composer/vendor/autoload.php
Stagehand_TestRunner version @package_version@

Copyright (c) 2005-2013 KUBO Atsuhiro and contributors,
All rights reserved.

Usage:
  [options] command [arguments]

Options:
  --help           -h Prints help and exit.
  --version        -V Prints version information and exit.
  --ansi              Enables ANSI output.
  --no-ansi           Disables ANSI output.

Testing Framework Commands:
  cakephp               Runs tests with CakePHP.
  ciunit                Runs tests with CIUnit.
  phpspec               Runs tests with PHPSpec.
  phpunit               Runs tests with PHPUnit.
  simpletest            Runs tests with SimpleTest.
Other Commands:
  compile               Compiles the DIC for the production environment.
  help                  Prints the help for a command.
  list                  Lists commands.
  phpunit:passthrough   Runs the phpunit command via the testrunner command.

無事にコマンドを実行できました。

ComposerでPHPUnit(3.7系)をインストール

色々と試行錯誤したのですが、最新版の4.1.0だとStagehand_TestRunnerを動かせなかったので、3.7系を入れることにします。

$ composer global require phpunit/phpunit:3.7.*
Changed current directory to /home/application/.composer
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing phpunit/php-text-template (1.2.0)
    Downloading: 100%

  - Installing phpunit/phpunit-mock-objects (1.2.3)
    Downloading: 100%

  - Installing phpunit/php-timer (1.0.5)
    Downloading: 100%

  - Installing phpunit/php-token-stream (1.2.2)
    Downloading: 100%

  - Installing phpunit/php-file-iterator (1.3.4)
    Downloading: 100%

  - Installing phpunit/php-code-coverage (1.2.17)
    Downloading: 100%

  - Installing phpunit/phpunit (3.7.37)
    Downloading: 100%

phpunit/phpunit-mock-objects suggests installing ext-soap (*)
phpunit/php-code-coverage suggests installing ext-xdebug (>=2.0.5)
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
Writing lock file
Generating autoload files

3.7.37が入りました。

$ ls -l ~/.composer/vendor/bin
total 0
lrwxrwxrwx 1 application application 39 May 21 14:02 phpunit -> ../phpunit/phpunit/composer/bin/phpunit
lrwxrwxrwx 1 application application 44 May 21 14:00 testrunner -> ../piece/stagehand-testrunner/bin/testrunner

こんな感じで、testrunnerに続いてphpunitコマンドへのリンクが張られてます。

なお、4.1.0を入れてから 3.7.*で上書きしてしまうと、やはり動かせなかったので要注意。

Warning: require_once(PHP/CodeCoverage/Autoload.php): failed to open stream: No such file or directory in /home/application/.composer/vendor/phpunit/phpunit/PHPUnit/Autoload.php on line 46

PHPUnit側でもPEAR形式でファイルを読み込もうとしていたようですが、依存ライブラリを全削除してから改めて3.7系を入れ直すとエラーは出ませんでした。

上書きダウングレードの際に依存解決ができてなかったのでしょうか?

(というか、依存するライブラリの未来の変更なんて予測できないのだし、過去バージョンに遡って定義をメンテナンスされてるような例は少ないでしょうね…)

プロジェクトルートでテスト実行

プロジェクトルート /home/application/project に移動して testrunner コマンドでPHPUnitのテストを実行してみます。

前述の通り -p オプションでComposerのオートロードスクリプトを読み込ませるとともに、 -c オプションでStagehand_TestRunnerの設定ファイルを読み込ませます。

$ cd /home/application/project/staging
$ testrunner phpunit -p ~/.composer/vendor/autoload.php -c testrunner.yml
Please run the following command before running the phpunit command:

  testrunner compile

phpunit command の前に testrunner compile しろって言われたので、その通りにします。

$ testrunner compile -p ~/.composer/vendor/autoload.php
$ testrunner phpunit -p ~/.composer/vendor/autoload.php -c testrunner.yml
…中略…
OK (345 tests, 904 assertions)
sh: notify-send: command not found

テストを実行できました。

notify-send コマンドがないって言われてますが、開発環境 (Windows) でこの設定を使ってて、切り替えるのも面倒なのでまあそのままで…。

毎回 testrunner phpunit -p ~/.composer/vendor/autoload.php -c testrunner.yml と入力するのはさすがに面倒なので、コマンドのエイリアスを定義しておきます。

$ vi ~/.bash_profile
alias testrunner-phpunit='testrunner phpunit -p ~/.composer/vendor/autoload.php -c testrunner.yml'
$ source ~/.bash_profile

定義したコマンド testrunner-phpunit を実行してみます。

$ testrunner-phpunit
OK (345 tests, 904 assertions)
sh: notify-send: command not found

同じ結果が返されました。

ちなみに testrunner.yml はこんな感じ。

general:
  framework: phpunit
  test_targets:
    recursive: true
    resources:
      - tests
  autotest:
    enabled: false
    watch_dirs:
      - src
      - tests
  notify: true

phpunit:
  config: phpunit.xml

phpunit コマンド単体でもテストは実行できるよう、PHPUnit側で指定可能な項目は phpunit.xml に定義しています。

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    backupGlobals="false"
    backupStaticAttributes="false"
    bootstrap="tests/bootstrap.php"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    forceCoversAnnotation="false"
    processIsolation="false"
    stopOnError="false"
    stopOnFailure="false"
    stopOnIncomplete="false"
    stopOnSkipped="false"
    strict="true"
    verbose="true"
>
    <testsuites>
        <testsuite name="Acme Test">
            <directory suffix="Test.php">./tests/Acme/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory>./src/</directory>
            <exclude>
                <directory>./tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

phpunit コマンド単体での実行結果

$ phpunit
PHPUnit 3.7.37 by Sebastian Bergmann.

Configuration read from /home/application/project/staging/phpunit.xml

...............................................................  63 / 345 ( 18%)
............................................................... 126 / 345 ( 36%)
............................................................... 189 / 345 ( 54%)
............................................................... 252 / 345 ( 73%)
............................................................... 315 / 345 ( 91%)
..............................

Time: 293 ms, Memory: 9.00Mb

OK (345 tests, 904 assertions)

こんな感じ。準備環境でのテストは最終確認のためなので、PHPUnitだけで良かったかもしれませんが…。