Różnica między assertEquals i assertSame w phpunit?

Odpowiedzi:

198

Używam obu sporadycznie, ale zgodnie z dokumentacją:

assertSame

Zgłasza błąd identyfikowany przez $messageJeśli dwóch zmiennych $expectedi $actualnie mają tego samego typu i wartości .”

I jak widać na poniższym przykładzie w powyższym fragmencie, przechodzą '2204'i 2204, co nie powiedzie się, assertSameponieważ jeden jest a, stringa jeden jest w int,zasadzie:

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

assertEquals

„Zgłasza błąd identyfikowany przez $ message, jeśli dwie zmienne $ oczekiwane i $ rzeczywiste nie są równe.”

assertEqualsnie wydaje się brać pod uwagę typu danych, więc skorzystaj z powyższego przykładu 2204:

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

Właśnie przeprowadziłem kilka testów jednostkowych z powyższymi przykładami i rzeczywiście spowodowały one udokumentowane zachowanie.

Mike Purcell
źródło
17
assertEquals nawet tak myśli '0012' == '12'. Nawet jeśli obie wartości są łańcuchami, do porównania są konwertowane na liczby całkowite! Powinieneś naprawdę używać assertSame, kiedy tylko możesz.
marco-fiset
2
Niestety, nawet assertEquals wydaje się być wybredne, np. Przy porównywaniu właściwości tablic i narzekaniu na string vs int.
andig
1
Po komentarzu marco-fiset zauważ, że to zachowanie nie ma już miejsca od PHPUnit 4.0, zobacz uwagi dotyczące aktualizacji .
Gras Double
@coviex Odniesienie jest fajne, ale adres URL jest nieprawidłowy (z powodu zamykającego nawiasu kwadratowego) ... czy możesz to naprawić? Dzięki!
Christian,
3
Ważna uwaga dotycząca porównywania obiektów z assertSame(). Zgłasza błąd identyfikowany przez $ message, jeśli dwie zmienne $ spodziewane i $ rzeczywiste nie odnoszą się do tego samego obiektu. phpunit.de/manual/current/en/…
coviex
23

Jeśli chodzi o porównanie obiektów:

assertSame: może potwierdzić tylko wtedy, gdy 2 obiekty odwołują się do tej samej instancji obiektu. Więc nawet jeśli 2 oddzielne obiekty mają dla wszystkich atrybutów dokładnie te same wartości, assertSame zakończy się niepowodzeniem, jeśli nie będą odwoływać się do tej samej instancji.

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

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

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

assertEquals: może potwierdzić, jeśli 2 oddzielne obiekty pasują do ich wartości atrybutów w każdym przypadku. Jest to więc metoda odpowiednia do zapewniania zgodności obiektów.

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

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

Grigoreas P.
źródło
7
Chociaż ta odpowiedź nie jest wyczerpująca (obejmuje tylko przedmioty), dokładnie to musiałem wiedzieć. Dzięki! :)
rinogo
Tak, ale assertEquals()porównuje nulla ""nawet 0jako równe.
Danon
20
$this->assertEquals(3, true);
$this->assertSame(3, true);

Pierwszy minie!

Drugi zawiedzie.

To jest różnica.

Myślę, że zawsze powinieneś używać assertSame.

człowiek z brązu
źródło
Właśnie to dostałem podczas testowego rozwoju. test przeszedł pomyślnie, przyjęto, że zwracana jest wartość 3, ale w rzeczywistości została zwrócona wartość true. co ciekawe $ this-> assertEquals ('3', prawda); zawodzi.
dwenaus
3

Jak powiedziano wcześniej, AssertSamezgłasza błąd, jeśli te dwa elementy nie mają wspólnego typu i wartości, ale ważne jest również, aby zanotować to z dokumentacji :

Zgłasza błąd identyfikowany przez $ message, jeśli dwie zmienne $ spodziewane i $ rzeczywiste nie odnoszą się do tego samego obiektu.

Więc ten test również się nie powiedzie, mimo że mają wspólny typ i wartość:

class SameTest extends TestCase
{
    public function testFailure()
    {
        $this->assertSame(new stdClass, new stdClass);
    }
}
Miquel Correa Casablanca
źródło
1

Ponadto,

// Passes
$this->assertSame("123.", "123.");
$this->assertEquals("123.", "123");
// Fails
$this->assertSame("123.", "123");
GogromaT
źródło
0

assertSame () == Sprawdza, czy rzeczywiste dane wyjściowe i oczekiwany parametr są takie same.

to jest :

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

lub

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

assertEquals == Jeśli widzimy w odniesieniu do strony internetowej, mam stronę, która ma 2 'tabele', więc kiedy uruchomię assertEquals, sprawdzę liczbę, że 'table' są 2 za pomocą funkcji count. Na przykład:

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

Tutaj widzimy, że assertEquals sprawdza, czy na stronie internetowej znajdują się 2 tabele. możemy również użyć podziałów znalezionych na stronie, używając w nawiasie '#division name'.

Np. 2:

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

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

    // assert that our calculator added the numbers correctly!
    $this->assertEquals(42, $result);
}
Arpan Buch
źródło
1
Użyj formatowania kodu, aby części kodu były bardziej czytelne i unikaj używania #znaczników, chyba że chcesz utworzyć nagłówek.
laalto
0

Jak wcześniej wspomniano, assertEquals()dotyczy przede wszystkim wartości interpretowanej, czy to poprzez żonglowanie typami, czy też obiektu z metodą prezentacji __magic ( __toString()na przykład).

Dobrym przypadkiem użycia assertSame()jest testowanie pojedynczej fabryki.

class CacheFactoryTest extends TestCase
{
    public function testThatCacheFactoryReturnsSingletons()
    {
        $this->assertSame(CacheFactory::create(), CacheFactory::create());
    }
}
Richard A Quadling
źródło