2017-03-12 169 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的任何解决方案。 –