2010-01-20 177 views
13

我試圖進入單元測試爲它引入的明顯積極,我試圖編寫一個單元測試我爲前一天寫的類。 (我知道這與TDD相反,請耐心等待)PHPUnit測試問題 - 如何單元測試我的課

我的課程Image與其他一些用於圖像處理。

Image本質上包裝GD圖像資源並將數據與其一起存儲。例如,Image一個實例將始終包含它的當前狀態,即其新的寬度/高度,如果調整,將原始圖像數據等

Image類也包含了方法,

  • 創建本身來自文件,字符串數據或URL,例如$image->loadFromPath()
  • 從當前的Image實例的屬性創建新的GD圖像資源,例如,圖像大小調整,以保持背景透明度等
  • 克隆使用的GD圖像資源的操作類

我掙扎什麼是單位如何測試這個類正確以及PHPUnit。我已經完成了一些閱讀,並且我對如何解決這個問題有一些矛盾的想法,我不知道什麼是正確的。

  1. 爲類的每種方法寫一個測試。我在某處讀到我應該測試每種方法。然而,一些方法運行其他方法(我可以添加),所以你有一個依賴鏈。但我也讀過每個單元測試應該獨立於另一個。那麼如果是這樣的話我該怎麼辦?
  2. 將每個測試寫爲類的使用路線。我還在某處讀到,每個測試應該代表1個路徑/使用路線,您可以在課程中使用。因此,如果您覆蓋每一種用法,您最終將獲得完整的代碼覆蓋率。

那麼,哪些是正確的,如果有的話?

+0

你知道代碼覆蓋率嗎?國際海事組織(IMO)至少運行一行代碼至關重要,而不是爲每一種方法都創建一個測試,這對於你提到的原因並不總是必要的。 – Franz 2010-01-20 15:54:32

+0

+1進入UnitTests – Gordon 2010-01-20 15:59:22

+0

我知道什麼代碼覆蓋率是肯定的,你應該瞄準100%,這就是說每一行至少應該運行一次。 因此,最好是編寫測試用例,其中每個測試都是您的類執行的操作,而不是針對特定方法的每個測試? – 2010-01-20 16:00:33

回答

8

應該編寫單元測試來評估一個類的公共接口。您的測試用例應該使用該類,因爲您打算在您的程序中使用它。這裏的想法是測試該類的行爲(預期的,意外的或邊緣條件)。

你發佈的這兩個想法都是正確的。從理論上講,你應該有足夠的測試用例(通過你的代碼的路由)運行你的類中的所有方法。如上所述,100%的測試覆蓋率是一個不錯的目標,但並不總是現實的。

另外,在GD的情況下,要小心編寫測試GD功能的單元測試(它已經過測試,不需要再浪費時間再次測試)。我會read up on在PHPUnit手冊中使用PHPUnit的模擬和存根(並嘲笑文件系統)。

下面是一個例子測試可能是什麼樣子:

public function testImageIsResized() 
{ 
    $image = new Image(); 
    $image->loadFromPath('some/path'); 
    $image->resize(200, 300); 
    $this->assertEquals(200, $image->getWidth()); 
    $this->assertEquals(300, $image->getHeight()); 
} 

現在,根據圖像類的預期行爲,這個測試可能通過沒有問題,或者因爲它期待新的尺寸可能會失敗以成比例地限制到原始圖像尺寸。但是我們沒有明確地調用在測試本身中檢查該約束的內部方法。

+0

非常感謝我的想法!感謝您的總結 – 2010-01-20 19:25:29

5

您可以使用covers annotation來指定測試是否涵蓋多種方法。因此,如果您的某個方法調用另一種方法,則可以將該註釋添加到測試的docblock中,並將其添加到代碼覆蓋率統計信息中,例如,

/** 
* @test 
* @covers MyClass::something() 
* @covers MyClass::_somethingElse() 
*/ 
public function somethingWorksAsExpected() 
{ 
    $this->assertSame($expected, $this->testObject->something()); 
} 

對於個人項目,100%的代碼覆蓋率的罰款。不過,我曾在會議上看過100%被懷疑是必要的會議。儘管有所有好處,但測試需要花時間編寫,並且在預算項目中,僅僅測試80/20就足夠了,並且可以忽略應用程序的不重要的低優先級功能。

至於如何測試你的班級,看看Behaviour Driven Development in the PHPUnit Manual的章節。就你而言,我會測試你在問題中描述的功能。

0

斯蒂芬·梅爾羅斯說:

然而,一些方法運行 別人(這是正確的我想補充),所以你 然後有依賴關係鏈。但我也 讀取每個單元測試應該 獨立於其他

測試獨立性不是不測試相同的代碼兩次,它是關於一個測試的結果(或缺乏導致的)是否影響另一個的結果。如果您的第一個測試插入一些數據,然後在刪除數據之前失敗,則您的第二個測試可能會得到與預期不同的結果。理想情況下,您應該能夠以隨機順序運行測試,或者運行一些測試而不是其他測試。