¿Cómo probar si la cadena contiene otra cadena en PHPUnit?

5 minutos de lectura

avatar de usuario
El codificador de historias

Parece que no puedo encontrar una afirmación en Unidad PHP que simplemente prueba si una cadena está contenida en algún lugar de otra cadena. Tratando de hacer algo como esto:

public function testRecipe() {

    $plaintext = get_bread_recipe();

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

}

¿Qué afirmación real pondría en lugar de assertStringContains ? Preferiría no tener que preocuparme por las expresiones regulares en este caso porque no hay absolutamente ninguna necesidad de ello.

Es tan simple que debe haber algo que he pasado por alto, ¡pero simplemente no puedo resolverlo! Bastante gracioso que hay assertStringStartsWith() y assertStringEndsWith()!

Actualizar: lo sé strpos() !== false podría usarse pero estoy buscando algo más limpio. Si solo uso las funciones de PHP de vainilla de todos modos, ¿cuál es el punto con todas las afirmaciones entonces …

  • No existe tal método para hacer eso, sin embargo, puede usar $this->assertGreaterThan(0, strpos($plaintext, 'flour'));

    – Bartek

    3 de junio de 2014 a las 13:14


  • @bartek Eso fallará si la cadena comienza con ‘harina’

    – GordonM

    3 de junio de 2014 a las 13:20

  • @GordonM Correcto, en este caso -1 hará el truco

    – Bartek

    3 de junio de 2014 a las 13:22

  • @bartek Eso todavía no funcionará. Tienes que hacer una prueba estricta para FALSO

    – GordonM

    3 de junio de 2014 a las 13:23

  • Mira, esto es exactamente por lo que quería esa afirmación específica: ¡la confusión ya es evidente aquí!

    – TheStoryCoder

    3 de junio de 2014 a las 13:48

avatar de usuario
Schleis

como podrías decir assertContains es para comprobar que una matriz contiene un valor.

Mirando para ver si la cadena contiene una subcadena, su consulta más simple sería usar afirmarRegexp()

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

Solo necesitaría agregar los delimitadores.

Si realmente quieres tener un assertStringContains afirmación, puede extender PHPUnit_Framework_TestCase y crea el tuyo propio.

ACTUALIZAR

En la última versión de PHPUnit, assertContains funcionará en cuerdas.

  • Las versiones más recientes de phpunit pueden hacer assertContains string.

    – Jeremy francés

    26/09/2014 a las 14:21

  • Actualización en v9: assertStringContainsString o assertStringContainsStringIgnoringCase

    – François Bretón

    22 de mayo de 2019 a las 16:03

  • Podemos usar estos métodos de PHPUnit: assertStringContainsString() o assertStringContainsStringIgnoringCase() Y assertStringNotContainsString() o assertStringNotContainsStringIgnoringCase() Por cierto, tenga en cuenta que assertContains() con pajares de cadena está obsoleto y no será compatible con PHPUnit 9.

    – Finn

    29 de noviembre de 2019 a las 10:39


  • @schleis ACTUALIZAR asertContains ya no funciona en cadenas (9.5.20) Tuve que usar `assertTrue(str_contains(…̀

    – St3an

    29 abr a las 6:56

avatar de usuario
malta

Siempre puede ocultar la fealdad dentro de un método de aserción personalizado, por lo que básicamente tendría una clase BaseTestCase que hereda del caso de prueba phpunit que podría usar para tener su propia biblioteca de aserciones reutilizables (ver http://xunitpatterns.com/Custom%20Assertion.html).. (En php 5.4 también puede usar rasgos, en mi humilde opinión, las bibliotecas de aserciones son uno de los casos en los que los rasgos son realmente útiles). Siempre introduzco bastantes aserciones personalizadas en mis proyectos, a menudo específicas del dominio. Y sí, algunos también son feos 🙂 bueno, supongo que para eso está la encapsulación… Entre otras cosas… 🙂

ACTUALIZAR:
Acabo de verificar y ‘assertContains’ y ‘assertNotContains’ en realidad también operan en cadenas y matrices (y cualquier cosa que implemente ‘Traversable’):

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

  • PHPUnit\Framework\Exception: el argumento n.º 2 (sin valor) de PHPUnit\Framework\Assert::assertContains() debe ser una matriz, transitable o una cadena

    – Farid Movsumov

    4 de noviembre de 2017 a las 21:23

  • este comportamiento está en desuso

    – bollos

    25 de febrero de 2019 a las 14:05

  • Estaba bien en 2015 pero bajo PHP 8.1 arroja un error fatal: TypeError: PHPUnit\Framework\Assert::assertContains(): Argument #2 ($haystack) must be of type iterable, string given. Podemos migrar a assertStringContainsString.

    – Dereckson

    12 de marzo a las 14:09

avatar de usuario
Tomás Votruba

2019 y actualización de PHPUnit 8.0

assertContains() está en desuso desde PHPUnit 8.0, consulte número 3425.

Ahora se recomienda el método específico (ver issue #3422):

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

SUGERENCIA: actualice al instante con Conjunto Rector y PHPUnit 8.0.

  • Respuesta clara, al grano y actualizada a la última versión. Esta es la respuesta válida para mí. Veo otras respuestas con una puntuación más alta, pero si el marco tiene un método específico para esto, no veo por qué usar soluciones alternativas como “assertRegexp”.

    –Miquel Canal

    27 de enero de 2021 a las 10:51

  • Las soluciones alternativas eran para versiones anteriores. Esta es la respuesta correcta para PHPUnit 8+.

    – Mat Lipe

    8 dic 2021 a las 16:08

Puede hacer afirmaciones contra cualquier cosa, incluidas las funciones básicas de PHP. Si afirma que strpos para la subcadena que le interesa en la cadena que está probando no devuelve FALSO, satisfará sus necesidades.

Sin embargo, asegúrese de verificar FALSO, y no algo que se evalúe como FALSO, como 0 (que es lo que devolverá strpos si la cadena que se está probando comienza con la subcadena dada).

Extendiendo desde @Schleis, si tiene cadenas más complicadas, deberá escapar de la expresión regular:

$this->assertRegexp("https://stackoverflow.com/" . preg_quote('[some $stuff]') . "https://stackoverflow.com/", $plaintext);

O envuélvelo en un método más ordenado:

public function assertStringContains($needle, $haystack)
{
    $this->assertRegexp("https://stackoverflow.com/" . preg_quote($needle) . "https://stackoverflow.com/", $haystack);
}

avatar de usuario
ermitañocodemonkey

¿No puedes simplemente hacer la cadena en cadena usando las funciones simples de PHP disponibles, y luego afirmar que es igual a la salida de eso? De acuerdo, no es tan brillante, pero funciona.

Alternativamente, puede usar assertThat con una expresión regular.

Sin embargo, parece que algo está intrínsecamente mal con el diseño del código/prueba, desde la perspectiva limitada del ejemplo. ¿Por qué una función devolvería una cadena compleja de longitud desconocida, con el bit esperado ‘en algún lugar’ de la cadena?

En la prueba, debe poder controlar su entrada, por lo que debe conocer toda la cadena de salida esperada. Si su función arruina otras partes de la cadena, solo esta afirmación no le informará al respecto. Probablemente por eso no existe la función assertStringContains.

¿Ha sido útil esta solución?