2012-07-24 155 views
10

結合依賴我有依賴於本身使用的數據提供者在PHPUnit的另一種方法,一個測試方法:與數據提供者

/** 
* @dataProvider getFields 
*/ 
public function testCanDoSomeStuff($parm1, $parm2) { 
    $result = my_func($parm1, $parm2); 
    $this->assertNotNull($result); 

    return $result; 
} 

/** 
* @depends testCanDoSomeStuff 
*/ 
public function testCanDoSomeMoreStuff($result) { 
    $this->assertNotNull($result); 
} 

我也有一個getFields()數據提供者的功能,無需表明這裏。

依賴於數據提供者的第一個測試通過 - $result不爲空。

我預計測試結果將作爲$result參數傳遞給相關測試。但是,testCanDoSomeMoreStuff函數接收到NULL參數,測試失敗。

更新

這個簡單的測試案例說明了問題:

class MyTest extends PHPUnit_Framework_TestCase { 

    /** 
    * @dataProvider myFunc 
    */ 
    public function testCanDoSomeStuff($value) { 
     $this->assertNotNull($value); 
     return $value; 
    } 

    /** 
    * @depends testCanDoSomeStuff 
    */ 
    public function testCanDoSomeMoreStuff($value) { 
     $this->assertNotNull($value); 
    } 

    /** 
    * Data provider function 
    */ 
    public function myFunc() { 
     $values = array('22'); 
     return array($values); 
    } 
} 

作爲一種解決方法,現在,我已經存儲的結果在測試之間的靜態屬性。

+0

您是否嘗試過'print_r($ results);'查看傳遞給'testCanDoSomeMoreStuff()'的東西? – uzyn 2012-07-24 11:16:55

+0

嗨Uzyn,是的 - null正在通過。我還將調用的結果打印到「my_func」,該結果不爲null。 – iainp999 2012-07-24 11:19:09

+0

你的代碼對我來說看起來不錯。也許你可能想分享你的實際代碼,但實際中可能會有一些錯誤。 – uzyn 2012-07-24 11:20:04

回答

2

問題是幾個因素的結果:

  • 每個測試結果被存儲在使用測試的名字作爲密鑰的陣列。
  • 接收數據的測試的名稱是<name> with data set #<x>
  • @depends註釋不接受多個單詞。

有一個hacky的解決方法:覆蓋TestCase::getDataSetAsString返回註釋將接受的名稱。由於所需的TestCase字段是私有的,所以這會產生一些問題,但使用PHP 5.3.2以上版本,您可以解決這個問題。

重要:不幸的是,你不能依賴試運行數據行 - 只有一個特定的行。如果您的數據提供者只返回一行數據,這不是問題。

下面是帶有示例測試的代碼。請注意,您不必爲您的數據行命名。如果您離開'foo'密鑰,請將@depends更改爲testOne-0

class DependencyTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @dataProvider data 
    */ 
    public function testOne($x, $y) { 
     return $x + $y; 
    } 

    public function data() { 
     return array(
      'foo' => array(1, 2), 
     ); 
    } 

    /** 
    * @depends testOne-foo 
    */ 
    public function testTwo($z) { 
     self::assertEquals(3, $z); 
    } 

    protected function getDataSetAsString($includeData = false) { 
     if (!$includeData && $this->getPrivateField('data')) { 
      return '-' . $this->getPrivateField('dataName'); 
     } 
     return parent::getDataSetAsString($includeData); 
    } 

    private function getPrivateField($name) { 
     $reflector = new ReflectionProperty('PHPUnit_Framework_TestCase', $name); 
     $reflector->setAccessible(true); 
     return $reflector->getValue($this); 
    } 
} 

顯然,這不是一個長期的解決方案。對於接收數據的方法中的每個測試結果,您可以運行一次相關測試。您可以向PHPUnit提交功能請求或拉取請求。

+0

謝謝David,這非常有用。我昨天連同示例代碼一起在github上報告了這個問題,所以我想我現在就把它留給他們。 – iainp999 2012-07-25 09:26:54

2

如果您在$resulttestCanDoSomeStuff()真的不null,那麼這個應該工作。

藉此分開,先嚐試簡化它沒有數據提供者,這樣的事情:

class StackTest extends PHPUnit_Framework_TestCase { 
    public function testCanDoSomeStuff() { 
     $result = true; 
     $this->assertTrue($result); 
     return $result; 
    } 

    /** 
    * @depends testCanDoSomeStuff 
    */ 
    public function testCanDoSomeMoreStuff($result) { 
     $this->assertNotNull($result); 
    } 
} 

測試這將導致到像...

~>phpunit test.php 
PHPUnit 3.6.11 by Sebastian Bergmann. 
.. 
Time: 1 second, Memory: 3.25Mb 
OK (2 tests, 2 assertions) 

現在添加數據提供程序,用您的函數替換我的簡單變量,然後再次測試它。

如果此結果不同,請將var_dump變量$result返回給測試用例testCanDoSomeStuff()。如果不是null那裏,bug the behaviour

+0

嗨Bjoern。對不起,我應該補充說,這正是我也試過的,並且它工作。感謝您的鏈接,我會嘗試在我可以作爲錯誤報告一部分提交的類中重新創建問題。 – iainp999 2012-07-24 12:57:02

2

我也希望所描述的問題能起作用,經過一番研究後,我發現這不是一個錯誤,而是一個預期的,沒有記錄的行爲。依賴測試不知道提供者返回的數據集,這就是測試參數爲null的原因。

來源:https://github.com/sebastianbergmann/phpunit/issues/183#issuecomment-816066

的@dataProvider註釋測試執行前得到計算。基本上,預測試階段爲數據提供者提供的每組參數創建一個測試方法。 @depends依賴於本質上是數據驅動測試的原型,所以@depends在一個不存在的(未執行的測試)上。

另一種想法是,如果提供者提供了多個參數集。 PHPUnit會創建許多testDataProvider方法,但不會有那麼多的testDataReceiver方法,因爲在測試階段沒有針對該測試方法的@dataProvider方法。

然而,您可以在相同的測試方法上使用@depends和@dataProvider。只要小心獲取正確的參數順序,雖然在這種情況下可能沒有第一個參數。

基本上,當數據集有多行時,應該使用數據提供者。但是,您始終可以同時使用@depend@dataProvider以實現大致相同的行爲。