Время выполнения тестов печати PHPUnit

есть ли способ распечатать время выполнения каждого теста с помощью PHPUnit?

6 ответов


вы можете реализовать свой собственный тестовый бегун, например, путем расширения PHPUnit_TextUI_TestRunner и сделать его собирать и печатать раз работать.


добавить еще несколько способов:


вы можете написать пользовательский тест слушателя и добавить его в XML-файл. В этом прослушивателе вы можете получить доступ к $testResult->time(). Несколько строк в вашем phpunit.xml и 10-строчный класс PHP. Не слишком много хлопот.

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

если вы создаете junit.xml в любом случае (для CI или при создании покрытия кода) все номера есть в любом случае, и с помощью простого XSLT вы можете сделать их еще больше читаемый.

пример junit.в XML

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="DemoTest" file="/home/edo/foo.php" tests="2" assertions="2" failures="1" errors="0" time="0.007727">
    <testcase name="testPass" class="DemoTest" file="/home/edo/foo.php" line="4" assertions="1" time="0.003801"/>
    <testcase name="testFail" class="DemoTest" file="/home/edo/foo.php" line="8" assertions="1" time="0.003926">
      <failure type="PHPUnit_Framework_ExpectationFailedException">DemoTest::testFail
Failed asserting that &lt;boolean:false&gt; is true.

/home/edo/foo.php:9
</failure>
    </testcase>
  </testsuite>
</testsuites>

и с такой трансформацией:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h1>Tests</h1>
    <xsl:for-each select="testsuites/testsuite">
      <h2><xsl:value-of select="@name"/></h2>
      <ul>
        <xsl:for-each select="testcase">
          <li>
            <xsl:value-of select="@name"/> : <xsl:value-of select="@time"/>
            <xsl:if test="failure">
              <b>Failed !</b>
              <i><xsl:value-of select="*"/></i>
            </xsl:if>
          </li>
        </xsl:for-each>
      </ul>
    </xsl:for-each>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

вы получаете строки, показывающие вам:<li>testPass : 0.003801</li> (HTML-это просто пример, он должен быть легко адаптируемым).

ссылка на мой собственный пост в блоге здесь:http://edorian.github.io/2011-01-19-creating-your-custom-phpunit-output.formats/ для материала xslt.


просто добавить --log-junit " my_tests_log.XML-код" а затем откройте этот файл с приложением электронной таблицы (Excel, Numbers, Calc), чтобы просмотреть его. Вы получаете всю информацию, которую вы просите, и вы можете сортировать по времени выполнения теста.


Если вам не нравится писать Testlistener, как уже было предложено, можно использовать следующий скрипт для парсинга результат теста JSON PHPUnit в более удобном для чтения формате:

alias phpunit-report-runtime="phpunit --log-json php://stdout \
    | awk '$NF ~ '/,/' && $1 ~ /\"(test|time)\"/' \
    | cut -d: -f2- \
    | sed \"N;s/\n/--/\"  \
    | sed \"s/,//\"   \
    | awk 'BEGIN{FS=\"--\"}; {print $2 $1}' | sort -r \
    | head -n 5"
- это <time in seconds>, <test method>. Пример вывода:
 $ phpunit-report-runtime
 0.29307007789612, "VCR\Util\SoapClientTest::testDoRequestHookDisabled"
 0.16475319862366, "VCR\CassetteTest::testRecordAndPlaybackRequest"
 0.092710018157959, "VCR\Util\SoapClientTest::testDoRequest"
 0.031861782073975, "VCR\LibraryHooks\SoapTest::testShouldInterceptCallWhenEnabled"
 0.026772022247314, "VCR\LibraryHooks\AbstractFilterTest::testRegisterAlreadyRegistered"

многие из текущих ответов обсуждают, как получить доступ и проанализировать время продолжительности в файле журнала. Я поделюсь двумя способами изменения вывода CLI в phpUnit версии 3.7.38 (что по умолчанию использует Travis-CI для PHP), основываясь на @edorian's неполный ответ.


используйте пользовательский принтер для переопределения вывода CLI. Я не могу найти документацию для принтеров, но они, похоже, поддерживаются. Вы можете увидеть, какие методы доступны в исходный код.

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
        );
    }
}

затем добавьте эти строки в качестве атрибутов в phpunit на :

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

вы также можете использовать --printer опция CLI, но это не играет хорошо с пространствами имен.


вы можете добавить к выходу CLI, в отличие от переопределения его, с помощью TestListener, реализуя PHPUnit_Framework_TestListener интерфейс (это тот же интерфейс, который используют принтеры). Это все равно будет печатать ., S и F так обязательно объясните это, если хотите.

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)
    {
    }
}

в версии 3.8 и выше есть PHPUnit_Framework_BaseTestListener это может быть расширено, чтобы вы определяли только методы, которые хотите переопределить.

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

чтобы включить нового слушателя, добавьте эти строки в свой :

<listeners>
    <listener class="TestDurationListener" file="path/to/TestDurationListener.php" />
</listeners>

Я думаю, вы могли бы использовать setUp и tearDown методы (которые называются в начале и конце каждого теста, соответственно) в :

  • журнал текущее время перед тестом, в setUp,
  • и вычислить время, которое занял тест, в tearDown.


Конечно, вам придется делать это в каждом из ваших тестовых классов-или в суперклассе, который будет унаследован всеми вашими тестовыми классами.