Разница между assertEquals и assertSame в phpunit?


121

PHPUnit содержит метод assertEquals: https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertEquals

У него также есть метод assertSame: https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertSame

На первый взгляд кажется, что они делают то же самое. Какая разница между двумя? Почему они оба указаны?

Ответы:


198

Я использую и то, и другое время от времени, но согласно документам:

assertSame

Сообщает об ошибке , идентифицированной , $messageесли две переменные $expectedи $actualне имеют одинаковый тип и значение «.

И, как вы можете видеть в примере ниже приведенного выше отрывка, они передают '2204'и 2204, которые не будут использоваться, assertSameпотому что один - это, stringа другой - в int,основном:

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

assertEquals

«Сообщает об ошибке, идентифицированной $ message, если две переменные $ expected и $ actual не равны».

assertEqualsпохоже, не принимает во внимание тип данных, поэтому, используя приведенный выше пример 2204:

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

Я просто провел несколько модульных тестов для приведенных выше примеров, и они действительно привели к задокументированному поведению.


17
assertEquals даже так думает '0012' == '12'. Даже если оба значения являются строками, они преобразуются в целые числа для сравнения! Вы действительно должны использовать assertSame всякий раз, когда можете.
marco-fiset

2
К сожалению, даже assertEquals кажется разборчивым, например, при сравнении свойств массива и жалуется на строку vs int.
andig

1
Следуя комментарию marco-fiset, обратите внимание, что это поведение больше не имеет места, начиная с PHPUnit 4.0, см. Примечания к обновлению .
Gras Double

@coviex Ссылка классная, но URL неправильный (из-за закрывающей квадратной скобки) ... не могли бы вы исправить это? Спасибо!
Кристиан,

3
Важное примечание о сравнении объектов с assertSame(). Сообщает об ошибке, идентифицированной $ message, если две переменные $ expected и $ actual не ссылаются на один и тот же объект. phpunit.de/manual/current/en/…
coviex

23

Что касается сравнения объектов:

assertSame: может только утверждать, если 2 объекта ссылаются на один и тот же экземпляр объекта. Таким образом, даже если два отдельных объекта имеют для всех своих атрибутов одинаковые значения, assertSame завершится ошибкой, если они не ссылаются на один и тот же экземпляр.

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

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

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

assertEquals: может утверждать, соответствуют ли 2 отдельных объекта своим значениям атрибутов в любом случае. Итак, это метод, подходящий для подтверждения соответствия объекта.

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

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


7
Хотя этот ответ не является исчерпывающим (он охватывает только объекты), это именно то, что мне нужно было знать. Спасибо! :)
rinogo

Да, но assertEquals()сравнивает nullи ""даже 0как равные.
Данон

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

Первый пройдет!

Второй выйдет из строя.

Вот в чем разница.

Я думаю, вам всегда следует использовать assertSame.


У меня была эта проблема во время разработки через тестирование. тест пройден, предполагается, что возвращается значение 3, но на самом деле было возвращено значение true. интересно $ this-> assertEquals ('3', true); выходит из строя.
dwenaus

3

Как было сказано ранее, AssertSameсообщает об ошибке, если два элемента не имеют общего типа и значения, но также важно отметить это в документации :

Сообщает об ошибке, идентифицированной $ message, если две переменные $ expected и $ actual не ссылаются на один и тот же объект.

Таким образом, этот тест тоже не пройдет, даже если у них общий тип и значение:

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

1

Более того,

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

0

assertSame () == Проверяет, совпадают ли фактический результат и ожидаемый параметр.

то есть :

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

или

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

assertEquals == Если мы видим, что касается страницы веб-сайта, у меня есть страница с двумя «таблицами», поэтому, когда я запускаю assertEquals, я проверю его счетчик, что «таблица» равна 2, с помощью функции подсчета. Например:

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

Здесь мы видим, что assertEquals проверяет наличие 2 таблиц на веб-странице. мы также можем использовать подразделения, найденные на странице, используя '#division name' внутри скобок.

Например, 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
Используйте форматирование кода, чтобы части кода были более удобочитаемыми, и избегайте использования #разметки, если вы не хотите сделать заголовок.
laalto

0

Как упоминалось ранее, assertEquals()в первую очередь речь идет об интерпретируемом значении, будь то манипуляция типом или объект с методом представления __magic ( __toString()например).

Хороший вариант использования assertSame()- это тестирование одноэлементной фабрики.

class CacheFactoryTest extends TestCase
{
    public function testThatCacheFactoryReturnsSingletons()
    {
        $this->assertSame(CacheFactory::create(), CacheFactory::create());
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.