何為單元測試:
指對軟件中的基本單元進行測試,如函數、方法等,以檢查其返回值或行為是否符合預期;實際中軟件是很復雜的,由許多組件構成,執行流程連貫在一起,要進行單元片段的測試,就需要為其提供執行上下文(或者說參數)和環境(比如打樁模擬一些對象)來運行,並監控其行為和返回值,為此我們就需要寫出做這件事情的程序代碼,這樣的代碼叫做測試用例,許多測試用例有機結合在一起形成一個整體的測試,又叫做測試套件,被測試的程序代碼叫做生產代碼。phpunit這個軟件就是用來幫助我們寫測試用例並進行測試的。
php的單元測試:phpunit
在其官網有詳細教程,這里介紹一些補充內容。
首先要明白phpunit軟件本身就是由php語言實現,其使用是通過命令行進行的,並不是通過瀏覽器訪問
明白這一點很重要,許多新人被卡在這里。很基礎也很簡單,但似乎沒怎么被提及
想試一下單元測試很久了,但是一直沒有合適的項目,而且中文網絡上的PHPUnit教程要么太舊,要么太亂,所以總也沒學會。最近准備把手頭的項目重構一下,決定開始使用PHPUnit做單元測試,先照着PHPUnit的官網做了一下Tutorial,雖然已經很簡單了,仍然被卡住幾次,所以寫篇文章記錄一下。因為對PHP的包管理系統不熟悉,這篇文章會從安裝開始。
1.安裝
PHPUnit如果使用PHAR安裝的話很簡單。Phar歸檔就像Java的Jar,可以直接被PHP解釋器執行。在*nix系統下,可以執行下面三條命令:
➜ wget ➜ chmod +x phpunit.phar ➜ sudo mv phpunit.phar /usr/local/bin/phpunit
考慮到這次的重構會引入比較多類庫,我選擇了Composer做依賴管理。我在Windows上試過PhpStorm里的Composer,總是失敗,感覺是網絡不好的原因。這次在Ubuntu下安裝很順利,全局安裝Composer之后,在命令行執行
composer global require phpunit/phpunit
全局安裝PHPUnit。然后在 ~/.bashrc
文件末尾加一行 PATH=$PATH:/home/feng/.composer/vendor/bin
(注意替換用戶名),來將Composer的global bin目錄加入PATH。
安裝過后運行 phpunit --version
看到版本信息則說明安裝成功。
另外,裝完以后我發現Ubuntu系統可以使用 apt-get install phpunit
來安裝,但我沒有試過。
在Windows下我用的是XAMPP環境,其中已經內置PHPUnit了。如果要在命令提示符下使用的話,可以修改環境變量中的PATH,在里面加上 C:\xampp\php
(或者你修改后的路徑)。再打開命令提示符,運行phpunit --version
看一下。
2.第一個測試
第一個Tutorial我使用的是PHPUnit官網上的Getting Started,這里寫的比它還要簡單一點。
項目的目錄結構如下:
├── phpunit.xml ├── src │ ├── autoload.php │ └── Money.php └── tests └── MoneyTest.php
第一個文件是項目代碼src/Money.php
,內容如下:
amount = $amount; } public function getAmount() { return $this->amount; } public function negate() { return new Money(-1*$this->amount); } }
與之對應的單元測試是tests
目錄下的MoneyTest.php
,注意單元測試文件名最好是*Test.php
,這樣以后指定tests
目錄便可以執行目錄下的所有測試。
negate(); $this->assertEquals(-1, $b->getAmount()); } }
代碼很簡單,$this->assertEquals(-1, $b->getAmount());
即斷言后一個參數的執行結果與前一個參數相等,其他不解釋了。
現在,如果在MoneyTest.php
里加一行include_once('../src/Money.php');
。然后在項目根目錄下執行phpunit tests/MoneyTest
,就可以看到執行結果了。
3.自動載入
但是,逐個添加include的方式太不方便,最好是能自動include所需的文件,PHPUnit提供了一個參數--bootstrap
,可以使用項目的autoload文件。這里我自己寫了一個最簡單的autoload.php
,只要4行。這個文件並不是PHPUnit專用的,應該放在src目錄下。
<?php function __autoload($class){ include $class.'.php'; } spl_autoload_register('__autoload');
當需要Money
類時,就去include Money.php
。寫完__autoload()
函數之后要用spl_autoload_register()
注冊上。
現在就可以去掉MoneyTest.php
中的include
語句,使用phpunit --bootstrap src/autoload.php tests/MoneyTest
來執行測試了。
雖然可以自動載入,但是要執行的命令更長了。我們還可以寫一個配置文件來為項目指定bootstrap,這樣就不用每次都寫在命令里了。
配置文件phpunit.xml
放在項目根目錄下。
如果要執行MoneyTest,在項目根目錄下執行:phpunit tests/MoneyTest
如果要執行tests目錄下的所有測試,在項目根目錄下執行:phpunit tests
Reference:
你可能會疑惑,上面的php代碼是怎么回事呢?
那就是一個測試用例,簡單的測試了一個數組操作,進行單元測試一般通過以下四步:
1. 針對生產代碼類 Class 的測試寫在類 ClassTest中。
2. ClassTest(通常)繼承自 PHPUnit\Framework\TestCase。
3. 測試都是命名為 test* 的公用方法。也可以在方法的文檔注釋塊(docblock)中使用 @test 標注將其標記為測試方法。
4. 在測試方法內,類似於 assertEquals()這樣的斷言方法用來對實際值與預期值的匹配做出斷言判斷。
這里你可能會有幾個地方迷惑:
1、在注釋塊中使用的標注,php可以通過反射得到,程序可以利用得到的信息進行配置
2、上列中測試用例代碼里面的TestCase類來自哪里?並沒有被加載啊?
上文提到phpunit本身是用php語言寫成的,打包成了phar供使用,phar是可執行的,執行時首先執行包里面的存根文件stub
你可以按照上文雲客的另外一篇phar帖子介紹的方法提取還原phpunit.phar包,或者使用phpstorm這樣的ide直接打開
在.phar/stub.php里你將看到存根代碼,TestCase類就是在存根代碼里面require的
“phpunit yunke”這條命令行代碼將首先運行phpunit腳本,從存根文件開始執行,然后由phpunit加載測試用例代碼
可以看出程序並不是從測試用例腳本開始執行的,現在明白TestCase類哪里來的了吧
通過以上內容再配合官網文檔,新手應該可以順利入門了