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

PHPUnit 10 Assertion failure results in "Uncaught Error: Class "PHPUnit\Framework\TestFailure" not found" #1421

Open
mnocon opened this issue Feb 8, 2023 · 1 comment

Comments

@mnocon
Copy link
Contributor

mnocon commented Feb 8, 2023

Hi!

When a PHPUnit assertion fails in a Behat Context class the tests fail with:

~/Desktop/repos/behat-phpunit10 on main !2 ?2 ❯ vendor/bin/behat                                                                                                                                                       14.17.0 at 10:36:00
Feature: PHPUnit 10 exception

  Scenario: Trigger PHPUnitExceptionStringer # features/Reproducer.feature:3
    Given ExceptionStringer is triggered     # FeatureContext::triggerExceptionStringer()
PHP Fatal error:  Uncaught Error: Class "PHPUnit\Framework\TestFailure" not found in /Users/mareknocon/Desktop/repos/behat-phpunit10/behat/src/Behat/Testwork/Exception/Stringer/PHPUnitExceptionStringer.php:49
Stack trace:
#0 /Users/mareknocon/Desktop/repos/behat-phpunit10/behat/src/Behat/Testwork/Exception/ExceptionPresenter.php(93): Behat\Testwork\Exception\Stringer\PHPUnitExceptionStringer->stringException(Object(PHPUnit\Framework\ExpectationFailedException), 1)
#1 /Users/mareknocon/Desktop/repos/behat-phpunit10/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStepPrinter.php(174): Behat\Testwork\Exception\ExceptionPresenter->presentException(Object(PHPUnit\Framework\ExpectationFailedException))
#2 /Users/mareknocon/Desktop/repos/behat-phpunit10/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStepPrinter.php(95): Behat\Behat\Output\Node\Printer\Pretty\PrettyStepPrinter->printException(Object(Behat\Testwork\Output\Printer\StreamOutputPrinter), Object(Behat\Behat\Tester\Result\ExecutedStepResult))
#3 /Users/mareknocon/Desktop/repos/behat-phpunit10/behat/src/Behat/Behat/Output/Node/EventListener/AST/StepListener.php(119): Behat\Behat\Output\Node\Printer\Pretty\PrettyStepPrinter->printStep(Object(Behat\Testwork\Output\NodeEventListeningFormatter), Object(Behat\Gherkin\Node\ScenarioNode), Object(Behat\Gherkin\Node\StepNode), Object(Behat\Behat\Tester\Result\ExecutedStepResult))
#4 /Users/mareknocon/Desktop/repos/behat-phpunit10/behat/src/Behat/Behat/Output/Node/EventListener/AST/StepListener.php(65): Behat\Behat\Output\Node\EventListener\AST\StepListener->printStepOnAfterEvent(Object(Behat\Testwork\Output\NodeEventListeningFormatter), Object(Behat\Behat\EventDispatcher\Event\AfterStepTested))

stopping the test execution.

I've created a reproducer for this issue, if you'd like to test it yourself:
https://github.com/mnocon/behat-phpunit10

PHPunit 9 used the TestFailure class to stringify an Exception:
https://github.com/sebastianbergmann/phpunit/blob/9.6/src/Framework/Exception/Exception.php#L58-L67

but in PHPUnit 10 ThrowableToStringMapper is responsible for that:
https://github.com/sebastianbergmann/phpunit/blob/10.0/src/Framework/Exception/Exception.php#L57-L69
(and the TestFailure class is gone).

I made an attempt at solving this, in #1422

@mnocon mnocon changed the title PHPUnit 10 Assertions failure results in "Uncaught Error: Class "PHPUnit\Framework\TestFailure" not found" PHPUnit 10 Assertion failure results in "Uncaught Error: Class "PHPUnit\Framework\TestFailure" not found" Feb 8, 2023
@uuf6429
Copy link

uuf6429 commented Apr 7, 2023

Hey, I saw the merged PR and I have a few follow up questions:

  1. since it has been merged, shouldn't this ticket be closed (if the problem is now solved)?
  2. looking at the code of the PR, I disagree a bit on how it works:
    1. In my understanding, PHPUnitExceptionStringer->supportsException should have prevented the original problem from happening, so I would recommend looking into why it wasn't
    2. The code of PHPUnitExceptionStringer->stringException is now a bit messier.. "if class exists return x; if class does not exist return z; else it must exist and therefore return y..", IMHO this would be clearer and more readable:
    switch (true) {
        case class_exists('PHPUnit\\Util\\ThrowableToStringMapper'):
            return trim(\PHPUnit\Util\ThrowableToStringMapper::map($exception));
    
        case class_exists('PHPUnit\\Framework\\TestFailure'):
            // PHPUnit assertion exceptions do not include expected / observed info in their
            // messages, but expect the test listeners to format that info like the following
            // (see e.g. PHPUnit_TextUI_ResultPrinter::printDefectTrace)
            return trim(\PHPUnit\Framework\TestFailure::exceptionToString($exception));
    
        case class_exists('PHPUnit_Framework_TestFailure'):
            return trim(\PHPUnit_Framework_TestFailure::exceptionToString($exception));
    
        default:
            // TODO this should also be somehow handled
    }
    It now also exposes the original flaw, which the patch didn't fix adequately IMO.
  3. Shouldn't PHPUnitExceptionStringer->supportsException also be updated to handle the new formatter?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants