Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

Ответ 2

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


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

Ответ 3

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

Ответ 4

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

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"

Ответ 5

Многие из текущих ответов обсуждают, как получить доступ и проанализировать время продолжительности в файле журнала. Я поделюсь двумя способами изменения вывода CLI в версии 3.7.38 phpUnit (это то, что 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>

Ответ 6

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

Ответ 7

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

  • Запишите текущее время перед тестом, в setUp,
  • И подсчитайте время, которое проверили в tearDown.


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

Ответ 8

Здесь приведен полный пример, основанный на идее от edorians. Протестировано на 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.

Ответ 9

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

$phpunit --log-json testExport.json

Ответ 10

Мне понравился ответ @adri. Я начал с этого:

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). Кроме того, вы можете запускать свои тесты и видеть их вывод как обычно... ваш терминал не просто сидит там, пока тесты не будут выполнены.

Ответ 11

Основываясь на ответах выше, я создал небольшую библиотеку для отображения времени выполнения. https://github.com/santik/phpunit-profiler