iT邦幫忙

DAY 18
3

逐步提昇PHP技術能力系列 第 18

逐步提昇PHP技術能力 - 開發工具 : 使用phing來建置土砲CI

有了一個自動化的建置系統,下一步就是用他做簡單的持續整合啦。

仔細看了一下,phing其實提供了足夠的機制,讓我們透過phing以及一些schedule機制(cron等),就可以做基本的持續整合(CI, Continuous Integration)。
參考:
http://www.phing.info/

先說一下,如果真的要做CI,還是要一台伺服器比較好。

通常的CI過程:

  1. 透過Schedule定時驅動
  2. 透過版本管理,取得要持續整合的專案原始碼
  3. 開始建構,主要是做測試
  4. 在伺服器提供的dashboard中,顯示歷次測試結果
  5. 通知開發者測試結果

為了節省時間,我略去了1跟2兩個步驟。不過phing是可以支援cvs、svn跟git的。而定時啟動,可以靠系統的schedule機制來達成,例如cron,這應該不困難。

先設計一下簡單的流程:

  1. 每次執行時,會記錄timestamp,用來辨識不同的建構
  2. 做完測試,會使用phpunit task的參數,來指定testresult屬性
  3. 做完測試,會使用phpunitreport task,產生報表到web伺服器中的目錄,並且用timestamp來區分
  4. 測試後,會根據testresult來寄發郵件,告知建構成功或失敗。

在使用前,還需要確定幾件事:

  1. 因為要使用mail來做通知,所以系統必須可以寄發email。我是參考: http://benjaminrojas.net/configuring-postfix-to-send-mail-from-mac-os-x-mountain-lion/ ,來讓我的mac可以透過gmail來寄信。
  2. html格式的報表,是在產生xml報表後,用xslt的方式產生的。用composer裝了phing的話,必要的xsl檔會放在:vendor/phing/phing/etc 目錄中

就先來看一下build.xml腳本:

<?xml version="1.0" encoding="UTF-8"?>
<project name="2-3a" default="dist">
	<target name="dist" depends="build">
		<zip destfile="dist/2-3a.zip">
			<fileset dir="builds">
				<include name="**/*.php" />
			</fileset>
		</zip>
	</target>
	<target name="build" depends="test">
		<copy todir="builds">
			<fileset dir="src">
				<include name="**.php" />
			</fileset>
		</copy>
	</target>
	<target name="test" depends="clear">
		<phpunit failureproperty="testresult">
			<formatter todir="reports" type="xml" outfile="phpunit_report.xml" />
			<batchtest>
				<fileset dir="tests">
					<include name="TestScormTimeUtils.php" />
				</fileset>
			</batchtest>
		</phpunit>
	</target>
	<target name="clear">
		<delete>
			<fileset dir="builds">
				<include name="**.*" />
			</fileset>
		</delete>
		<delete>
			<fileset dir="reports">
				<include name="**.*" />
			</fileset>
		</delete>
		<delete>
			<fileset dir="dist">
				<include name="**.*" />
			</fileset>
		</delete>
	</target>
    <target name="mailtest">
        <mail tolist="fillano.feng@gmail.com" from="fillano2001@yahoo.com.tw" subject="mailtest">test mail body.</mail>
    </target>
    <target name="timestamp" depends="test">
    	<tstamp>
    		<format property="reporttime" pattern="%Y%m%d%H%M%S" />
    	</tstamp>
    </target>
    <target name="notify" depends="timestamp">
    	<if>
    		<equals arg1="${testresult}" arg2="true" />
    		<then>
    			<mail tolist="fillano.xxxx@gmail.com" from="fillanoxxxx@yahoo.com.tw" subject="build failed">build failed. please check reports for detail. http://localhost/tests/reports/${reporttime} ...</mail>
    		</then>
    		<else>
    			<mail tolist="fillano.xxxx@gmail.com" from="fillanoxxxx@yahoo.com.tw" subject="build passed">build passed. please check reports for detail. http://localhost/tests/reports/${reporttime} ...</mail>
    		</else>
    	</if>
    </target>
    <target name="reportdir" depends="notify">
    	<mkdir dir="/Users/fillano/Dropbox/Dev/www/html/reports/${reporttime}" />
    </target>
    <target name="htmlreport" depends="reportdir">
    	<phpunitreport infile="reports/phpunit_report.xml" format="frames" todir="/Users/fillano/Dropbox/Dev/www/html/reports/${reporttime}" styledir="vendor/phing/phing/etc" />
    </target>
    <target name="cibuild" depends="htmlreport">
    	<echo msg="build for CI" />
    </target>
