How to test if string contains another string in PHPUnit?

PhpPhpunit

Php Problem Overview


I can't seem to find an assertion in PHPUnit that simply tests if a string is contained somewhere in another string. Trying to do something like this:

public function testRecipe() {

	$plaintext = get_bread_recipe();

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

}

What real assertion would I put instead of assertStringContains ? I would prefer not having to worry about regex in this case because there is absolutely no need for it.

It's so simple that there must be something I have overlooked, but I just can't figure it out! Funny enough there is assertStringStartsWith() and assertStringEndsWith()!

Update: I know strpos() !== false could be used but I'm looking for something cleaner. If I just use vanilla PHP functions anyway what's the whole point with all the assertions then...

Php Solutions


Solution 1 - Php

As you could tell assertContains is for checking that an array contains a value.

Looking to see if the string contains a substring, your simplest query would be to use assertRegexp()

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

You would just need to add the delimiters.

If you really want to have an assertStringContains assertion, you can extend PHPUnit_Framework_TestCase and create your own.

UPDATE

In the latest version of PHPUnit, assertContains will work on strings.

Solution 2 - Php

You can always hide the ugliness inside a custom assertion method, so basically I would have a BaseTestCase class which inherits from the phpunit test case which you could use to have your own library of reusable assertions (see http://xunitpatterns.com/Custom%20Assertion.html).. (In php 5.4 you can use traits as well, imho assertion libraries are one of the cases where traits actually are useful)..I always introduce quite a few custom assertions in my projects, often domain specific. And yes, some are ugly too:) well, I guess that's what encapsulation is there for... Amongst things...:)

UPDATE: I just checked and 'assertContains' and 'assertNotContains' actually also operate on strings as well as arrays (and anything that implements 'Traversable'):

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

Solution 3 - Php

2019 and PHPUnit 8.0 update

assertContains() is deprecated since PHPUnit 8.0, see issue #3425.


Now the specific method is recommended (see issue #3422):

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


TIP: Upgrade instantly with Rector and PHPUnit 8.0 set.

Solution 4 - Php

You can do asserts against anything, including vanilla PHP functions. If you assert that strpos for the substring you're interested in on the string you're testing doesn't return FALSE it will meet your needs.

Make sure you're checking against FALSE though, and not something that evaluates to FALSE such as 0 (which is what strpos will return if the string being tested starts with the given substring).

Solution 5 - Php

Extending from @Schleis, if you have more complicated strings you will need to escape the regex:

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

Or wrap it up in a neater method:

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

Solution 6 - Php

Can't you just do the string in string using the plain PHP functions available, and then assertEquals the output of that? Granted, it's not as shiny, but it works.

Alternatively you can use assertThat with a regular expression.

It sounds like something is inherently wrong with the design of the code / test though, from the limited perspective of the example. Why would a function return a complex string of unknown length, with the expected bit 'somewhere' in the string?

In the test you should be able to control your input, so you should know your entire expected output string. If your function ruins other parts of the string just this assertion wouldn't tell you about it. Which is probably why the assertStringContains function doesn't exist.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTheStoryCoderView Question on Stackoverflow
Solution 1 - PhpSchleisView Answer on Stackoverflow
Solution 2 - PhpmalteView Answer on Stackoverflow
Solution 3 - PhpTomas VotrubaView Answer on Stackoverflow
Solution 4 - PhpGordonMView Answer on Stackoverflow
Solution 5 - PhpElliot ChanceView Answer on Stackoverflow
Solution 6 - PhphermitcodemonkeyView Answer on Stackoverflow