Wie teste ich, ob eine Zeichenfolge eine andere Zeichenfolge in PHPUnit enthält?

73

Ich kann anscheinend keine Behauptung in PHPUnit finden , die einfach testet, ob eine Zeichenfolge irgendwo in einer anderen Zeichenfolge enthalten ist. Der Versuch, so etwas zu tun:

public function testRecipe() {

    $plaintext = get_bread_recipe();

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

}

Welche wirkliche Behauptung würde ich stattdessen setzen assertStringContains? Ich würde es vorziehen, mich in diesem Fall nicht um Regex kümmern zu müssen, da dies absolut nicht erforderlich ist.

Es ist so einfach, dass es etwas geben muss, das ich übersehen habe, aber ich kann es einfach nicht herausfinden! Komisch genug gibt es assertStringStartsWith()und assertStringEndsWith()!

Update: Ich weiß, strpos() !== falsekönnte verwendet werden, aber ich suche etwas saubereres. Wenn ich nur Vanille-PHP-Funktionen benutze, worum geht es dann bei all den Behauptungen?

TheStoryCoder
quelle
Es gibt keine solche Methode, aber Sie können verwenden$this->assertGreaterThan(0, strpos($plaintext, 'flour'));
Bartek
1
@bartek Das wird fehlschlagen, wenn die Zeichenfolge mit 'Mehl' beginnt
GordonM
@ GordonM Richtig, in diesem Fall -1wird der Trick machen
Bartek
1
@bartek Das wird immer noch nicht funktionieren. Sie müssen einen strengen Test für FALSE
GordonM
6
Sehen Sie, genau deshalb wollte ich diese spezifische Behauptung - die Verwirrung ist hier bereits offensichtlich!
TheStoryCoder

Antworten:

23

2019 und PHPUnit 8.0 Update

assertContains()ist seit PHPUnit 8.0 veraltet, siehe Problem # 3425 .


Nun wird die spezifische Methode empfohlen (siehe issue #3422):

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

TIPP: Aktualisieren Sie sofort mit Rector und PHPUnit 8.0 .

Tomáš Votruba
quelle
79

Wie Sie sehen können, assertContainsdient die Überprüfung, ob ein Array einen Wert enthält.

Wenn Sie prüfen möchten, ob die Zeichenfolge eine Teilzeichenfolge enthält, verwenden Sie am einfachsten assertRegexp ().

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

Sie müssten nur die Trennzeichen hinzufügen.

Wenn Sie wirklich eine assertStringContainsBehauptung haben möchten , können Sie PHPUnit_Framework_TestCaseIhre eigene erweitern und erstellen.

AKTUALISIEREN

In der neuesten Version von PHPUnit assertContainswird an Zeichenfolgen gearbeitet.

Schleis
quelle
14
Neuere Versionen von phpunit können assertContains-Zeichenfolgen ausführen.
Jeremy French
4
Update in v9: assertStringContainsString oder assertStringContainsStringIgnoringCase
François Breton
2
Wir können diese Methoden von PHPUnit verwenden: assertStringContainsString () oder assertStringContainsStringIgnoringCase () und assertStringNotContainsString () oder assertStringNotContainsStringIgnoringCase () Übrigens beachten Sie, dass assertContains () mit String Heuhaufen ist veraltet und wird nicht in PHPUnit unterstützt 9.
FFinn
76

Sie können die Hässlichkeit immer in einer benutzerdefinierten Assertionsmethode verbergen, daher hätte ich im Grunde eine BaseTestCase-Klasse, die vom phpunit-Testfall erbt, mit der Sie Ihre eigene Bibliothek wiederverwendbarer Assertions erstellen können (siehe http://xunitpatterns.com/Custom) % 20Assertion.html ) .. (In PHP 5.4 können Sie auch Merkmale verwenden. Imho-Assertion-Bibliotheken sind einer der Fälle, in denen Merkmale tatsächlich nützlich sind.) .. Ich füge in meinen Projekten immer einige benutzerdefinierte Assertions ein, oft domänenspezifisch. Und ja, einige sind auch hässlich :) Nun, ich denke, dafür ist die Kapselung da ... Unter anderem ... :)

UPDATE: Ich habe gerade überprüft, und 'assertContains' und 'assertNotContains' funktionieren tatsächlich auch mit Strings und Arrays (und allem, was 'Traversable' implementiert):

function test_Contains()
{
    $this->assertContains("test", "this is a test string" );
    $this->assertNotContains("tst", "this is a test string");
}
malte
quelle
PHPUnit \ Framework \ Exception: Argument # 2 (kein Wert) von PHPUnit \ Framework \ Assert :: assertContains () muss ein Array, ein Traversable oder ein String sein
Farid Movsumov
1
Dieses Verhalten ist veraltet
Scones
-1

Sie können gegen alles behaupten, einschließlich Vanille-PHP-Funktionen. Wenn Sie behaupten, dass Strpos für den Teilstring, an dem Sie interessiert sind, für den zu testenden String nicht FALSE zurückgeben, entspricht dies Ihren Anforderungen.

Stellen Sie jedoch sicher, dass Sie gegen FALSE prüfen und nicht gegen FALSE wie 0 (was strpos zurückgibt, wenn die zu testende Zeichenfolge mit der angegebenen Teilzeichenfolge beginnt).

GordonM
quelle
Ich wollte nur etwas saubereres als strpos (), genau aus dem Grund, den Sie erwähnen! Aber ich denke es existiert einfach nicht.
TheStoryCoder
-1

Wenn Sie von @Schleis aus kompliziertere Zeichenfolgen haben, müssen Sie sich dem regulären Ausdruck entziehen:

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

Oder wickeln Sie es in einer ordentlicheren Methode ein:

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

Können Sie die Zeichenfolge nicht einfach mit den verfügbaren einfachen PHP-Funktionen in Zeichenfolge ausführen und dann die Ausgabe davon bestätigen? Zugegeben, es ist nicht so glänzend, aber es funktioniert.

Alternativ können Sie assertThat mit einem regulären Ausdruck verwenden.

Aus der begrenzten Perspektive des Beispiels klingt es jedoch so, als ob etwas mit dem Design des Codes / Tests von Natur aus nicht stimmt. Warum sollte eine Funktion eine komplexe Zeichenfolge unbekannter Länge mit dem erwarteten Bit "irgendwo" in der Zeichenfolge zurückgeben?

Im Test sollten Sie in der Lage sein, Ihre Eingabe zu steuern, sodass Sie Ihre gesamte erwartete Ausgabezeichenfolge kennen sollten. Wenn Ihre Funktion andere Teile des Strings ruiniert, sagt Ihnen diese Behauptung nichts darüber. Aus diesem Grund ist die Funktion assertStringContains wahrscheinlich nicht vorhanden.

hermitcodemonkey
quelle
Ja, ich habe nach dem glänzenden Weg gesucht, es zu tun. Ich teste das Abrufen einer Webseite, auf der ich Variablen gepostet habe, und möchte daher testen, ob die Anforderung in Ordnung war, basierend darauf, ob auf dieser Seite eine Zeichenfolge vorhanden ist oder nicht. Ich kann nicht sehen, wie ich das anders machen kann.
TheStoryCoder