Prev Next

第19章 継続的インテグレーション

 

Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily, leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly.

継続的インテグレーション というソフトウェア開発手法は、チームのメンバーどうしが お互いの開発内容を頻繁に結合させるというものだ、通常は、 最低でも一日に一度、あるいは場合によっては一日に何度もこれを行う。 結合の際には自動ビルド (テストを含む) を行い、 エラーはできるだけ早い段階で検出する。 多くのチームが、この手法によって結合時の問題を激減させている。 また、ソフトウェアをより高速に開発できるようにもなっている。

 
  --Martin Fowler

この章では、まず継続的インテグレーションという技法の概要について述べ、 それを PHPUnit にどのように適用するかを説明していきます。

CruiseControl

継続的インテグレーションでは、テストを含めたビルド手順を 完全に自動化して何度でも実行できるようにしておく必要があります。 これは、一日に何度も実行されます。 各開発者は、この仕組みによって結合を行い、結合時の問題を減らします。 自動化を実現するには cronjob を使用します。このジョブでは、まずプロジェクトの ソースコードリポジトリ から定期的に最新版をチェックアウトし、 テストを実行し、その結果を利用しやすい形式で出力します。

ここで CruiseControl のような継続的ビルドプロセス用のフレームワークの出番です。 このフレームワークには、メールでの通知や Apache Ant との統合、 またさまざまなバージョン管理ツールとの統合のためのプラグインが用意されています。 またウェブインターフェイスも用意されており、 最新のビルドおよび以前のビルドについての詳細を見ることができます。

次の例では、CruiseControl が /usr/local/cruisecontrol にインストールされていることを想定しています。

  1. cd /usr/local/cruisecontrol
    
  2. mkdir -p projects/BankAccount/build/logs
    
  3. cd projects/BankAccount
    
  4. svn co svn://svn.phpunit.de/phpunit/phpunit/branches/release/3.2/PHPUnit/Samples/BankAccount source
    
  5. build.xml ファイルを編集します。

例 19.1: projects/BankAccount/build.xml

<project name="BankAccount" default="build" basedir=".">
 <target name="checkout">
  <exec dir="${basedir}/source/" executable="svn">
   <arg line="up"/>
  </exec>
 </target>

 <target name="test">
  <exec dir="${basedir}/source" executable="phpunit" failonerror="true">
   <arg line="--log-xml ${basedir}/build/logs/bankaccount.xml BankAccountTest"/>
  </exec>
 </target>

 <target name="build" depends="checkout,test"/>
</project>

  1. cd /usr/local/cruisecontrol
    
  2. config.xml ファイルを編集します。

例 19.2: config.xml

<cruisecontrol>
  <project name="BankAccount" buildafterfailed="false">
    <plugin
    name="svnbootstrapper"
    classname="net.sourceforge.cruisecontrol.bootstrappers.SVNBootstrapper"/>
    <plugin
    name="svn"
    classname="net.sourceforge.cruisecontrol.sourcecontrols.SVN"/>

    <listeners>
      <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
    </listeners>

    <bootstrappers>
      <svnbootstrapper localWorkingCopy="projects/${project.name}/source/"/>
    </bootstrappers>

    <modificationset>
      <svn localWorkingCopy="projects/${project.name}/source/"/>
    </modificationset>

    <schedule interval="300">
      <ant
      anthome="apache-ant-1.7.0"
      buildfile="projects/${project.name}/build.xml"/>
    </schedule>

    <log dir="logs/${project.name}">
      <merge dir="projects/${project.name}/build/logs/"/>
    </log>

    <publishers>
      <currentbuildstatuspublisher
      file="logs/${project.name}/buildstatus.txt"/>

      <email
      mailhost="localhost"
      buildresultsurl="http://cruise.example.com/buildresults/${project.name}"
      skipusers="true"
      spamwhilebroken="true"
      returnaddress="project@example.com">
        <failure address="dev@lists.example.com" reportWhenFixed="true"/>
      </email>
    </publishers>
  </project>
