不扩展PHPUnit_Framework_TestCase,是否可以使用PHPUnit断言?

5
也许这个问题听起来有些奇怪,但我正在尝试解决的问题是...首先,请记住我更多是一名Java开发人员,正在逐渐习惯使用PHP,所以也许我的思维过程是问题所在!
我正在测试一个用Symfony构建的网站。对于我的组件测试,我创建了一个扩展WebTestCase的测试类,并且我的测试中有一系列断言,例如以下内容,以验证页面标题是否在我想要的位置并包含我期望的内容:
$text = "Page Title";
$selector = "h2#pageHeading";
$this->assertEquals(1, $crawler->filter($selector)->count(), "Found wrong number of elements using selector ".$selector);
$this->assertEquals(trim($text),
        trim($crawler->filter($selector)->text()),
        "Element $selector didn't have expected text");

然后我为站点中的其他页面编写更多测试,并且在所有这些页面中,我都希望测试标题是否按照应有的方式出现,因此为了能够重用代码,我将上述内容重构为父类中的函数,以便其他测试类可以重用:

function assertPageTitle($text) {
    $selector = "h2#pageHeading";
    $this->assertEquals(1, $crawler->filter($selector)->count(), "Found wrong number of elements using selector ".$selector);
    $this->assertEquals(trim($text),
            trim($crawler->filter($selector)->text()),
            "Element $selector didn't have expected text");
}

我在测试中调用了这个方法。随着测试的发展,我可以重构更多类似的“复杂断言”,它们都会被放到父类中,从而使我的父类变成一个庞大的断言容器:

protected function assertSelectedOptionContainsTextValue($selector, $text, $value, $crawler) {
    ...
}

protected function assertMenusContainItems($menus, $crawler) {
    ...
}

protected function assertErrorMessageShown($message, $crawler) {
    ...
}

... (more and more) ...

你明白了吧。我接下来的想法是将所有这些“复杂断言”重构到其他类中,可能遵循页面对象模式,但是其他类将无法访问assertEquals方法,除非这些其他类也扩展了WebTestCase或至少PHPUnit_Framework_TestCase,这似乎不是一个很好的主意...
那么有没有一种简单的方法可以访问assertEquals方法(及相关内容)而不必扩展基本的PHPUnit类?我能用组合来实现吗?

如果你想测试你的UI代码,你真的应该使用Selenium。https://phpunit.de/manual/current/en/selenium.html - geggleto
1
我不太确定我会同意那个观点。Selenium速度慢且不稳定,容易因神秘原因而失败。我们只在PHP测试无法达到的地方使用Selenium。 - quiram
3个回答

14
PHPUnit的内置断言是在PHPUnit_Framework_Assert类中实现为公共静态方法。例如,只需调用PHPUnit_Framework_Assert::assertTrue()即可。

好观点。实际上,即使我正在应用@user2970075的建议,这绝对更接近于我的原始问题的答案。我会将其标记为这样。谢谢! - quiram

2
首先,在你的“通用”函数开头覆盖了$text变量,但我理解你只想展示想法。
其次,使用单元测试来进行这种类型的测试并不是最好的选择。我认为你应该将标题逻辑提取到单独的类中,然后通过PHPUnit进行测试,或者使用更合适的测试解决方案,如Behat或Selenium。
如果你仍然没有改变你的想法……每当你想要使用PHPUnit进行测试时,你必须至少扩展PHPUnit_Framework_TestCase。
小提示:Traits可以很好地提取你的断言。

感谢指出代码中的错别字,已经修改。我之前尝试避免扩展 PHPUnit_Framework_TestCase,可能是因为我在考虑 Java(在那里你可以只导入断言并使用它们)。Traits 的选择听起来很有趣,但好像只从 5.4.0 开始提供,而我被困在 5.3.24 :( - quiram
所以我认为你应该改变你的思维方式 :) 没有什么比这更好的方法了。 - tracerout

0
为了在trait中创建可重用的phpunit断言,可以在许多测试用例中使用。您可以使用静态调用PHPUnit_Framework_Assert :: assertSame的trait,以下是一个快速示例:
<?php

namespace Tests\Foo;

use PHPUnit_Framework_Assert;

trait AssertTrait
{
    public function assertInTraitAlwaysFailing()
    {
        PHPUnit_Framework_Assert::assertSame(1, 2, 'always failing');
    }
}

它将充当助手,可以在许多需要相同断言以防止重复的地方使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接