Différence entre assertEquals et assertSame dans phpunit?


121

PHPUnit contient une méthode assertEquals: https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertEquals

Il a également une méthode assertSame: https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertSame

À première vue, on dirait qu'ils font la même chose. Quelle est la différence entre les deux? Pourquoi sont-ils tous les deux spécifiés?

Réponses:


198

J'utilise les deux sporadiquement, mais selon la documentation:

assertSame

Signale une erreur identifiée par $messagesi les deux variables $expectedet $actualn'ont pas le même type et la même valeur . "

Et comme vous pouvez le voir dans l'exemple ci-dessous l'extrait ci-dessus, ils passent '2204'et 2204, ce qui échouera assertSamecar on est un stringet un est int,fondamentalement:

'2204' !== 2204
assertSame('2204', 2204) // this test fails

assertEquals

"Signale une erreur identifiée par $ message si les deux variables $ attendu et $ réel ne sont pas égales."

assertEqualsne semble pas prendre en compte le type de données, donc en utilisant l'exemple ci-dessus de 2204:

'2204' == 2204
assertEquals('2204', 2204) // this test passes

J'ai juste exécuté quelques tests unitaires par rapport aux exemples ci-dessus, et ils ont effectivement abouti à un comportement documenté.


17
assertEquals pense même cela '0012' == '12'. Même si les deux valeurs sont des chaînes, elles sont converties en entiers pour la comparaison! Vous devriez vraiment utiliser assertSame chaque fois que vous le pouvez.
marco-fiset

2
Malheureusement, même assertEquals semble être pointilleux, par exemple lors de la comparaison des propriétés d'un tableau et se plaint alors de string vs int.
andig

1
Suite au commentaire de marco-fiset, notez que ce comportement n'est plus le cas depuis PHPUnit 4.0, voir les notes de mise à jour .
Gras Double

@coviex Reference est cool, mais l'URL est incorrecte (à cause de la fermeture du crochet carré) ... pouvez-vous le réparer? THX!
Christian

3
Remarque importante sur la comparaison d'objets avec assertSame(). Signale une erreur identifiée par $ message si les deux variables $ attendu et $ réel ne font pas référence au même objet. phpunit.de/manual/current/en/…
coviex

23

En ce qui concerne la comparaison d'objets:

assertSame: ne peut affirmer que si 2 objets référencent la même instance d'objet. Ainsi, même si 2 objets séparés ont pour tous leurs attributs exactement les mêmes valeurs, assertSame échouera s'ils ne référencent pas la même instance.

    $expected = new \stdClass();
    $expected->foo = 'foo';
    $expected->bar = 'bar';

    $actual = new \stdClass();
    $actual->foo = 'foo';
    $actual->bar = 'bar';

    $this->assertSame($expected, $actual); FAILS

assertEquals: peut affirmer si 2 objets séparés correspondent à leurs valeurs d'attribut dans tous les cas. C'est donc la méthode appropriée pour affirmer la correspondance d'objet.

    $this->assertEquals($expected, $actual); PASSES

https://phpunit.de/manual/current/en/appendixes.assertions.html


7
Bien que cette réponse ne soit pas exhaustive (elle ne couvre que les objets), c'est exactement ce que j'avais besoin de savoir. Merci! :)
rinogo

Oui, mais assertEquals()compare nullet ""et même 0comme égaux.
Danon il y a

20
$this->assertEquals(3, true);
$this->assertSame(3, true);

Le premier passera!

Le second échouera.

Voilà la différence.

Je pense que vous devriez toujours utiliser assertSame.


Je viens d'avoir ce problème lors du développement piloté par les tests. test réussi, supposé que la valeur 3 était renvoyée mais que true était renvoyé. intéressant $ this-> assertEquals ('3', true); échoue.
dwenaus

3

Comme cela a été dit précédemment, AssertSamesignale une erreur si les deux éléments ne partagent pas le type et la valeur, mais il est également important de le noter à partir de la documentation :

Signale une erreur identifiée par $ message si les deux variables $ attendu et $ réel ne font pas référence au même objet.

Donc, ce test échouerait également même s'ils partagent le type et la valeur:

class SameTest extends TestCase
{
    public function testFailure()
    {
        $this->assertSame(new stdClass, new stdClass);
    }
}

1

De plus,

// Passes
$this->assertSame("123.", "123.");
$this->assertEquals("123.", "123");
// Fails
$this->assertSame("123.", "123");

0

assertSame () == Teste que si la sortie réelle et le paramètre attendu sont identiques.

C'est :

$this->assertSame('$expected','$expected');

ou

$this->assertSame('100','100');

assertEquals == Si nous voyons par rapport à une page de site Web, j'ai une page qui a 2 'table' donc quand je lance assertEquals je vérifierai son compte que les 'table' sont 2 en utilisant une fonction de comptage. Par exemple:

$this->assertEquals(2, $var->filter('table')->count()); 

Ici, nous pouvons voir que assertEquals vérifie qu'il existe 2 tables sur la page Web. nous pouvons également utiliser les divisions trouvées sur la page en utilisant '#division name' à l'intérieur du crochet.

Par exemple 2:

public function testAdd()
{
    $calc = new Calculator();

    $result = $calc->add(30, 12);

    // assert that our calculator added the numbers correctly!
    $this->assertEquals(42, $result);
}

1
Veuillez utiliser la mise en forme du code pour rendre les parties de code plus lisibles et éviter d'utiliser le #balisage sauf si vous souhaitez créer un en-tête.
laalto

0

Comme mentionné précédemment, il assertEquals()s'agit principalement d'une valeur interprétée, que ce soit par jonglage de type ou un objet avec une méthode de présentation __magic ( __toString()par exemple).

Un bon cas d'utilisation pour assertSame()tester une usine singleton.

class CacheFactoryTest extends TestCase
{
    public function testThatCacheFactoryReturnsSingletons()
    {
        $this->assertSame(CacheFactory::create(), CacheFactory::create());
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.