本文目的
本文目的是收錄一些PHPUnit的有用技巧,這些技巧能夠為給PHPUnit單元測試帶來很多便利。本文将要介紹的技巧如下:
函數依賴測試
資料提供函數
異常測試
跳過忽略測試
自動生成測試架構
有時候,類中的函數有依賴,而且你的邏輯需要被依賴函數正确執行,此時,你可以通過phpunit的依賴标簽顯示的标明這種依賴關系,如果任意被依賴的函數執行失敗,那麼依賴函數将會被自動跳過。如下所示代碼(dependenceDemo.cpp):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<code><?php</code>
<code>class</code> <code>DependanceDemo</code><code>extends</code> <code>PHPUnit_Framework_TestCase</code>
<code>{</code>
<code> </code><code>public</code> <code>function</code> <code>testOne()</code>
<code> </code><code>{</code>
<code> </code><code>echo</code> <code>"testOne\n"</code><code>;</code>
<code> </code><code>$this</code><code>->assertTrue(TRUE);</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>public</code> <code>function</code> <code>testTwo()</code>
<code> </code><code>echo</code> <code>"testTwo\n"</code><code>;</code>
<code> </code><code>$this</code><code>->assertTrue(FALSE);</code>
<code> </code><code>/**</code>
<code> </code><code>* @depends testOne</code>
<code> </code><code>* @depends testTwo</code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>function</code> <code>testThree()</code>
<code>}</code>
<code>?></code>
上面的代碼執行結果如下圖:
<a href="http://images.cnblogs.com/cnblogs_com/bourneli/201209/201209082031436904.jpg"></a>
可以看到,testThree依賴testOne和testTwo,但是testTwo失敗,是以testThree被跳過,使用S表示。
@depends标簽還可以依賴傳回值。如下例子所示(paramDependence.php),
25
26
<code> </code><code>return</code> <code>"testOne"</code><code>;</code>
<code> </code><code>return</code> <code>"testTwo"</code><code>;</code>
<code> </code><code>public</code> <code>function</code> <code>testThree(</code><code>$param1</code><code>,</code><code>$param2</code><code>)</code>
<code> </code><code>echo</code> <code>'First param: '</code><code>.</code><code>$param1</code><code>.</code><code>"\n"</code><code>;</code>
<code> </code><code>echo</code> <code>'Second param: '</code><code>.</code><code>$param2</code><code>.</code><code>"\n"</code><code>;</code>
上面代碼的執行結果如下:
<a href="http://images.cnblogs.com/cnblogs_com/bourneli/201209/201209082031449347.jpg"></a>
值得注意的是,函數的順序與依賴标簽的數序一緻。
函數一般會有多組不同的輸入參數,如果每一組參數都寫一個測試函數,那麼寫測試比較麻煩,如果能提供一種批量的參數輸入方法,那麼測試代碼将會簡潔許多。好在,phpunit提供@dataProvider标簽,支援這種特性,看如下代碼(dataProviderDemo.php):
<code>class</code> <code>DataTest</code><code>extends</code> <code>PHPUnit_Framework_TestCase</code>
<code>{ </code>
<code> </code><code>* @dataProvider provider </code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>function</code> <code>testAdd(</code><code>$a</code><code>,</code><code>$b</code><code>,</code><code>$c</code><code>) </code>
<code> </code><code>{</code>
<code> </code><code>$this</code><code>->assertEquals(</code><code>$c</code><code>,</code><code>$a</code> <code>+</code><code>$b</code><code>);</code>
<code> </code><code>} </code>
<code> </code><code>public</code> <code>function</code> <code>provider()</code>
<code> </code><code>return</code> <code>array</code><code>(</code>
<code> </code><code>array</code><code>(0, 0, 0),</code>
<code> </code><code>array</code><code>(0, 1, 1),</code>
<code> </code><code>array</code><code>(1, 1, 1),</code>
<code> </code><code>array</code><code>(1, 2, 3)</code>
<code> </code><code>); </code>
<code>}?></code>
上面的代碼輸出如下所示:
<a href="http://images.cnblogs.com/cnblogs_com/bourneli/201209/201209082031455692.jpg"></a>
可以看到,函數testAdd周遊了函數provider的傳回的結果,并将他們作為參數,被@dataProvider标記的函數的唯一要求就是傳回數組。
PHPUnit提供三種方法測試異常,如下面代碼所示(exceptionsDemo.php):
27
28
29
30
31
<code>class</code> <code>ExceptionsDemo</code><code>extends</code> <code>PHPUnit_Framework_TestCase</code>
<code> </code><code>* @expectedException InvalidArgumentException</code>
<code> </code><code>public</code> <code>function</code> <code>testTagException()</code>
<code> </code><code>{ </code>
<code> </code><code>throw</code> <code>new</code> <code>InvalidArgumentException;</code>
<code> </code><code>public</code> <code>function</code> <code>testApiException()</code>
<code> </code><code>$this</code><code>->setExpectedException(</code><code>'InvalidArgumentException'</code><code>);</code>
<code> </code><code>public</code> <code>function</code> <code>testTryException()</code>
<code> </code><code>try</code>
<code> </code><code>{</code>
<code> </code><code>throw</code> <code>new</code> <code>InvalidArgumentException;</code>
<code> </code><code>} </code>
<code> </code><code>catch</code> <code>(InvalidArgumentException</code><code>$expected</code><code>)</code>
<code> </code><code>{ </code>
<code> </code><code>return</code><code>; </code>
<code> </code><code>} </code>
<code> </code><code>$this</code><code>->fail(</code><code>'An expected exception has not been raised.'</code><code>);</code>
當然,這三種方法各有用處,效果等同,使用時看需要而定。
在編寫單元測試過程中,有時候隻寫出了測試方法名稱,沒有寫具體的測試内容。這樣,PHPUnit架構預設的認為此測試通過,這樣,我們很可能忘記了該測試方法還沒有實作,如果使用$this->fail(),隻能表明該測試失敗,但是該測試并沒有失敗,令人誤解。是以,我們需要PHPUnit提供一組方法,使得可以跳過沒有實作的測試,并且給與正确的提示。PHPUnit提供下面這四個方法,幫助我們辦到這一點:
方法
意義
void markTestSkipped()
标記目前的測試被跳過,用“S”标記
void markTestSkipped(string $message)
标記目前的測試被跳過,用“S”标記,并且輸出一段示消息
void markTestIncomplete
标記目前的測試不完全,用“I”标記
void markTestIncomplete(string $message)
标記目前的測試不完全,用“I”标記,并且輸出一段提示消息
下面的代碼示範了上面四個方法的使用(SIMarkDemo.php):
<code>class</code> <code>SkipIncompleteMarkDemo</code><code>extends</code> <code>PHPUnit_Framework_TestCase</code>
<code> </code><code>public</code> <code>function</code> <code>testSkipped()</code>
<code> </code><code>$this</code><code>->markTestSkipped();</code>
<code> </code><code>public</code> <code>function</code> <code>testSkippedWithMessage()</code>
<code> </code><code>$this</code><code>->markTestSkipped(</code><code>"this is a skipped test."</code><code>);</code>
<code> </code><code>public</code> <code>function</code> <code>testIncomplete()</code>
<code> </code><code>$this</code><code>->markTestIncomplete();</code>
<code> </code><code>public</code> <code>function</code> <code>testIncompleteWithMessage()</code>
<code> </code><code>$this</code><code>->markTestIncomplete(</code><code>"this is a incomplete test."</code><code>);</code>
輸出結果如下
<a href="http://images.cnblogs.com/cnblogs_com/bourneli/201209/201209082031455626.jpg"></a>
在編寫單元測試的時候,你會發現有些代碼都是千篇一律的,比如testXXXX(){…..},是以基于這種考慮,PHPUnit提供了生成測試架構的指令。該指令可以給為被測試的類中的每一個方法生成一個預設的測試方法,該方法使用markTestIncomplete标記。
如下圖面的代碼表示的類,
<code>class</code> <code>Calculator</code>
<code> </code><code>public</code> <code>function</code> <code>add(</code><code>$a</code><code>,</code><code>$b</code><code>)</code>
<code> </code><code>{ </code>
<code> </code><code>return</code> <code>$a</code> <code>+</code><code>$b</code><code>; </code>
<code> </code><code>public</code> <code>function</code> <code>minus(</code><code>$a</code><code>,</code><code>$b</code><code>)</code>
<code> </code><code>return</code> <code>$a</code> <code>-</code><code>$b</code><code>; </code>
使用如下指令:
<a href="http://images.cnblogs.com/cnblogs_com/bourneli/201209/201209082031468625.jpg"></a>
将會生成一個類CalculatorTest.php,内容如下:
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
<code>require_once</code> <code>'PHPUnit/Framework.php'</code><code>;</code>
<code>require_once</code> <code>'/home/bourneli/test/UnitTestDemo/PHPUnitFeatures/Calculator.php'</code><code>;</code>
<code>/**</code>
<code> </code><code>* Test class for Calculator.</code>
<code> </code><code>* Generated by PHPUnit on 2011-05-24 at 20:54:59.</code>
<code> </code><code>*/</code>
<code>class</code> <code>CalculatorTest</code><code>extends</code> <code>PHPUnit_Framework_TestCase</code>
<code> </code><code>* @var Calculator</code>
<code> </code><code>protected</code> <code>$object</code><code>;</code>
<code> </code><code>* Sets up the fixture, for example, opens a network connection.</code>
<code> </code><code>* This method is called before a test is executed.</code>
<code> </code><code>protected</code> <code>function</code> <code>setUp()</code>
<code> </code><code>$this</code><code>->object =</code><code>new</code> <code>Calculator;</code>
<code> </code><code>* Tears down the fixture, for example, closes a network connection.</code>
<code> </code><code>* This method is called after a test is executed.</code>
<code> </code><code>protected</code> <code>function</code> <code>tearDown()</code>
<code> </code><code>* @todo Implement testAdd().</code>
<code> </code><code>public</code> <code>function</code> <code>testAdd()</code>
<code> </code><code>// Remove the following lines when you implement this test.</code>
<code> </code><code>$this</code><code>->markTestIncomplete(</code>
<code> </code><code>'This test has not been implemented yet.'</code>
<code> </code><code>);</code>
<code> </code><code>* @todo Implement testMinus().</code>
<code> </code><code>public</code> <code>function</code> <code>testMinus()</code>
可以看到,該架構還是比較完整的,生成了setUp,tearDown函數,還為每一個函數生成了一個測試方法。當然,phpunit還提供替他架構函數,如果想要了解更多,可以參見參考文檔中的連結。
參考文檔
本文轉自bourneli部落格園部落格,原文連結:http://www.cnblogs.com/bourneli/archive/2012/09/08/2676978.html,如需轉載請自行聯系原作者