Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assertSame ignoring key order #6088

Open
Seldaek opened this issue Dec 18, 2024 · 2 comments
Open

assertSame ignoring key order #6088

Seldaek opened this issue Dec 18, 2024 · 2 comments
Labels
feature/assertion Issues related to assertions and expectations type/enhancement A new idea that should be implemented

Comments

@Seldaek
Copy link
Contributor

Seldaek commented Dec 18, 2024

Key order when we're talking about associative arrays is quite often irrelevant, especially when checking stuff that will end up being json serialized where dictionaries do not guarantee the key order.

Right now I'm stuck between using assertEqualsCanonicalizing and risking datatype errors, e.g.:

        $this->assertEqualsCanonicalizing(['foo' => 1], ['foo' => '1']); // true

Or use assertSame but then key order tends to make tests extra brittle. Having an option for assertSame or a new assertDictionarySame or something would be great.

@Seldaek Seldaek added the type/enhancement A new idea that should be implemented label Dec 18, 2024
@sebastianbergmann sebastianbergmann added the feature/assertion Issues related to assertions and expectations label Dec 19, 2024
@mfn
Copy link

mfn commented Dec 19, 2024

I've been working with JSON api stuff for years and always required this (I wanted the assertSame safety so badly) and almost a decade ago came up with this, which I still use today and it hardly changed. May it be useful to others or serve as inspiration:

    /**
     * Asserts that the non-array values of the arrays are the same
     * (using assertSame) but the order of keys within the arrays
     * does not matter.
     *
     * Implementation detail:
     * - uses SORT_NATURAL for sorting keys so that the order for keys like
     *   0 and "a" are defined (without it, sort will return them in order
     *   of 0,"a" or "a",0).
     *
     * Inspired by http://stackoverflow.com/a/33029270/47573
     *
     * @param array $aryPath Only used internally for constructing the
     *                       assert message helping to figure out where the arrays differ.
     */
    public static function assertArraySame(array $expectedAry, array $actualAry, array $aryPath = ['/']): void
    {
        if (['/'] === $aryPath) {
            // The built-in assert has very useful diffing capability.
            // By first checking whether the array "equals" we
            // already established lots of tests we would
            // otherwise # need to do ourselves (e.g.
            // checking if no keys are missing, etc.)
            Assert::assertEquals($expectedAry, $actualAry);
        }

        foreach ($expectedAry as $expectedKey => $expectedValue) {
            $actualValue = $actualAry[$expectedKey];

            $currentPath = $aryPath;
            $currentPath[] = $expectedKey;

            if (\is_object($expectedValue) && \is_object($actualValue)) {
                Assert::assertEquals($expectedValue, $actualValue);

                continue;
            }

            if (\is_array($expectedValue) && \is_array($actualValue)) {
                static::assertArraySame($expectedValue, $actualValue, $currentPath);

                continue;
            }

            Assert::assertSame(
                $expectedValue,
                $actualValue,
                'Failed asserting that values in array at ' . implode('/', $currentPath) . ' are the same.'
            );
        }
    }

@Seldaek
Copy link
Contributor Author

Seldaek commented Dec 19, 2024

Thanks for sharing the code. This indeed is probably not that hard to implement, but I believe it might qualify as something worth having built-in, which is why I opened the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature/assertion Issues related to assertions and expectations type/enhancement A new idea that should be implemented
Projects
None yet
Development

No branches or pull requests

3 participants