PHPUnit print tests execution time

前端 未结 9 1390
天涯浪人
天涯浪人 2021-02-11 21:04

is there a way to print the execution time of each test with PHPUnit?

相关标签:
9条回答
  • 2021-02-11 21:25

    Many of the current answers discuss how to access and analyze the duration times in the log file. I will share two ways to modify the CLI output in phpUnit version 3.7.38 (which is what Travis-CI uses for PHP by default), building on @edorian's incomplete answer.


    Use a custom printer to override the CLI output. I can't find any documentation for printers but they appear to be supported. You can see which methods are available in the source code.

    class TestDurationPrinter extends PHPUnit_TextUI_ResultPrinter
    {
        public function endTest(PHPUnit_Framework_Test $test, $time)
        {
            printf("Test '%s' ended and took %s seconds.\n", 
               $test->getName(),
               $time
            );
        }
    }
    

    Then add these lines as attributes to phpunit in the phpunit.xml file:

    printerFile="path/to/TestDurationPrinter.php"
    printerClass="TestDurationPrinter"
    

    You can also use the --printer CLI option but that doesn't play well with namespaces.


    You can add to the CLI output, as opposed to overriding it, with a TestListener by implementing the PHPUnit_Framework_TestListener interface (this is the same interface that printers use). This will still print ., S, and F so be sure to account for that, if you desire.

    class TestDurationListener implements PHPUnit_Framework_TestListener
    {
        public function endTest(PHPUnit_Framework_Test $test, $time)
        {
            printf("Test '%s' ended and took %s seconds.\n", 
               $test->getName(),
               $time
            );
        }
    
        public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
        {
        }
    
        public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
        {
        }
    
        public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
        {
        }
    
        public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time)
        {
        }
    
        public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
        {
        }
    
        public function startTest(PHPUnit_Framework_Test $test)
        {
        }
    
        public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
        {
        }
    
        public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
        {
        }
    }
    

    In version 3.8 and above there is a PHPUnit_Framework_BaseTestListener that can be extended so that you only define the methods you want to override.

    class TestDurationListener extends PHPUnit_Framework_BaseTestListener
    {
        public function endTest(PHPUnit_Framework_Test $test, $time)
        {
            printf("Test '%s' ended.\n", $test->getName());
        }
    }
    

    To include your new listener, add these lines to your phpunit.xml file:

    <listeners>
        <listener class="TestDurationListener" file="path/to/TestDurationListener.php" />
    </listeners>
    
    0 讨论(0)
  • 2021-02-11 21:30

    In my opinion, the simplest solution is to export test statistic as json:

    $ phpunit --log-json testExport.json

    0 讨论(0)
  • 2021-02-11 21:31

    Just add --log-junit "my_tests_log.xml" and then open this file with spreadsheet application (Excel, Numbers, Calc) to view it. You get all information you ask for, and you can sort by test execution time.

    0 讨论(0)
  • 2021-02-11 21:38

    I guess you could use the setUp and tearDown methods (which are called at the beginning and end of each test, respectively) to :

    • Log the current time before the test, in setUp,
    • And calculate the time the test took, in tearDown.


    Of course, you'll have to do this in each one of your test classes -- or in a super-class which will be inherited by all your test classes.

    0 讨论(0)
  • 2021-02-11 21:38

    Well, you can have it export the execution time with Logging. It's not directly outputted as the result, but you could write a pretty report viewer that would output the results of the log file (either from JSON or XML). That should get you what you want...

    0 讨论(0)
  • 2021-02-11 21:41

    Here's a complete example based on the idea from edorians answer. Tested on PHPunit 4.

    Create the following PHP class:

    class ProfilingTestListener extends PHPUnit_Framework_BaseTestListener
    {
        public function endTest(PHPUnit_Framework_Test $test, $time)
        {
            printf("Test '%s' ended.\tTotal time %s s.\tTest time %s s.\n",
                str_pad($test->toString(), 50),
                number_format($test->getTestResultObject()->time(), 3),
                number_format($time, 3)
            );
        }
    }
    

    Add the following to your phpunit.xml:

    <phpunit ..>
        ...
        <listeners>
            <listener class="ProfilingTestListener"></listener>
        </listeners>
        ...
    </phpunit>
    

    Example output:

    PHPUnit 4.7.7 by Sebastian Bergmann and contributors.
    
    Test 'FooTest::testFoo              ' ended.    Total time 2.050 s. Test time 0.026 s. 
    .Test 'FooTest::testBar             ' ended.    Total time 2.077 s. Test time 1.000 s.
    .Test 'FooTest::testBar2            ' ended.    Total time 3.077 s. Test time 0.730 s.
    
    0 讨论(0)
提交回复
热议问题