我有测试套件,里面有很多测试.这是一个中等大小的:
ok 4 - CommodityBasketTest::testStartsOutEmpty ok 5 - CommodityBasketTest::testCanAddACommodity ok 6 - CommodityBasketTest::testWillAddOneCommodityByDefault ok 7 - CommodityBasketTest::testCannotAddACommodityWithAnNonNumericQuantity ok 8 - CommodityBasketTest::testAddingTheSameCommodityWillIncreaseItsQuantity ok 9 - CommodityBasketTest::testMultipleCommodityCanBeAdded ok 10 - CommodityBasketTest::testTakingFromAnEmptyBasketWontWork ok 11 - CommodityBasketTest::testTakesFirstCommodityFromTheBasket ok 12 - CommodityBasketTest::testCanRetrieveASpecificCommodity ok 13 - CommodityBasketTest::testWillThrowExceptionOnMissingCommodity ok 14 - CommodityBasketTest::testReturnsZeroWorthForEmptyBaskets ok 15 - CommodityBasketTest::testReturnsProperWorthOfACommodity ok 16 - CommodityBasketTest::testWillAccuratelyReturnStatistics
我如何装备PHPUnit以便我可以以某种方式显示正在测试的基础方法,就像我在粘贴中一样?我对输出很灵活;我只想知道CommodityBasketTest :: testReturnsZeroWorthForEmptyBaskets测试CommodityBasket :: getValuation(),例如.
这就是我想要的:
-- CommodityBasket::__construct() -- ok 4 - CommodityBasketTest::testStartsOutEmpty -- CommodityBasket::add() -- ok 5 - CommodityBasketTest::testCanAddACommodity ok 6 - CommodityBasketTest::testWillAddOneCommodityByDefault ok 7 - CommodityBasketTest::testCannotAddACommodityWithAnNonNumericQuantity ok 8 - CommodityBasketTest::testAddingTheSameCommodityWillIncreaseItsQuantity ok 9 - CommodityBasketTest::testMultipleCommodityCanBeAdded -- CommodityBasket::take() -- ok 10 - CommodityBasketTest::testTakingFromAnEmptyBasketWontWork ok 11 - CommodityBasketTest::testTakesFirstCommodityFromTheBasket ok 12 - CommodityBasketTest::testCanRetrieveASpecificCommodity ok 13 - CommodityBasketTest::testWillThrowExceptionOnMissingCommodity -- CommodityBasket::getValuation() -- ok 14 - CommodityBasketTest::testReturnsZeroWorthForEmptyBaskets ok 15 - CommodityBasketTest::testReturnsProperWorthOfACommodity -- CommodityBasket::dumpStats() -- ok 16 - CommodityBasketTest::testWillAccuratelyReturnStatistics
谢谢你的建议.
我的方法是
@covers
标签和自定义结果打印机的组合.
你应该使用@covers标签来生成更有意义的代码覆盖,特别是在更大的测试套件中,确保只测试方法的测试确实为它生成覆盖是很重要的.
我知道你的问题与报道无关,但我们会在一分钟内完成.并且可能只是使用该注释就足够了,因为无论您运行所有集成测试等等,每个没有专用测试的方法都会显示0%的覆盖率.
自定义结果侦听器,用于收集所需的信息
实施可以调整,我只想生产一些能够很好地展示概念的东西,并希望能给你一些你可以适应的东西.
代码是alpha,因为我只为这个问题编写它,但它适用于当前的PHPunit,我想我粘贴了你需要的一切.
结果:
--- myClass --- -- myClass::a -- ok - myClassTest::testAone fail - myClassTest::testAtwoFails -- myClass::b -- ok - myClassTest::testB -- myClass::untested -- !! Method untested !!
我希望这符合你想要的输出.在下面的代码中可以很容易地更改格式.
它为您测试的每个班级打印这条信息(空的就足够了!)
如果一个人测试@covers多个方法,它将显示这些方法中的每一个
正在测试的课程
<?PHP class myClass { public function a() { return 1; } public function b() { return 2; } public function untested() { return 3; } }
测试用例
<?PHP require_once("myClass.PHP"); class myClassTest extends PHPUnit_Framework_TestCase { /** * @covers a */ public function testAone() { $sut = new myClass(); $this->assertSame(1,$sut->a()); } /** * @covers a */ public function testAtwoFails() { $sut = new myClass(); $this->assertSame("error",$sut->a()); } /** * @covers b */ public function testB() { $sut = new myClass(); $this->assertSame(2,$sut->b()); } }
<PHPunit> <listeners> <listener class="ResultPrinterListener" file="./ResultPrinterListener.PHP"></listener> </listeners> </PHPunit>
结果打印机
<?PHP class ResultPrinterListener implements PHPUnit_Framework_TestListener { protected $suites = array(); 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,$time) {} public function addSkippedTest(PHPUnit_Framework_Test $test,$time) {} public function startTest(PHPUnit_Framework_Test $test) {} public function endTest(PHPUnit_Framework_Test $test,$time) {} public function startTestSuite(PHPUnit_Framework_TestSuite $suite) {} public function endTestSuite(PHPUnit_Framework_TestSuite $suite) { $this->suites[] = $suite; } public function __destruct() { $tests = array(); foreach($this->suites as $suite) { foreach($suite->tests() as $test) { if(!$test instanceOf PHPUnit_Framework_TestCase) { continue; } $testClass = get_class($test); $classUnderTest = substr($testClass,-4); // just cutting the "Test" for now /** * Create an array structue * array[ClassUnderTests][methodUnderTest][arrayOfTestMethodsThatTestThatMethod] * Every method for a class you have at least one test for will show up here for now */ if(!isset($tests[$classUnderTest])) { if(!class_exists($classUnderTest)) { echo "\nCan't find matching class '$classUnderTest' for test class $testClass!\n"; } $class = new ReflectionClass($classUnderTest); foreach($class->getMethods() as $method) { $tests[$classUnderTest][$method->getName()] = array(); } } $annotations = $test->getAnnotations(); if(!isset($annotations["method"]["covers"])) { continue; } foreach($annotations["method"]["covers"] as $functionUnderTest) { $statusLine = ""; $status = $test->getStatus(); if($status == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) { $statusLine .= "fail - "; } else if($status == PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED) { $statusLine .= "skip - "; } else if($status == PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE) { $statusLine .= "inc - "; } else { $statusLine .= "ok - "; } $statusLine .= $testClass."::".$test->getName(); $tests[$classUnderTest][$functionUnderTest][] = $statusLine; } } } foreach($tests as $classUnderTest => $methods) { echo "\n\n --- $classUnderTest --- \n\n"; foreach($methods as $method => $testCaseStrings) { echo "-- $classUnderTest::$method -- \n"; if($testCaseStrings == array()) { echo " !! Method untested !!\n"; continue; } foreach($testCaseStrings as $testCaseString) { echo " $testCaseString\n"; } echo "\n"; } } } }