基於Jenkins實現php專案的自動化測試、自動打包和自動部署

科技小先鋒發表於2017-11-22

本篇博文宅鳥將在上篇: 基於Jenkins 搭建持續整合環境 的基礎上,繼續介紹Jenkins結合php專案實現自動化測試和自動部署。廢話不再多說,直接上幹活。

   宅鳥所使用的server為Ubuntu

   要實現在jenkins中實現php的自動化測試,首先需要Jenkins伺服器上安裝php測試框架,php的測試框架很多,在這裡我們選擇 PHPUnit Framework.

PHPUnit的安裝很簡單:

1
sudo apt-get install phpunit

如果出現如下錯誤:

1
2
PHP Warning: require_once(PHP/CodeCoverage/Filter.php): failed to open stream: No such file or directory in /usr/bin/phpunit on line 39
PHP Fatal error: require_once(): Failed opening required `PHP/CodeCoverage/Filter.php` (include_path=`.:/usr/share/php:/usr/share/pear`in /usr/bin/phpunit on line 39


可以通過下面方法安裝:

1
2
3
4
5
6
7
8
9
sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover pear.symfony-project.com
sudo pear channel-discover components.ez.no
sudo pear channel-discover pear.symfony.com
sudo pear update-channels
sudo pear upgrade-all
sudo pear install pear.symfony.com/Yaml
sudo pear install --alldeps phpunit/PHPUnit
sudo pear install --force --alldeps phpunit/PHPUnit


安裝後執行phpunit –version 返回版本資訊。表示安裝成功。

1
2
root@dop-kvm-2:# phpunit --version
PHPUnit 3.7.28 by Sebastian Bergmann.



下面我們開始給Jenkins一些外掛:

Subversion/Git:用於整合專案版本控制軟體,根據需要選擇(在上篇博文已安裝使用)

Phing/Ant:使用Phing或Apache Ant 對PHP專案做自動化構建

CheckStyle:使用PHP CodeSniffer進行程式碼風格檢查的工具。用於檢查PHP程式碼是否有違反一組預先設定好的編碼標準的一個PEAR包,內建了ZEND,PEAR的編碼風格規則

Clover PHP:使用phpunit進行單元測試的工具,可以被xdebug擴充套件用來生成程式碼覆蓋率報告,並且可以與phing整合來自動測試,還可以和Selenium整合來完成大型自動化整合測試

DRY:使用PHPCPD(php copy paste detector)來發現專案中的重複程式碼

HTML Publisher:用來發布phpunit程式碼覆蓋率報告

JDepend:使用PHP Depend分析php中靜態程式碼,用來檢查專案中的程式碼規模和複雜程度

Plot:使用phploc來統計php專案規模大小的工具,可以統計php的專案程式碼行數

PMD:使用phpmd(php mess dector),對基於pdepend的結果進行分析,一旦專案超過了pdepend中各具體指標的規定,將發出警告資訊.

Violations:按照程式碼缺陷嚴重性集中顯示pwd靜態程式碼分析的結果

xUnit:使用JUnit的格式來輸出phpunit的日誌檔案


注意這些外掛是jenkins為php專案所提供的一些外掛,但並不是必須的,所以宅鳥只把最值得大家關注的怎麼自動化測試、打包和釋出來給大家講解。

先給出專案的目錄結構:

1
2
3
4
5
6
7
8
9
root@dop-kvm-2:/home/jenkins/api# tree
.
├── aa.php
├── build.xml
├── create.php
└── test
    ├── DemoTest.php
    └── FunctionTest.php
1 directory, 5 files


注意:

aa.php、create.php是專案的程式檔案

test目錄下的DemoTest.php和FunxtionTest.php是專案的測試檔案

build.xml是jenkins持續整合測試打包部署的呼叫檔案


首先給出專案需要的build.xml檔案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?xml version="1.0" encoding="UTF-8"?>
<project name="api" default="build">
        <target name="build" depends="make_runtime,phpcs-ci,phploc,pdepend,phpcb,phpunit,phpdox,phpcpd"/>
        <property name="version-m"  value="1.1" />
        <property name="version"    value="1.1.0" />
        <property name="stability"  value="stable" />
        <property name="releasenotes" value="" />
        <property name="tarfile"     value="${phing.project.name}.${buildnumber}.${buildid}.tar.gz" />
        <property name="pkgfile"     value="${phing.project.name}.${version}.tgz" />
        <property name="distfile"    value="dist/${tarfile}" />
        <property name="tests.dir" value="test" />
        <fileset id="api.tar.gz" dir=".">
            <include name="test/**"/>
            <include name="*.php"/>
            <include name="*.xml"/>
        </fileset>
        <target name="make_runtime">
                <mkdir dir="${project.basedir}/Runtime" />
                <mkdir dir="${project.basedir}/build/logs" />
                <mkdir dir="${project.basedir}/build/pdepend" />
                <mkdir dir="${project.basedir}/build/code-browser" />
        </target>
        <target name="phpcs" description="Find coding standard violations using PHP_CodeSniffer">
                <exec executable="phpcs">
                        <arg value="--standard=${project.basedir}/build/phpcs.xml" />
                        <arg value="--ignore=autoload.php" />
                        <arg path="${project.basedir}/" />
                </exec>
        </target>
        <target name="phpcs-ci" description="Find coding standard violations using PHP_CodeSniffer">
                <exec executable="phpcs" output="${project.basedir}/build/build.log">
                        <arg value="--report=checkstyle" />
                        <arg value="--report-file=${project.basedir}/build/logs/checkstyle.xml" />
                        <arg value="--standard=${project.basedir}/build/phpcs.xml" />
                        <arg value="--ignore=" />
                        <arg path="${project.basedir}/" />
                </exec>
        </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        <target name="phploc" description="Measure project size using PHPLOC">
                <exec executable="phploc">
                        <arg value="--log-csv" />
                        <arg value="${project.basedir}/build/logs/phploc.csv"/>
                        <arg path="${project.basedir}/"/>
                </exec>
        </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        <target name="pdepend" description="Calculate software metrics using PHP_Depend">
                <exec executable="pdepend">
                        <arg value="--jdepend-xml=${project.basedir}/build/logs/jdepend.xml"/>
                        <arg value="--jdepend-chart=${project.basedir}/build/pdepend/dependencies.svg"/>
                        <arg value="--overview-pyramid=${project.basedir}/build/pdepend/overview-pyramid.svg"/>
                        <arg path="${project.basedir}/"/>
                </exec>
        </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        <target name="phpmd" description="Perform project mess detection using PHPMD">
                <exec executable="phpmd">
                        <arg path="${project.basedir}/"/>
                        <arg value="text"/>
                        <arg value="${project.basedir}/build/phpmd.xml"/>
                </exec>
        </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        <target name="phpmd-ci" description="Perform project mess detection using PHPMD">
                <exec executable="phpmd">
                        <arg path="${project.basedir}/"/>
                        <arg value="xml"/>
                        <arg value="${project.basedir}/build/phpmd.xml"/>
                        <arg value="--reportfile"/>
                        <arg value="${project.basedir}/build/logs/pmd.xml"/>
                </exec>
        </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        <target name="phpcpd" description="Find duplicate code using PHPCPD">
                <exec executable="phpcpd">
                        <arg value="--log-pmd"/>
                        <arg value="${project.basedir}/build/logs/pmd-cpd.xml"/>
                        <arg path="${project.basedir}/"/>
                </exec>
        </target>
        <target name="phpdox" description="Generate API documentation using phpDox">
                <exec executable="phpdox"/>
        </target>
        <target name="phpunit" description="Run unit tests with PHPUnit">
                <exec executable="phpunit" />
        </target>
        <target name="test" description="Run PHPUnit tests">
            <phpunit haltonerror="true" haltonfailure="true" printsummary="true">
            <batchtest>
            <fileset dir="${tests.dir}">
                <include name="**/*Test.php" />
            </fileset>
            </batchtest>
            </phpunit>
        </target>
        <target name="phpcb" description="Aggregate tool output with PHP_CodeBrowser">
                <exec executable="phpcb">
                        <arg value="--log"/>
                        <arg path="${project.basedir}/build/logs"/>
                        <arg value="--source"/>
                        <arg path="${project.basedir}/"/>
                        <arg value="--output"/>
                        <arg path="${project.basedir}/build/code-browser"/>
                </exec>
        </target>
        <target name="check" description="Check variables" >
            <fail unless="version" message="Version not defined!" />
            <fail unless="buildnumber" message="buildnumber not defined!" />
            <fail unless="buildid" message="buildid not defined!" />
            <delete dir="dist" failonerror="false" />
            <mkdir dir="dist" />
        </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        <target name="tar" depends="check" description="Create tar file for release">
            <echo msg="Creating distribution tar for ${phing.project.name} ${version}"/>
            <delete file="${distfile}" failonerror="false"/>
            <tar destfile="${distfile}" compression="gzip">
                <fileset refid="api.tar.gz"/>
            </tar>
        </target>
</project>


閱讀build.xml後,大家可以瞭解一下內容:


 專案名稱、版本、打後的包名稱:

1
2
3
4
5
6
7
8
9
10
<project name="api" default="build">
        <target name="build" depends="make_runtime,phpcs-ci,phploc,pdepend,phpcb,phpunit,phpdox,phpcpd"/>
        <property name="version-m"  value="1.1" />
        <property name="version"    value="1.1.0" />
        <property name="stability"  value="stable" />
        <property name="releasenotes" value="" />
        <property name="tarfile"     value="${phing.project.name}.${buildnumber}.${buildid}.tar.gz" />
        <property name="pkgfile"     value="${phing.project.name}.${version}.tgz" />
        <property name="distfile"    value="dist/${tarfile}" />
        <property name="tests.dir" value="test" />



打包時包括的檔案和資料夾:這裡還可以使用exclude排除檔案和資料夾:

1
2
3
4
5
<fileset id="api.tar.gz" dir=".">
           <include name="test/**"/>
           <include name="*.php"/>
           <include name="*.xml"/>
       </fileset>



測試檔案所在地址:

1
2
3
4
5
6
7
8
9
10
11
12
<target name="phpunit" description="Run unit tests with PHPUnit">
                <exec executable="phpunit" />
        </target>
        <target name="test" description="Run PHPUnit tests">
            <phpunit haltonerror="true" haltonfailure="true" printsummary="true">
            <batchtest>
            <fileset dir="${tests.dir}">
                <include name="**/*Test.php" />
            </fileset>
            </batchtest>
            </phpunit>
        </target>


瞭解這些後,我們開始在jenkins中新建autoTestTarAndPublish專案,選擇:構建一個自由風格的軟體專案:

並且指定好程式碼庫:如圖所示

172124575.jpg


然後再 增加構建步驟->Invoke Phing targets:

增加兩個 target: test,tar 分別與build.xml中的test,tar名稱相對應

172650946.jpg


給tar加上引數:

172622637.jpg



然後在左邊主選單: 系統管理->系統設定->Publish over SSH 下新增主機:(這裡宅鳥設定使用ssh免密碼登陸)需要設定成從jenkins到要釋出的web伺服器的無密碼登陸

如圖設定:

175130605.jpg

這裡新增設定的主機名是:134


接下來我們就可以設定部署工作了:

在新增構建步驟下來表中選擇:Send files or execute commands over SSh,如果該選項未出現需要在外掛管理中安裝外掛:Publish Over SSH 然後重啟jenkins即可.


174009766.jpg


然後在出現的SSH Publishers中選擇要釋出的主機:

並填寫打包檔案地址,釋出到遠端server地址資訊,並在Exec command文字框中填寫解壓等shell指令碼:

詳情見圖:

175817788.jpg

此項設定完畢後,就可以釋出php專案到134伺服器上了:


最後檔案釋出包的存檔工作:


增加構建後操作步驟:

180033526.jpg

填寫dist/*.tar.gz

180210215.jpg


至此配置完畢後,點選 儲存 按鈕.我們就可以釋出程式到指定伺服器134上了.


來看一下發布結果:

回到專案左側點選:立即構建:可以看到構建進度條,結束後可以在控制檯看到輸出結果:

085434850.jpg


我們來到134上看:

180805428.jpg

至此釋出完畢.


此時我們檢視一下test/DemoTest.php檔案內容:

1
2
3
4
5
6
7
8
9
10
<?php
class DemoTest extends PHPUnit_Framework_TestCase {
  public function testPass() {
      $this->assertTrue(true);
    }
  public function testFail() {
      $this->assertFalse(false);
    }
}
?>


我們把 testFail()改成下面:

1
2
3
4
5
6
7
8
9
10
<?php
class DemoTest extends PHPUnit_Framework_TestCase {
  public function testPass() {
      $this->assertTrue(true);
    }
  public function testFail() {
     $this->assertTrue(false);
    }
}
?>

$this->assertTrue(false);

這個是錯誤的斷定:

提交檔案後再次構建:

我們可以看到本次構建失敗,檢視輸出結果如下:

181704835.jpg


當把測試用例修改回正確後,執行構建,釋出正確。


1
2
3
4
5
6
7
8
9
10
<?php
class DemoTest extends PHPUnit_Framework_TestCase {
  public function testPass() {
      $this->assertTrue(true);
    }
  public function testFail() {
      $this->assertFalse(false);
    }
}
?>


182504533.jpg

ok,到此介紹結束.

總結一下:

jenkins根據專案根目錄下的build.xml檔案,並根據jenkins中targets的配置,首先自動執行test,當測試通過後,開始執行tar,打包完成後,開始連結遠端webserver把程式包上傳到遠端webserver指定目錄下,然後再根據jenkins下的command 執行解壓操作,然後就可以根據自己的業務通過shell指令碼進行自動處理自動釋出的各項操作.


如果在執行test過程中,出現發現測試用例不通過,則就發出錯誤報告,終止本次構建。


本文轉自birdinroom 51CTO部落格,原文連結:http://blog.51cto.com/birdinroom/1346812,如需轉載請自行聯絡原作者


相關文章