10

例如,操作 intest1将数据存储在外部*,test2然后执行断言,但tearDown删除该数据,从而破坏test2. tearDown由于其他测试依赖于它,因此无法删除缓存删除。这个问题是询问是否有一种方法可以在依赖案例之间跳过 setUp/tearDown 的同时保持其功能@depends(如果第一个测试失败而不是第二个测试失败,则跳过第二个测试)。

public function tearDown() {
    // delete cache
}

// verify the expected data was retrieved from an uncached source
public function test1() {
    $sut = new SystemUnderTest();
    $data = $sut->getDataAndCache();
    $this->assertEquals('expected', $data);
    return $sut;
}

// verify the expected data was cached
/** @depends test1 */
public function test2($sut) {
    $this->assertEquals('expected', $sut->getCache());
}

*我们将这些称为集成测试,因为它们与外部系统交互。

4

5 回答 5

18

在设置方法中,您可以检查测试是否有hasDependencies(),然后跳过设置过程:

public function setUp()
{
    if (!$this->hasDependencies()) {
        // do setup tasks 
    }
}
于 2014-07-23T19:25:24.820 回答
2

有几个选项。

第一个是将这两个测试隔离到一个单独的测试类中。这样你在其他课程中的拆解就不会干扰。

您可能仍然希望在测试后摆脱缓存。好吧,测试缓存删除本身可能是一个步骤。但是 PHPUnit 还提供了两个静态方法,它们在测试类开始测试之前运行,以及在类中的所有测试都运行之后:setUpBeforeClass()tearDownAfterClass()(参见http://phpunit.de/manual/3.7/en/fixtures.html)。

另一方面,最简单的方法是将两种测试方法组合成一个函数。通过命名函数 getData* AND *Cache,您已经在违反单一职责原则方面遇到了麻烦,因此将测试分成两个函数几乎没有什么好处。

于 2013-08-25T12:15:12.733 回答
0

另一种选择是在两个测试中执行大部分的安排和行动步骤。那么就不需要在 test1 和 test2 之间维护外部状态。如果 test1 失败,@depends注释仍会导致 test2 被跳过。如果安排和执行步骤更复杂,则可以将它们提取到单独的方法中并由两个测试调用。

这是更新的 test2 方法的示例(使用原始问题中的 test1 ):

// verify the expected data was cached
/** @depends test1 */
public function test2($sut) {
    $data = $sut->getDataAndCache();
    $this->assertEquals('expected', $sut->getCache());
}
于 2013-08-26T23:39:50.017 回答
0

我的一个想法是使用一个静态字段,例如is_dependswhich 将设置为 true in和test1false intest2并且会在运行之前检查 的值。例如setUptearDownis_depends

private static is_depends;

public function setUp() {
    if (self::$is_depends) return;
    // do setup that shouldn't be done between dependencies
}

public function tearDown() {
    if (self::$is_depends) return;
    // delete cache
}

// verify the expected data was retrieved from an uncached source
public function test1() {
    $sut = new SystemUnderTest();
    $data = $sut->getDataAndCache();
    $this->assertEquals('expected', $data);
    self::$is_depends = true;
    return $sut;
}

// verify the expected data was cached
/** @depends test1 */
public function test2($sut) {
    $this->assertEquals('expected', $sut->getCache());
    self::$is_depends = false;
}

有没有更好的办法?

于 2013-08-25T05:39:04.103 回答
0

这是 2021 年针对 PHPUnit 9.5 的 hack:

    protected function setUp(): void
    {
        parent::setUp()

        // prevent from running for tests with @depends
        if (!empty($this->requires())) { 
            return;
        }

        // ...
    }

它适用于问题的要求。

但是,我说这是一个 hack,所以请记住:

  • tearDown仍在运行 - 它会破坏测试对象实例(aka ),如果您等$this,则回滚所有事务。use DatabaseTransactions;
  • 如果您将公共变量分配给$this-它们将消失!
  • parent::setUp()如果你在 Laravel 或类似的框架中,启动应用程序,这就是为什么你很可能仍然必须像示例中那样每次都调用它。

所以简而言之,这很可能不是一个好主意

也许考虑使用像PestPHP这样的 PHPUnit 包装器来处理这样的语法糖,我只是希望它经过更多时间的考验,并且不太可能在十年内被放弃......

于 2021-08-17T08:38:56.487 回答