PHPUnit "FAILURES! Tests: N, Assertions: M, Failures: K" in CI
PHPUnit ran your tests and one or more assertions did not hold, so it exits non-zero and fails the job. Either the code is genuinely wrong, or the test depends on something that differs between local and CI - timezone, locale, ordering, or missing config.
What this error means
PHPUnit prints "FAILURES!" with a summary like "Tests: 42, Assertions: 118, Failures: 3" and details each "Failed asserting that ...". The step exits 1 (or 2 with errors).
1) App\Tests\InvoiceTest::testTotal
Failed asserting that 100.0 matches expected 99.99.
/app/tests/InvoiceTest.php:31
FAILURES!
Tests: 42, Assertions: 118, Failures: 1.Common causes
A genuine assertion failure
The code produces a value the test does not expect. The "Failed asserting that X matches expected Y" line shows the exact mismatch.
CI-only environment differences
Tests that depend on timezone, locale, current date, random ordering, or an env var/config present locally but not in CI fail only on the runner.
How to fix it
Read the diff and fix code or expectation
Use the failure detail to decide whether the code or the assertion is wrong, and run just that test while iterating.
vendor/bin/phpunit --filter testTotal --testdoxMake the environment deterministic
- Pin timezone and locale (
date.timezone,LC_ALL) so CI matches local. - Provide every env var/config the tests need in the CI job (e.g. a
.env.testing). - Freeze "now" with a clock abstraction instead of
new DateTime()in assertions.
How to prevent it
- Set timezone/locale explicitly in
phpunit.xmlor the CI env. - Avoid real time, randomness, and network in unit tests; inject them.
- Run the suite locally with the CI PHP version before pushing.