【问题标题】:How to test if string contains another string in PHPUnit?如何测试字符串是否包含 PHPUnit 中的另一个字符串?
【发布时间】:2014-07-23 20:01:57
【问题描述】:

我似乎无法在PHPUnit 中找到一个断言来简单地测试一个字符串是否包含在另一个字符串的某个位置。尝试做这样的事情:

public function testRecipe() {

    $plaintext = get_bread_recipe();

    $this->assertStringContains('flour', $plaintext);

}

我会提出什么真正的断言而不是 assertStringContains ?在这种情况下,我宁愿不必担心正则表达式,因为绝对不需要它。

太简单了,一定有什么我忽略了,但我就是想不通!有趣的是assertStringStartsWith()assertStringEndsWith()

更新:我知道strpos() !== false 可以使用,但我正在寻找更清洁的东西。如果我只是使用普通的 PHP 函数,那么所有断言的重点是什么......

【问题讨论】:

  • 没有这样的方法可以做到这一点,但是你可以使用$this->assertGreaterThan(0, strpos($plaintext, 'flour'));
  • @bartek 如果字符串以 'flour' 开头,则会失败
  • @GordonM 对,在这种情况下,-1 可以解决问题
  • @bartek 那仍然行不通。您必须对 FALSE 进行严格的测试
  • 看,这正是我想要这个特定断言的原因——这里的混乱已经很明显了!

标签: php phpunit


【解决方案1】:

你不能只使用可用的普通 PHP 函数在字符串中处理字符串,然后 assertEquals 的输出吗?诚然,它没有那么闪亮,但它确实有效。

您也可以将 assertThat 与正则表达式一起使用。

从示例的有限角度来看,听起来代码/测试的设计本质上是错误的。为什么函数会返回一个长度未知的复杂字符串,而字符串中的预期位“某处”?

在测试中,您应该能够控制输入,因此您应该知道整个预期的输出字符串。如果你的函数破坏了字符串的其他部分,那么这个断言就不会告诉你。这可能是 assertStringContains 函数不存在的原因。

【讨论】:

  • 是的,我一直在寻找闪亮的方法。我正在测试检索已发布变量的网页,因此我想根据该页面中是否存在字符串来测试请求是否正常。看不出有什么不同的方法。
【解决方案2】:

您可以对任何东西进行断言,包括普通的 PHP 函数。如果您断言您对正在测试的字符串感兴趣的子字符串的 strpos 不返回 FALSE,它将满足您的需求。

请确保您检查的是 FALSE,而不是评估为 FALSE 的东西,例如 0(如果正在测试的字符串以给定的子字符串开头,strpos 将返回该值)。

【讨论】:

  • 我只是想要一些比使用 strpos() 更干净的东西,因为你提到的那个原因!但我想它根本不存在。
【解决方案3】:

正如您所说,assertContains 用于检查数组是否包含值。

查看字符串是否包含子字符串,最简单的查询是使用assertRegexp()

$this->assertRegexp('/flour/', $plaintext);

您只需要添加分隔符。

如果你真的想要一个assertStringContains 断言,你可以扩展PHPUnit_Framework_TestCase 并创建你自己的。

更新

在最新版本的 PHPUnit 中,assertContains 可以处理字符串。

【讨论】:

  • 最新版本的phpunit可以做assertContains字符串。
  • v9 更新:assertStringContainsString 或 assertStringContainsStringIgnoringCase
  • 我们可以使用 PHPUnit 的这些方法: assertStringContainsString() 或 assertStringContainsStringIgnoringCase() 和 assertStringNotContainsString() 或 assertStringNotContainsStringIgnoringCase() 顺便注意,带有字符串 haystacks 的 assertContains() 已被弃用,并且在PHPUnit 9.
【解决方案4】:

你总是可以在自定义断言方法中隐藏丑陋,所以基本上我会有一个继承自 phpunit 测试用例的 BaseTestCase 类,你可以使用它来拥有自己的可重用断言库(参见http://xunitpatterns.com/Custom%20Assertion.html)。 (在 php 5.4 中您也可以使用特征,恕我直言断言库是特征实际上有用的情况之一)..我总是在我的项目中引入很多自定义断言,通常是特定于域的。是的,有些也很丑:)好吧,我想这就是封装的用途......其中包括......:)

更新: 我刚刚检查过,“assertContains”和“assertNotContains”实际上也对字符串和数组(以及任何实现“Traversable”的东西)进行操作:

function test_Contains()
{
    $this->assertContains("test", "this is a test string" );
    $this->assertNotContains("tst", "this is a test string");
}

【讨论】:

  • PHPUnit\Framework\Exception: PHPUnit\Framework\Assert::assertContains() 的参数 #2(无值)必须是数组、可遍历或字符串
  • 此行为已弃用
【解决方案5】:

从@Schleis 扩展,如果您有更复杂的字符串,则需要转义正则表达式:

$this->assertRegexp('/' . preg_quote('[some $stuff]') . '/', $plaintext);

或者用更简洁的方法把它包起来:

public function assertStringContains($needle, $haystack)
{
    $this->assertRegexp('/' . preg_quote($needle) . '/', $haystack);
}

【讨论】:

    【解决方案6】:

    2019 和 PHPUnit 8.0 更新

    assertContains() 自 PHPUnit 8.0 起已弃用,请参阅issue #3425


    现在推荐具体方法(见issue #3422):

    $plaintext = 'I fell on the flour';
    $this->assertStringContainsString('flour', $plaintext);
    

    提示:使用Rector and PHPUnit 8.0 set 立即升级。

    【讨论】:

    • 明确回答,直截了当并更新到最新版本。这对我来说是有效的答复。我看到其他得分更高的答案,但如果框架对此有特定的方法,我不明白为什么要使用像“assertRegexp”这样的变通方法。
    • 解决方法适用于旧版本。这是 PHPUnit 8+ 的正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    相关资源
    最近更新 更多