bt3's avatar
Level 9

Debug PHPUnit tests that only fail occasionally based on factory data

Hi there,

I'm working with a financial application that basically accepts inputs from a user, does some calculations, and spits back "scenarios", think financial planning. There's a few options the user can set that change how the calculations work, but at the end of the day, there's an inherent amount of flexibility in the amount of data that is processed.

As I've started to build up my testing suite, I have a series of tests that run on seeded data, and another set of tests that run based on factories. The latter of which is hugely beneficial because it allows me to test a hypothetical combination of data.

Most of my assertions are easy; lots of assertTrue type things, where I calculate an $expectedValue then I compare it the $actualValue.

Anywhere, when I run the test suite for factory data, I've noticed recently that on occasion, a test will fail, and the only feedback I get is something like failed asserting that 10.50 equals 10 or something similar. Obviously since the data is randomly generated, that information by itself isn't actionable. Ideally I'd be able to view the entire $record, and maybe even a collection of all $records. Can PHPUnit trigger a dump to logs based on a failure?

Thoughts on the best way to debug tests like this that only fail occasionally because of the variability of the data?

My original thought was to switch to another mysql database (instead of the in-memory sqlite one), then remove the RefreshDatabase trait, but this doesn't have predictable results and just leaves me with a mound of data that I still wouldn't be able to debug the above.

I'm fairly new to PHPUnit, so unsure if there's better ways to be addressing test failures, especially if they only happen rarely.

0 likes
2 replies
click's avatar
click
Best Answer
Level 35

Maybe you can play around with onNotSuccessfulTest(Throwable $t) see https://phpunit.readthedocs.io/en/9.3/fixtures.html

or wrap your test in a try{ } catch (\Throwable $e) { } and handle the exception yourself. This way you probably have access to your variables you are working with it.

try {
   $this->assertTrue(false);
} catch (\Throwable $t) {
    dump('Hello');
    throw $t;
}

Maybe someone has a better suggestion

bt3's avatar
Level 9

Ah yes, for some reason I didn't think a try catch would work. Seems like a decent approach for the time being, and is working to just raw dump the data I'm looking for to debug. Much appreciate the second pair of eyes on this.

Please or to participate in this conversation.