Время выполнения тестов печати PHPUnit - PullRequest
23 голосов
/ 04 марта 2011

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

Ответы [ 10 ]

20 голосов
/ 07 марта 2011

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


Вы можете написать пользовательский тестовый прослушиватель и добавить его в файл 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.

15 голосов
/ 21 июля 2011

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

9 голосов
/ 26 января 2014

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

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"
6 голосов
/ 11 июня 2015

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


Используйте пользовательский принтер для переопределения вывода 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 в файле phpunit.xml:

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

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

<listeners>
    <listener class="TestDurationListener" file="path/to/TestDurationListener.php" />
</listeners>
5 голосов
/ 04 марта 2011

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

3 голосов
/ 20 октября 2015

Вот полный пример, основанный на идее эдорианского ответа.Протестировано на PHPunit 4.

Создайте следующий класс PHP:

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

Добавьте в свой phpunit.xml следующее:

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

Пример вывода:

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.
3 голосов
/ 04 марта 2011

Ну, вы можете экспортировать время выполнения с помощью Регистрация . Он не выводится напрямую в качестве результата, но вы можете написать красивую программу просмотра отчетов, которая выводит результаты файла журнала (из JSON или XML). Это должно дать вам то, что вы хотите ...

3 голосов
/ 04 марта 2011

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

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


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

1 голос
/ 11 сентября 2017

На мой взгляд, самое простое решение - экспортировать статистику теста как json:

$ phpunit --log-json testExport.json

0 голосов
/ 26 января 2015

Мне понравился ответ @ Адри. Это заставило меня начать это:

alias phpunittime=" | awk '\$NF ~ '/,/' && \$1 ~ /\"(test|time)\"/' \
    | cut -d: -f2- \
    | sed \"N;s/\n/--/\"  \
    | sed \"s/,//\"   \
    | awk 'BEGIN{FS=\"--\"}; {print \$2 \$1}' | sort -r \
    | head"

Для использования вам необходимо настроить PHP-модуль для вывода в файл журнала JSON. Для этого сделайте ваш phpunit.xml похожим на это:

<phpunit>
    <logging>
        <log type="json" target="/tmp/logfile.json"/>
    </logging>
</phpunit>

Тогда используйте вот так:

$ cat /tmp/logfile.json | phpunittime

Чтобы увидеть больше или меньше 10 временных интервалов, скажем, 2 или 19, используйте -n 2 или -n 19 соответственно в конце.

Что приятно в этом, так это то, что он не делает предположений о том, как вы вызываете / запускаете сам phpunit (в моем случае я использую CakePHP и запускаю свою команду следующим образом: Console/cake test app). Кроме того, вы можете запускать свои тесты и видеть их вывод как нормальный ... ваш терминал не просто сидит там, пока тесты не будут завершены.

...