Adopting a different test syntax on top of the same engine, evaluated properly rather than by preference.
// the same test, both ways
public function testItRejectsAnEmptyBasket(): void
{
$this->expectException(EmptyBasket::class);
(new Checkout())->place(new Basket([]));
}
it('rejects an empty basket', function () {
(new Checkout())->place(new Basket([]));
})->throws(EmptyBasket::class);
A month of writing new tests in one and maintaining old tests in the other produced a clear answer for us and it is not a general one: the closure syntax reads better and the stack traces read worse, and on a codebase where debugging a failing test is the common activity, the traces won. Both run on PHPUnit, so the decision is reversible, which is the reason it was worth trying at all.