在PHP中使用Mockery進行測試驅動開發(TDD) - 上

測試驅動開發網上也談了不少了,PHP方面的文章也有一些,在百度和Google裏搜,好像沒有看到幾篇談用Mock(假裝對象)的技術的,這裏寫篇文章講講。php

先過一下測試驅動開發的基本理念:就是先寫測試用例(通常這個測試用例都是自動化的單元測試用例,便於快速回滾執行),而後經過逐步修復測試用例的方法補齊產品代碼,最後測試用例修復完畢後,產品也就寫完了。ubuntu

從我本身的實踐中,我認爲在類庫開發的時候使用測試驅動開發技術是一個很好的方案,理由以下: 
可以寫出測試用例,即說明對問題域已經有一個清晰的瞭解, 
節省了寫文檔的時間,測試用例就是類庫調用的示例代碼了。 
代碼質量有保證,由於寫類庫的過程就是修復測試用例的過程,因此測試用例修復完畢後類庫也就寫完了。 
便於估時,估計類庫開發時間的問題就簡化成估計修復測試用例的時間了,相對於來講估時容易一些。svn

咱們以編寫一個字符串轉數字的函數爲例講解測試驅動開發的理念,再引入Mock技術。在開始以前,須要安裝PHPUnit和Mockery庫(本文不使用PHPUnit自帶的Mock庫):函數

# 安裝PHPUnitpear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit# 安裝Mock庫sudo pear channel-discover pear.survivethedeepend.com
sudo pear channel-discover hamcrest.googlecode.com/svn/pear
sudo pear install --alldeps deepend/Mockery

那從測試驅動開發的理念來作的話,咱們先寫測試用例 – parseinttest.php:單元測試

<?    class ParseIntTest extends PHPUnit_Framework_TestCase {        public function testParseIntBasic() {
            $v = parse_int("12345");
            $this->assertEquals(12345, $v);

            $v = parse_int("-12345");
            $this->assertEquals(-12345, $v);        /*            $v = parse_int("abcd");            $this->assertEquals(0, $v);            $v = parse_int("0xab12");            $this->assertEquals(0xab12, $v);            $v = parse_int("01b");            $this->assertEquals(1, $v);        */
        }
    }
?>

上面的代碼裏,咱們經過單元測試用例指定了要實現的函數parse_int的需求,便可以解析整數、帶符號的整數等,又由於時間和資源的限制,那咱們去掉了對十六進制和二進制的支持。測試

運行下面的命令執行測試用例:this

phpunit --verbose parseinttest

由於這個時間沒有任何代碼,因此獲得指望的錯誤 – PHPUnit告訴咱們找不到parse_int這個函數: 
PHPUnit 3.6.12 by Sebastian Bergmann.google

PHP Fatal error:  Call to undefined function parse_int() in /var/www/pmdemo/parseinttest2.php on line 6spa

那咱們先建一個空的parse_int函數 – parseint.php:.net

<?
    function parse_int($str) {        return 0;
    }
?>

上面的代碼裏咱們先不實現函數parse_int的任何邏輯,再運行測試用例,獲得:

shiyimin@ubuntu :/var/www/pmdemo$ phpunit --verbose parseinttest 
PHPUnit 3.6.12 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 2.75Mb

There was 1 failure:

1) ParseIntTest::testParseIntBasic 
Failed asserting that 0 matches expected 12345.

/var/www/pmdemo/parseinttest.php:7

FAILURES! 
Tests: 1, Assertions: 1, Failures: 1.

從上面紅色高亮顯示出來的錯誤消息,咱們知道是測試用例裏的第一個判斷沒有經過,即下面的判斷語句沒有執行成功:

$this->assertEquals(12345, $v);

這是由於咱們的parse_int函數老是返回0這個值,發現了這個錯誤,咱們來補齊這個邏輯以修復測試用例:

parseint.php

<?
    function parse_int($str) {
        $result = 0;
    $i = 0;    

    for ( $i = 0; $i < strlen($str); ++$i ) {    
        $result *= 10;
        $result += $str[$i] - '0';
    }    return $result;
    }
?>

再次運行測試用例: 
shiyimin@ubuntu :/var/www/pmdemo$ phpunit --verbose parseinttest 
PHPUnit 3.6.12 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 2.75Mb

There was 1 failure:

1) ParseIntTest::testParseIntBasic 
Failed asserting that 12345 matches expected -12345.

/var/www/pmdemo/parseinttest.php:10

FAILURES! 
Tests: 1, Assertions: 2, Failures: 1.

從上面的結果能夠看出,第一個測試用例已經修復了,如今是在處理帶符號的字符串時,發生了問題,繼續修復代碼:

parseint.php

<?
    function parse_int($str) {
        $result = 0;
    $i = 0;
    $neg = 1;        
        if ( $str[0] == '-' ) { 
        $neg = -1;
    }    for ( $i = 0; $i < strlen($str); ++$i ) {    
        $result *= 10;
        $result += $str[$i] - '0';
    }    return $result * $neg;
    }
?>

再運行測試用例: 
shiyimin@ubuntu :/var/www/pmdemo$ phpunit --verbose parseinttest 
PHPUnit 3.6.12 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 2.75Mb

OK (1 test, 2 assertions)

好了,此次全部測試用例都經過了,那咱們的產品代碼的實現也告一段落了,固然文章爲了講解方便,上面的代碼並非一個完整的實現,例如它就沒法處理字符串「+12345」的情形。

下篇文章講解如何在PHPUnit裏應用Mock技術。

相關文章
相關標籤/搜索