9

I know how to test php output with PHPUnit library, using expectOutputString() or expectOutputString(). Now I need to be sure that output doesn't contain given string. I can do this using output buffering and searching for string inside but probably better way is to use expectOutputString() with proper expression.

How should this expression be built?

Filburt
  • 17,626
  • 12
  • 64
  • 115
koral
  • 2,807
  • 3
  • 37
  • 65

2 Answers2

5

You want to use a regex, and to do a negative match you have to use the lookahead assertion syntax. E.g. to test that the output does not contain "hello":

class OutputRegexTest extends PHPUnit_Framework_TestCase
{
    private $regex='/^((?!Hello).)*$/s';

    public function testExpectNoHelloAtFrontFails()
    {
        $this->expectOutputRegex($this->regex);
        echo "Hello World!\nAnother sentence\nAnd more!";
    }

    public function testExpectNoHelloInMiddleFails()
    {
        $this->expectOutputRegex($this->regex);
        echo "This is Hello World!\nAnother sentence\nAnd more!";
    }

    public function testExpectNoHelloAtEndFails()
    {
        $this->expectOutputRegex($this->regex);
        echo "A final Hello";
    }

    public function testExpectNoHello()
    {
        $this->expectOutputRegex($this->regex);
        echo "What a strange world!\nAnother sentence\nAnd more!";
    }
}

Gives this output:

$ phpunit testOutputRegex.php 
PHPUnit 3.6.12 by Sebastian Bergmann.

FFF.

Time: 0 seconds, Memory: 4.25Mb

There were 3 failures:

1) OutputRegexTest::testExpectNoHelloAtFrontFails
Failed asserting that 'Hello World!
Another sentence
And more!' matches PCRE pattern "/^((?!Hello).)*$/s".


2) OutputRegexTest::testExpectNoHelloInMiddleFails
Failed asserting that 'This is Hello World!
Another sentence
And more!' matches PCRE pattern "/^((?!Hello).)*$/s".


3) OutputRegexTest::testExpectNoHelloAtEndFails
Failed asserting that 'A final Hello' matches PCRE pattern "/^((?!Hello).)*$/s".


FAILURES!
Tests: 4, Assertions: 4, Failures: 3.
Darren Cook
  • 27,837
  • 13
  • 117
  • 217
  • Unfortunately this seems not to work with multiline. Please use `echo "What a strange world!\nNew sentence";` inside `testExpectNoHello()` – koral Mar 18 '13 at 09:05
  • @koral Aha, you need the `s` flag in the regex. I've edited my answer, as this is typically what you'll want. – Darren Cook Mar 18 '13 at 10:01
  • `echo "What Hello a strange world!\n";` doesn't give me failure :( – koral Mar 18 '13 at 10:34
  • @koral You're right. Some study of http://stackoverflow.com/questions/406230/regular-expression-to-match-string-not-containing-a-word told me I had the wrong regex. The `*` should've been outside the brackets! I've expanded my answer with two more tests. – Darren Cook Mar 18 '13 at 12:00
5

This is very simple. Test that string does not contain other string:

Edit

In 2020 for PHPUnit 9.x up there is another concise approach:

$this->assertStringNotContainsString(needle, haystack);

See PHPUnit assertion doc. Not all available assertions are documented in the docs.

The good way to find these is to dd($this) for Laravel (or var_dump($this) in pure PHP) from within your PHPUnit test class and scroll through the output's methods section. There you see the available assertions including the undocumented ones.

The Older Answer

More verbose, more flexible with different assertions not only for strings.

$string='just some string'; 
$this->assertThat($string, $this->logicalNot($this->stringContains('script')));
// Assertion is passed.

Based on the great example of multiple assertions in the same test from http://www.kreamer.org/phpunit-cookbook/1.0/assertions/use-multiple-assertions-in-one-test

I use it to check the form fields sanitization went OK.

Within PHPUnit test I establish a test array having <script> tag in it to be sanitized. Pass it to the sanitization method under test. Serialize the sanitization result (to avoid messing with asserting an array, plus easier on my eyes when var_dump'ing serialized result).

And then apply the stringContains method within assertThat assertion as seen above and enjoy :)

Valentine Shi
  • 6,604
  • 4
  • 46
  • 46