2017-03-12 278 views
1

我想針對一整套文件的內容運行多個測試用例。我可以用一個數據提供者載入我的文件,並使用相同提供商都像這樣的測試:phpunit:重用數據提供者

class mytest extends PHPUnit_Framework_TestCase { 

    public function contentProvider() { 
     return glob(__DIR__ . '/files/*'); 
    } 


    /** 
    * @dataProvider contentProvider 
    */ 
    public function test1($file) { 
     $content = file_get_contents($file); 
     // assert something here 
    } 
... 
    /** 
    * @dataProvider contentProvider 
    */ 
    public function test10($file) { 
     $content = file_get_contents($file); 
     // assert something here 
    } 
} 

顯然,這意味着,如果我有10個測試用例,每個文件被加載10倍。

我可以調整數據提供者加載所有文件並返回一個包含所有內容的大結構。但是由於提供程序是針對每個測試單獨調用的,它仍然意味着每個文件都會被加載10次,此外它會將所有文件同時加載到內存中。

我當然可以將10個測試壓縮到一個測試中,並有10個斷言,但是在第一個斷言失敗後它會立即中止,而且我真的想要報告所有文件錯誤的事情。

我知道數據提供者也可以返回一個迭代器。但phpunit似乎爲每個測試單獨重新運行迭代器,仍導致每個文件加載10次。

有沒有一種巧妙的方法讓phpunit只運行一次迭代器並將結果傳遞給每個測試,然後繼續?

回答

0

測試依賴

如果某些測試的家屬,你應該使用@depends註釋申報Test dependencies。由依賴關係返回的數據由聲明此依賴關係的測試使用。

但是,如果聲明爲依賴項的測試失敗,則不執行相關測試。

靜態存儲的數據

要共享的測試之間的數據,這是常見的setup fixtures statically。 您可以使用同樣的方法與數據提供者:

<?php 

use PHPUnit\Framework\TestCase; 

class MyTest extends TestCase 
{ 
    private static $filesContent = NULL; 

    public function filesContentProvider() 
    { 
     if (self::$filesContent === NULL) { 
      $paths = glob(__DIR__ . '/files/*'); 

      self::$filesContent = array_map(function($path) { 
       return [file_get_contents($path)]; 
      }, $paths); 
     } 
    } 

    /** 
    * @dataProvider filesContentProvider 
    */ 
    public function test1($content) 
    { 
     $this->assertNotEmpty($content, 'File must not be empty.'); 
    } 

    /** 
    * @dataProvider filesContentProvider 
    */ 
    public function test2($content) 
    { 
     $this->assertStringStartsWith('<?php', $content, 
             'File must start with the PHP start tag.'); 
    } 
} 

正如你所看到的,它不支持開箱即用。由於測試類實例在每個測試方法執行後被銷燬,所以您必須將初始化的數據存儲在類變量中。

+0

好的,是的,它存儲靜態工作。但這也意味着我同時擁有內存中的所有文件的內容。不理想。 –

+0

@AndreasGohr:所以,你想要的是執行每個文件的測試類的所有測試。但是通過文件逐個文件,爲所有測試分配/釋放每個文件的內存一次,而不是通過測試。它允許您爲每個文件分配/釋放一次內存,此外,還可以只同時在內存中保留一個文件。聽起來就像一個數據提供者應用於整個測試課程!不僅僅是一種測試方法。 –

+0

@AndreasGohr:如TestSuite類的[createTest()方法](https://github.com/sebastianbergmann/phpunit/blob/218eb7494c010b6f5a6343e9bca9fa9212664b50/src/Framework/TestSuite.php#L549)所示,數據由提供者在任何測試運行之前都存儲。因此,當第一次測試運行時,提供程序返回的所有數據都已實例化,即使使用迭代器讀取當前文件的內容以用於[current()](http://php.net/手動/ en/iterator.current.php)方法。我沒有看到使用PHPUnit的任何解決方案。 –