11

PHPUnit でデータ プロバイダーを使用する別のメソッドに依存する 1 つのテスト メソッドがあります。

/** 
 * @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()データ プロバイダー機能もありますが、ここで示す必要はありません。

データ プロバイダーのパスに依存する最初のテストは、$resultNULL ではありません。

テストの結果が依存テストに$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);
    }
}

現時点での回避策として、テスト間で結果を静的プロパティに保存しました。

4

3 に答える 3

2

この問題は、いくつかの要因の結果です。

  • 各テスト結果は、テストの名前をキーとして配列に格納されます。
  • データを受け取るテストの名前は<name> with data set #<x>.
  • 注釈は複数の@depends単語を受け入れません。

TestCase::getDataSetAsStringハックな回避策があります:アノテーションが受け入れる名前を返すためにオーバーライドします。必須フィールドがプライベートであるため、これは少し問題になりTestCaseますが、PHP 5.3.2+ ではそれを回避できます。

重要:残念ながら、すべてのデータ行に対して依存テストを実行することはできません。特定の 1 行のみです。データ プロバイダーが 1 行のデータのみを返す場合、これは問題ではありません。

サンプル テストを含むコードを次に示します。データ行に名前を付ける必要はないことに注意してください。キーを外したままにする場合は、 を'foo'に変更@dependstestOne-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);
    }
}

明らかに、これは長期的な解決策ではありません。データを受信するメソッドからのテスト結果ごとに、依存するテストを 1 回実行する方がよいでしょう。機能リクエストまたはプル リクエストを PHPUnit に送信できます。

于 2012-07-24T18:46:43.920 に答える
2

また、説明されている問題が機能することも期待していました。いくつかの調査の結果、これはバグではなく、文書化されていない予想される動作であることがわかりました。依存するテストは、プロバイダーから返されたデータ セットを認識していないため、テスト パラメーターが null になっています。

ソース: https://github.com/sebastianbergmann/phpunit/issues/183#issuecomment-816066

@dataProvider アノテーションは、テストの実行前に計算されます。基本的に、事前テスト フェーズでは、データ プロバイダーによって提供されるすべてのパラメーター セットに対してテスト メソッドを作成します。@depends は、本質的にデータ駆動型テストのプロトタイプに依存しているため、ある意味で @depends は存在しない (実行されていないテスト) に依存しています。

それを考える別の方法は、プロバイダーが複数のパラメーターのセットを提供していた場合です。PHPUnit は多くの testDataProvider メソッドを作成しますが、テスト前フェーズのテスト メソッドには @dataProvider メソッドがないため、それほど多くの testDataReceiver メソッドはありません。

ただし、同じテスト メソッドで @depends と @dataProvider を使用することはできます。この場合、最初のパラメーターがない可能性がありますが、パラメーターの順序を正しくするように注意してください。

基本的に、データ セットに複数の行がある場合は、データ プロバイダーを使用する必要があります。ただし、いつでも@depend@dataProviderを同時に使用して、ほぼ同じ動作を実現できます。

于 2013-06-25T17:33:13.890 に答える
2

あなたの$resultintestCanDoSomeStuff()が本当にそうでない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)

ここで、データ プロバイダーを追加し、単純な変数を関数に置き換えてから、もう一度テストします。

この結果が異なる場合、 testcase で返す前var_dumpの変数。そこにない場合は、動作にバグがあります$resulttestCanDoSomeStuff()null

于 2012-07-24T11:28:32.233 に答える