PHPUnitを使用して各テストの実行時間を出力する方法はありますか?
10 に答える
さらにいくつかの方法を追加するには:
カスタムテストリスナーを作成して、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 <boolean:false> 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は単なる例であり、簡単に適応できるはずです)。
ここで私自身のブログ投稿を参照してください:https : //edorian.github.io/2011-01-19-creating-your-custom-phpunit-output.formats/xsltのもの。
--log-junit "my_tests_log.xml"を追加し、スプレッドシートアプリケーション(Excel、Numbers、Calc)でこのファイルを開いて表示するだけです。必要なすべての情報を取得し、テストの実行時間で並べ替えることができます。
すでに提案されているように、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"
現在の回答の多くは、ログファイルの継続時間にアクセスして分析する方法について説明しています。@edorianの不完全な回答に基づいて、phpUnitバージョン3.7.38(Travis-CIがデフォルトでPHPに使用するもの)でCLI出力を変更する2つの方法を共有します。
カスタムプリンターを使用して、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"
CLIオプションを使用することもでき--printer
ますが、名前空間ではうまく機能しません。
インターフェイスを実装することにより、TestListenerを使用して、CLI出力をオーバーライドするのではなく、CLI出力に追加でき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>
たとえば、PHPUnit_TextUI_TestRunner
実行時間を延長して収集および印刷することにより、独自のテストランナーを実装できます。
setUp
とtearDown
メソッド(各テストの最初と最後にそれぞれ呼び出されます)を使用して、次のことができると思います。
- テスト前の現在の時刻を、に記録します
setUp
。 - そして、テストにかかった時間を計算し
tearDown
ます。
もちろん、これは各テストクラスで行う必要があります。または、すべてのテストクラスに継承されるスーパークラスで行う必要があります。
さて、 Loggingを使用して実行時間をエクスポートさせることができます。結果として直接出力されるわけではありませんが、ログファイルの結果(JSONまたはXMLのいずれかから)を出力するきれいなレポートビューアーを作成できます。それはあなたが望むものを手に入れるはずです...
これは、edoriansの回答からのアイデアに基づいた完全な例です。PHPunit4でテスト済み。
次の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.
私の意見では、最も簡単な解決策は、検定統計量をjsonとしてエクスポートすることです。
$ phpunit --log-json testExport.json
@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"
使用するには、JSONログファイルに出力するようにPHPユニットを構成する必要があります。そのためには、次のように表示します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
。また、テストを実行して、通常どおりに出力を確認できます...テストが完了するまで、端末はそこに留まるだけではありません。