</cruisecontrol>

これで CruiseControl サーバを(再)起動できるようになります。

  1. ./cruisecontrol.sh
    
  2. http://localhost:8080/ をブラウザで開きます。

phpUnderControl

phpUnderControl は CruiseControl の拡張で、さまざまな PHP 開発ツール、たとえばテスト用の PHPUnit や 静的コード解析用の PHP_CodeSniffer、 そして API ドキュメントの生成用の PHPDocumentor を統合します。強力なコマンドラインツールも付属しており、あなたのプロジェクト用に CruiseControl の XML 設定ファイルを自動生成させることもできます。 次の例では、CruiseControl が /usr/local/cruisecontrol にインストールされていることを想定しています。

  1. pear install --alldeps phpunit/phpUnderControl
    
  2. phpuc install /usr/local/cruisecontrol
    
  3. phpuc project --version-control svn
                  --version-control-url svn://svn.phpunit.de/phpunit/phpunit/branches/release/3.3/PHPUnit/Samples/BankAccount
                  --test-case BankAccountTest
                  --test-file BankAccountTest.php
                  --test-dir .
                  --project-name BankAccount
                  /usr/local/cruisecontrol
    

上のコマンドは、まずプロジェクトのディレクトリとそのプロジェクト用の設定ファイル build.xml を作成し、ソースリポジトリから初期チェックアウトを行い、 その新しいプロジェクトをグローバル設定ファイル config.xml に追加します。 これで CruiseControl サーバを(再)起動できるようになります。

  1. cd /usr/local/cruisecontrol
    
  2. ./cruisecontrol.sh
    
  3. http://localhost:8080/ をブラウザで開きます。

Apache Maven

Apache Maven は、ソフトウェアプロジェクトの管理や理解のためのツールです。 プロジェクト指向モデル (POM) にもとづいた Apache Maven は、 プロジェクトのビルドやレポート、ドキュメントの作成を共通の情報から行います。

PHPUnit の XML ログ機能 (「XML 形式」 を参照ください) で作成した XML のログファイルは、テストスイート単位で個別の XML に分割しないと Apache Maven の surefire plugin で処理することができません。 このプラグインはプロジェクトのテストフェーズで用いるもので、 アプリケーションのユニットテストを実行します。 例 19.4 に、XML の分割を行うための XSLT スタイルシートを示します。 例 19.3pom.xml 設定ファイルの例です。

例 19.3: pom.xml

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

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- ... -->
  <prerequisites>
    <maven>2.0.7</maven>
  </prerequisites>
  <!-- ... -->
  <build>
  <!-- ... -->
    <plugins>
      <plugin>
      <dependencies>
        <dependency>
          <groupId>org.apache.ant</groupId>
          <artifactId>ant-trax</artifactId>
          <version>1.7.0</version>
        </dependency>
        <dependency>
          <groupId>net.sf.saxon</groupId>
          <artifactId>saxon</artifactId>
          <version>8.7</version>
        </dependency>
      </dependencies>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-antrun-plugin</artifactId>
      <version>1.2-SNAPSHOT</version>
      <executions>
        <execution>
          <id>codecoverage</id>
          <phase>pre-site</phase>
          <goals>
            <goal>run</goal>
          </goals>
          <configuration>
            <tasks>
              <property name="phpunit.codecoverage"
                        location="${project.reporting.outputDirectory}/phpunit/codecoverage" />
              <property name="surefire.reports"
                        location="${project.build.directory}/surefire-reports" />

              <mkdir dir="${phpunit.codecoverage}"/>
              <mkdir dir="${surefire.reports}"/>

              <!-- ${ant.phpunit} path to PHPUnit executable -->
              <!-- ${ant.pear};... this is the include path for your test execution -->
              <!-- ${test.AllTests} PHPUnit cmd line args like 'AllTests de/dmc/dashboard/AllTests.php' -->
              <exec executable="${ant.phpunit}" dir="${basedir}">
                <arg line="-d include_path=${ant.pear};${project.build.sourceDirectory};${project.build.testSourceDirectory}
                           --report ${phpunit.codecoverage} ${test.AllTests}" />
              </exec>

              <xslt in="${phpunit.codecoverage}/logfile.xml"
                    out="${surefire.reports}/xslt.info"
                    style="src/test/config/phpunit_to_surefire.xslt"
                    processor="trax">
                <!-- this is the output folder for surefire like XML Reports -->
                <param name="outputDir" expression="${surefire.reports}"/>
              </xslt>
            </tasks>
          </configuration>
        </execution>
      </executions>
      </plugin>
    </plugins>
  </build>
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-report-plugin</artifactId>
        <version>2.4-SNAPSHOT</version>
        <reportSets>
          <reportSet>
            <reports>
              <report>report-only</report>
            </reports>
          </reportSet>
        </reportSets>
      </plugin>
    </plugins>
  </reporting>
