sebastianbergmann / phpunit

The PHP Unit Testing framework.
https://phpunit.de/
BSD 3-Clause "New" or "Revised" License
19.69k stars 2.2k forks source link

`assertContainsEquals()` does not work with `DateInterval` objects #5922

Open sebastianstucke87 opened 2 months ago

sebastianstucke87 commented 2 months ago
Q A
PHPUnit version 11.3.0
PHP version 8.3.10
Installation Method Composer

Summary

assertContainsEquals does not work with \DateInterval

Current behavior

test_2 failes with ErrorException: Warning: Cannot compare DateInterval objects

How to reproduce

public function test_1()
{
    $a = \DateInterval::createFromDateString('1 DAY');
    $b = \DateInterval::createFromDateString('1 DAY');

    // ok
    $this->assertEquals($a, $b);
    $this->assertEqualsCanonicalizing($a, $b);
}

public function test_2()
{
    $a = \DateInterval::createFromDateString('1 DAY');
    $b = \DateInterval::createFromDateString('1 DAY');

    // ErrorException: Warning: Cannot compare DateInterval objects
    $this->assertContainsEquals($a, [$b]);
}

Expected behavior

test_2 passes without warnings

sebastianbergmann commented 2 months ago

I can confirm this with PHPUnit 11.3, but I do not understand how this could have worked with previous versions such as PHPUnit 10.5.

Issue5922Test.php

<?php declare(strict_types=1);
namespace PHPUnit\TestFixture\Issue5922;

use DateInterval;
use PHPUnit\Framework\TestCase;

final class Issue5922Test extends TestCase
{
    public function testOne(): void
    {
        $a = DateInterval::createFromDateString('1 day');
        $b = DateInterval::createFromDateString('1 day');

        $this->assertContainsEquals($a, [$b]);
    }
}

PHPUnit 10.5

PHPUnit 10.5.29-16-g9de5bef4ac by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.10
Configuration: /usr/local/src/phpunit/phpunit.xml

F                                                                   1 / 1 (100%)

Time: 00:00.014, Memory: 10.00 MB

There was 1 failure:

1) PHPUnit\TestFixture\Issue5922\Issue5922Test::testOne
Failed asserting that an array contains DateInterval Object #800 (
    'from_string' => true,
    'date_string' => '1 day',
).

/usr/local/src/phpunit/src/Framework/Constraint/Constraint.php:106
/usr/local/src/phpunit/src/Framework/Constraint/Constraint.php:51
/usr/local/src/phpunit/src/Framework/Assert.php:1870
/usr/local/src/phpunit/src/Framework/Assert.php:135
/home/sb/Issue5922Test.php:14
/usr/local/src/phpunit/src/Framework/TestCase.php:1188
/usr/local/src/phpunit/src/Framework/TestCase.php:687
/usr/local/src/phpunit/src/Framework/TestRunner.php:106
/usr/local/src/phpunit/src/Framework/TestCase.php:517
/usr/local/src/phpunit/src/Framework/TestSuite.php:380
/usr/local/src/phpunit/src/TextUI/TestRunner.php:64
/usr/local/src/phpunit/src/TextUI/Application.php:202

FAILURES!
Tests: 1, Assertions: 1, Failures: 1, Warnings: 1.

PHPUnit 11.3

PHPUnit 11.3.0-22-g18ec59af3f by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.10
Configuration: /usr/local/src/phpunit/phpunit.xml

F                                                                   1 / 1 (100%)

Time: 00:00.013, Memory: 10.00 MB

There was 1 failure:

1) PHPUnit\TestFixture\Issue5922\Issue5922Test::testOne
Failed asserting that an array contains DateInterval Object #822 (
    'from_string' => true,
    'date_string' => '1 day',
).

/usr/local/src/phpunit/src/Framework/Constraint/Constraint.php:103
/usr/local/src/phpunit/src/Framework/Constraint/Constraint.php:56
/usr/local/src/phpunit/src/Framework/Assert.php:2024
/usr/local/src/phpunit/src/Framework/Assert.php:233
/home/sb/Issue5922Test.php:14
/usr/local/src/phpunit/src/Framework/TestCase.php:1234
/usr/local/src/phpunit/src/Framework/TestCase.php:515
/usr/local/src/phpunit/src/Framework/TestRunner/TestRunner.php:86
/usr/local/src/phpunit/src/Framework/TestCase.php:362
/usr/local/src/phpunit/src/Framework/TestSuite.php:394
/usr/local/src/phpunit/src/TextUI/TestRunner.php:64
/usr/local/src/phpunit/src/TextUI/Application.php:207

--

1 test triggered 1 PHP warning:

1) /usr/local/src/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php:31
Cannot compare DateInterval objects

Triggered by:

* PHPUnit\TestFixture\Issue5922\Issue5922Test::testOne
  /home/sb/Issue5922Test.php:9

FAILURES!
Tests: 1, Assertions: 1, Failures: 1, Warnings: 1.
mgleska commented 2 months ago

We can find answer in PHP documentation: https://www.php.net/manual/en/class.dateinterval.php

Since there is no well defined way to compare date intervals, DateInterval instances are incomparable.

Simple test:

<?php

$a = DateInterval::createFromDateString('1 day');
$b = DateInterval::createFromDateString('1 day');

var_dump($a == $b);

and result:

PHP Warning:  Cannot compare DateInterval objects in C:\prog\phpunit\test.php on line 6

Warning: Cannot compare DateInterval objects in C:\prog\phpunit\test.php on line 6
bool(false)

I think, we should consider this issue as bug in PHPUnit version 10.