{"record":{"id":"0a462f9786df5853","repo":"sebastianbergmann/comparator","slug":"failed-asserting-that-s-matches-expected-s","errorCode":null,"errorMessage":"Failed asserting that %s matches expected %s.","messagePattern":"Failed asserting that (.+?) matches expected (.+?)\\.","errorType":"exception","errorClass":"ComparisonFailure","httpStatus":null,"severity":"error","filePath":"src/NumericComparator.php","lineNumber":58,"sourceCode":"        assert(is_numeric($expected));\n        assert(is_numeric($actual));\n\n        if ($this->isInfinite($expected) && $this->isInfinite($actual)) {\n            if ($expected < 0 && $actual < 0) {\n                return;\n            }\n\n            if ($expected > 0 && $actual > 0) {\n                return;\n            }\n        }\n\n        if (($this->isInfinite($actual) xor $this->isInfinite($expected)) ||\n            ($this->isNan($actual) || $this->isNan($expected)) ||\n            abs($actual - $expected) > $delta) {\n            $exporter = $this->exporter();\n\n            throw new ComparisonFailure(\n                $expected,\n                $actual,\n                '',\n                '',\n                sprintf(\n                    'Failed asserting that %s matches expected %s.',\n                    $exporter->export($actual),\n                    $exporter->export($expected),\n                ),\n                $this->contextLines(),\n            );\n        }\n    }\n\n    private function isInfinite(mixed $value): bool\n    {\n        return is_float($value) && is_infinite($value);\n    }","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/sebastianbergmann/comparator/blob/00837a9d227b4e123b0b42a91736960f6b0b3583/src/NumericComparator.php#L40-L76","documentation":"NumericComparator compares int/float values within a delta ($delta defaults to 0.1 for its PHPUnit usage). It throws a ComparisonFailure when exactly one side is infinite, either side is NAN, or the absolute difference exceeds the delta. NAN comparisons fail by definition since NAN != NAN.","triggerScenarios":"assertEquals() on numbers where: one value is INF/NAN (e.g. from division by zero, log(0), sqrt(-1)), or abs($actual - $expected) > $delta, e.g. assertEquals(1.0, 1.2) with default or too-tight delta.","commonSituations":"Comparing floating-point results of math functions that produce NAN/INF (log(0), atanh(>1), 1/0 via intdiv overflow paths); accumulated float precision error exceeding the delta; forgetting that the delta defaults to 0.1 rather than exact equality.","solutions":["Check the failure diff: if NAN/INF appears, find where the computation becomes undefined (log of non-positive, division by zero, sqrt of negative) and guard the input","Add a delta tolerant of floating-point precision: assertEqualsWithDelta($expected, $actual, 1e-9)","Fix the calculation or update the expected value if the difference is a real regression/feature change","Convert to exact comparisons on scaled integers or strings when float precision makes equality unstable"],"exampleFix":"// before\n$this->assertEquals(0.3, $a + $b); // 0.30000000000000004 fails\n// after\n$this->assertEqualsWithDelta(0.3, $a + $b, 0.000000001);","handlingStrategy":"validation","validationCode":"if (is_nan($actual) || is_infinite($actual) || is_nan($expected) || is_infinite($expected)) {\n    throw new InvalidArgumentException('Cannot compare NAN/INF values');\n}\nif (abs($actual - $expected) > $tolerance) { /* handle before asserting */ }","typeGuard":"function isComparableNumber(mixed $v): bool { return is_int($v) || (is_float($v) && !is_nan($v) && !is_infinite($v)); }","tryCatchPattern":"try {\n    $comparator->assertEquals($expected, $actual, $delta);\n} catch (ComparisonFailure $e) {\n    // inspect exporter output; treat NAN/INF as a computation bug upstream\n}","preventionTips":["Guard math inputs against undefined operations (log of <=0, sqrt of negative, division by zero) before comparing","Use assertEqualsWithDelta with an explicit precision-appropriate delta instead of relying on the 0.1 default","Remember NAN fails every comparison including against itself; check is_nan() explicitly"],"tags":["php","phpunit","floating-point","assertion"],"backgroundTag":"value-out-of-range","analyzedSha":"00837a9d227b4e123b0b42a91736960f6b0b3583","analyzedAt":"2026-09-15T03:36:55.154Z","contentChangedAt":"2026-09-15T03:36:55.154Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}