</project>

例 19.4: phpunit_to_surefire.xsl

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

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:param name="outputDir">.</xsl:param>

  <xsl:template match="testsuites">
    <xsl:apply-templates select="testsuite"/>
  </xsl:template>

  <xsl:template match="testsuite">
    <xsl:if test="testcase">
      <xsl:variable name="outputName" select="./@name"/>
      <xsl:result-document href="file:///{$outputDir}/{$outputName}.xml" method="xml">
        <xsl:copy-of select="."/>
      </xsl:result-document>
    </xsl:if>

    <xsl:apply-templates select="testsuite"/>
  </xsl:template>
</xsl:stylesheet>


Prev Next
1. 自動テスト
2. PHPUnit の目標
3. PHPUnit のインストール
4. PHPUnit 用のテストの書き方
データプロバイダ
例外のテスト
PHP のエラーのテスト
5. コマンドラインのテストランナー
6. Fixtures
tearDown() よりも setUp()
バリエーション
Fixture の共有
7. テストの構成
スイートレベルのセットアップ
8. テストケースの拡張
出力内容のテスト
パフォーマンス低下のテスト
9. データベースのテスト
データセット
Flat XML データセット
XML データセット
操作
データベースのテストのコツ
10. 不完全なテスト・テストの省略
不完全なテスト
テストの省略
11. モックオブジェクト
自己シャント
スタブ
12. テストの進め方
開発中のテスト
デバッグ中のテスト
13. テストファーストプログラミング
銀行口座の例
14. コードカバレッジ解析
カバーするメソッドの指定
コードブロックの無視
ファイルのインクルードや除外
15. テストのその他の使用法
アジャイルな文書作成
複数チームでのテスト
16. ログ出力
XML 形式
コードカバレッジ (XML)
JavaScript Object Notation (JSON)
Test Anything Protocol (TAP)
GraphViz マークアップ
テストデータベース
17. 雛形ジェネレータ
アノテーション
18. PHPUnit と Selenium
Selenium RC
PHPUnit_Extensions_SeleniumTestCase
19. 継続的インテグレーション
CruiseControl
phpUnderControl
Apache Maven
20. PHPUnit の実装
21. PHPUnit API
概要
PHPUnit_Framework_Assert
PHPUnit_Framework_Test
PHPUnit_Framework_TestCase
PHPUnit_Framework_TestSuite
PHPUnit_Framework_TestResult
パッケージの構成
22. PHPUnit の拡張
PHPUnit_Framework_TestCase のサブクラスの作成
アサートクラスの作成
PHPUnit_Extensions_TestDecorator のサブクラスの作成
PHPUnit_Framework_Test の実装
PHPUnit_Framework_TestResult のサブクラスの作成
PHPUnit_Framework_TestListener の実装
新しいテストランナーの作成
A. アサーション
B. XML 設定ファイル
テストスイート
グループ
コードカバレッジ対象のファイルの追加や除外
ログ出力
PMD ルール
PHP INI 項目やグローバル変数の設定
C. PHP 4 用の PHPUnit
D. 目次
E. 参考文献
F. 著作権