assertEquals is loose; assertSame is what you meant

assertEquals compares with ==, which is PHP’s loose comparison — so a method that has quietly started returning the string "0" where it used to return the integer 0 passes every test it has. assertSame compares with === and would have caught it on the first run.

$this->assertEquals(0, '');       // passes
$this->assertEquals(0, '0');      // passes
$this->assertEquals(1, true);     // passes
$this->assertEquals(
    array('a' => 1, 'b' => 2),
    array('b' => 2, 'a' => 1)     // passes: key order is ignored
);

$this->assertSame(0, '0');        // fails, correctly
$this->assertSame(1.0, 1);        // fails, correctly

// floats are the exception: never identity, always a delta
$this->assertEquals(0.3, 0.1 + 0.2, '', 0.00001);

The rule that survives contact with a real suite is assertSame by default and assertEquals deliberately. Two cases genuinely want the loose version. Floating point, where identity is the wrong question and the fourth argument is the delta. And objects, where assertEquals compares attributes recursively while assertSame demands the very same instance — which is almost never what the test means. Arrays sit in between: assertEquals ignores key order and assertSame does not, so a test asserting on the result of a query with no ORDER BY is using the loose one to cover for a bug in the query. The assertContains family has the same split, expressed as an extra boolean argument rather than a second method name, which is why it is so often left at the default.