2010-12-09 57 views
3

我正在寫一些對文件系統進行大量使用的對象。我不確定什麼是測試它們的正確方法。我在理論上知道我應該在某些對象中抽象文件系統的功能,然後嘲笑它們,但在我的情況下它將毫無意義:我想測試的類的主要用途是管理文件。所以當測試新對象時,我會遇到同樣的問題,只是移動了一個層次。具有文件系統功能的測試對象

我可以考慮進行測試的唯一方法是實際上使用文件系統。問題是測試將在瀏覽器和命令行中都運行,因此我需要在每個人都可以寫入的目錄中工作。而且,這似乎不是一個非常便攜的解決方案。

任何想法?

回答

5

您可以mock the filesystem with vfsStreamsuggested in the PHPUnit Manual

vfsStream是可能有益的單元測試來模擬真實的文件系統的虛擬文件系統中的流包裝[...]如果PEAR安裝程序是適用於您的系統,你只需要執行下面的命令:

$ pear channel-discover pear.bovigo.org 
$ pear install bovigo/vfsStream-beta 

examples at Github,也是一個Wiki

+8

'哈 - 你是一個垃圾文件系統。我擁有的最後一個文件系統比你好多了,哈哈。那種嘲笑? ;) – PaulJWilliams 2010-12-09 16:13:26

+2

PHPUnit文檔不完整。有更好的參考嗎?它缺少關於如何模擬文件系統的信息(如模擬文件存在,指定模擬文件的內容等) – 2012-11-14 22:18:01

1

引入非常低級別的php函數,除了調用文件系統函數之外什麼都不做,並在代碼中使用這些函數。

然後,在您的測試工具中,用存根(可能記錄它們已被調用)重寫此函數。這樣你就可以驗證你的代碼在實時系統中調用正確的低級PHP函數。對於你所能做的單元測試,真的。

+0

原來的問題沒有提及單元測試,這似乎是專門集成相關的問題。我會認爲嘲笑任何東西都會破壞測試的目的? – 2013-11-09 19:17:16

1

當我看到它,你有三種選擇:

  • 接受一些測試是最好的集成測試。通過創建一個用於測試運行的小世界來開始測試(在%TEMP%中,基於類/方法名稱),然後在完成時將其銷燬。
  • 檢查你的抽象層,並從類中提取文件IO。爲此創建一個接口。其餘的使用集成測試(但這將是非常小的)。這與上面的不同之處在於,不是在執行file.Read你寫意圖,說ioThingie.loadSettings()。
  • 模擬IO(如上面Gordon所示)。

我通常用的選項之一,二,只用三爲邊緣的情況下,我在C#中嘲諷的原始IO層(有System.IO.File)真的只能說明你可以寫嘲諷語句找到一個組合去,並且讓你的測試過於依賴實現,但是上面的vfs看起來像是嘲笑FS,而不是對象。

1

另一個變種是模擬使用文件系統的PHP函數runkit。不知道這是最好的解決方案,但它的工作原理。 有phpunit-mockfunction - PHPUnit擴展,簡化了模擬PHP功能。

因此例子是:

class Tests extends PHPUnit_Framework_TestCase { 
    // ... setUp, tearDown, other tests... 

    function test_1(){ 
     $file_size_to_return = 10; 

     $fake_filesize = new PHPUnit_Extensions_MockFunction('filesize', $this->obj->tested_method); 
     $fake_filesize->expects($this->once())->will($this->returnValue($file_size_to_return)); 

     $this->obj->tested_method(); // actually run method we want test that contains filesize() function... 
    } 
}