</project>

為了做CI,特別做了一個target叫做cibuild,然後透過depends把整個流程串起來。先執行一下看看:

Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phing cibuild
Buildfile: /Users/fillano/builds/ironman6/2-3a/build.xml

2-3a > clear:

   [delete] Deleting 1 files from reports

2-3a > test:


2-3a > timestamp:


2-3a > notify:

     [mail] Sending mail to fillano.feng@gmail.com

2-3a > reportdir:

    [mkdir] Created dir: /Users/fillano/Dropbox/Dev/www/html/reports/20131018223544

2-3a > htmlreport:


2-3a > cibuild:

     [echo] build for CI

BUILD FINISHED

Total time: 0.5631 seconds

然後到gmail看一下信:

打開信裡面的連結,可以看到測試報告:

再來修改一下測試,讓測試失敗看看:

<?php
require "vendor/autoload.php";
require "src/ScormTimeUtils.php";

class TestScormTimeUtils extends PHPUnit_Framework_TestCase
{
    public $fixture1 = array("0000:20:21.023", "0002:23:20.324", "0002:43:41.347");
    public $fixture2 = array('0000:00:23.043', 23043);
    public function testScormTimeAdd() {
        $this->assertEquals(ScormTimeUtils::SCORMTimeAdd($this->fixture1[0], $this->fixture1[1]), $this->fixture1[2]);
        $this->assertEquals(ScormTimeUtils::SCORMTimeAdd('0000:00:00.000', '0000:00:00.000'), '0000:00:00.000');
    }
    public function testScormTimeDiff() {
        $this->assertEquals(ScormTimeUtils::SCORMTimeDiff($this->fixture1[2], $this->fixture1[1]), $this->fixture1[0]);
    }
    public function testScormTimeParser() {
        $this->assertEquals(ScormTimeUtils::SCORMTimeParser($this->fixture2[0]), $this->fixture2[1]);
    }
    /**
    * @expectedException InvalidArgumentException
    * @test
    */
    public function doScormTimeParserSecException() {
        ScormTimeUtils::SCORMTimeParser('0000:00:61.000');
    }
    /**
    * @expectedException InvalidArgumentException
    * @test
    */
    public function doScormTimeParserMinException() {
        ScormTimeUtils::SCORMTimeParser('0000:62:59.000');
    }
    public function testScormTimeFormat() {
        $this->assertEquals(ScormTimeUtils::SCORMTimeFormat($this->fixture2[1]), $this->fixture2[0]);
        $this->assertEquals(true, false);//this assert will fail...
    }
}

然後再跑一次cibuild:

Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phing cibuild
Buildfile: /Users/fillano/builds/ironman6/2-3a/build.xml

2-3a > clear:

   [delete] Deleting 1 files from reports

2-3a > test:


2-3a > timestamp:


2-3a > notify:

     [mail] Sending mail to fillano.feng@gmail.com

2-3a > reportdir:

    [mkdir] Created dir: /Users/fillano/Dropbox/Dev/www/html/reports/20131018230306

2-3a > htmlreport:


2-3a > cibuild:

     [echo] build for CI

BUILD FINISHED

Total time: 0.8938 seconds

這次會收到建構失敗的通知:

然後看一下測試報告:

這樣就知道哪裡測試失敗。

除了每次的測試結果,透過上一層目錄,也可以看一下每次測試的結果:

=====

在多人協作的專案中,由於每個人只負責一部分,有時候因為一些依賴性的關係,要到每個人的開發結果都上到版本管理時才會發現。使用CI有一個好處,就是早期發現早期治療,這樣可以避免問題進一步擴大。

明天再來嘗試一下真正的CI伺服器方案看看。


上一篇
逐步提昇PHP技術能力 - 開發工具 : 使用phing來讓專案建置過程自動化
下一篇
逐步提昇PHP技術能力 - 開發工具 : 試用PHPCI
系列文
逐步提昇PHP技術能力30

尚未有邦友留言

立即登入留言