Implementation of an alternative PHPUnit plugin:

- Reformat the error output.
- Display collapsed trace in the Information tab widget.
- Handle incomplete tests in the results.
- Unit tests for all new classes.
- Display raw phpunit output.
This commit is contained in:
Pablo Tejada 2017-01-05 17:59:58 +07:00 committed by Dmitry Khomutov
commit c32a520b91
13 changed files with 1385 additions and 4 deletions

View file

@ -0,0 +1,98 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace Tests\PHPCI\Plugin;
use PHPCI\Plugin\Option\PhpUnitOptions;
/**
* Unit test for the PHPUnitOptions parser
*
* @author Pablo Tejada <pablo@ptejada.com>
*/
class PhpUnitOptionsTest extends \PHPUnit_Framework_TestCase
{
public function validOptionsProvider()
{
return array(
array(
array(
'config' => 'tests/phpunit.xml',
'args' => '--stop-on-error --log-junit /path/to/log/',
),
array(
'stop-on-error' => '',
'log-junit' => '/path/to/log/',
'configuration' => 'tests/phpunit.xml',
),
),
array(
array(
'coverage' => '/path/to/coverage2/',
'args' => array(
'coverage-html' => '/path/to/coverage1/',
),
),
array(
'coverage-html' => array(
'/path/to/coverage1/',
'/path/to/coverage2/',
),
),
),
array(
array(
'directory' => array(
'/path/to/test1/',
'/path/to/test2/',
),
'args' => array(
'coverage-html' => '/path/to/coverage1/',
),
),
array(
'coverage-html' => '/path/to/coverage1/',
),
),
);
}
/**
* @param $rawOptions
* @param $parsedArguments
*
* @dataProvider validOptionsProvider
*/
public function testCommandArguments($rawOptions, $parsedArguments)
{
$options = new PhpUnitOptions($rawOptions);
$this->assertSame($parsedArguments, $options->getCommandArguments());
}
public function testGetters()
{
$options = new PhpUnitOptions(
array(
'run_from' => '/path/to/run/from',
'path' => 'subTest',
)
);
$this->assertEquals('/path/to/run/from', $options->getRunFrom());
$this->assertEquals('subTest', $options->getTestsPath());
$this->assertNull($options->getOption('random'));
$this->assertEmpty($options->getDirectories());
$this->assertEmpty($options->getConfigFiles());
$files = $options->getConfigFiles(PHPCI_DIR);
$this->assertFileExists(PHPCI_DIR . $files[0]);
}
}

View file

@ -0,0 +1,127 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace Tests\PHPCI\Plugin;
/**
* Unit test for the PHPUnit V2 plugin.
*
* @author Pablo Tejada <pablo@ptejada.com>
*/
class PhpUnitV2Test extends \PHPUnit_Framework_TestCase
{
public function testSingleConfigFile()
{
$options = array(
'config' => PHPCI_DIR . 'phpunit.xml'
);
$mockPlugin = $this->getPluginBuilder($options)->setMethods(array('runConfigFile'))->getMock();
$mockPlugin->expects($this->once())->method('runConfigFile')->with(PHPCI_DIR . 'phpunit.xml');
$mockPlugin->execute();
}
public function testMultiConfigFile()
{
$options = array(
'config' => array(
PHPCI_DIR . 'phpunit1.xml',
PHPCI_DIR . 'phpunit2.xml',
)
);
$mockPlugin = $this->getPluginBuilder($options)->setMethods(array('runConfigFile'))->getMock();
$mockPlugin->expects($this->exactly(2))->method('runConfigFile')->withConsecutive(
array(PHPCI_DIR . 'phpunit1.xml'), array(PHPCI_DIR . 'phpunit2.xml')
);
$mockPlugin->execute();
}
/**
* @param array $options
*
* @return \PHPUnit_Framework_MockObject_MockBuilder
*/
protected function getPluginBuilder($options = array())
{
$loggerMock = $this->getMockBuilder('\Monolog\Logger')
->setConstructorArgs(array('Test'))
->setMethods(array('addRecord'))
->getMock();
$mockBuild = $this->getMockBuilder('\PHPCI\Model\Build')->getMock();
$mockBuilder = $this->getMockBuilder('\PHPCI\Builder')
->setConstructorArgs(array($mockBuild, $loggerMock))
->setMethods(array('executeCommand'))->getMock();
return $this->getMockBuilder('PHPCI\Plugin\PhpUnitV2')->setConstructorArgs(
array($mockBuilder, $mockBuild, $options)
);
}
public function testSingleDir()
{
$options = array(
'directory' => '/test/directory/one'
);
$mockPlugin = $this->getPluginBuilder($options)->setMethods(array('runDir'))->getMock();
$mockPlugin->expects($this->once())->method('runDir')->with('/test/directory/one');
$mockPlugin->execute();
}
public function testMultiDir()
{
$options = array(
'directory' => array(
'/test/directory/one',
'/test/directory/two',
)
);
$mockPlugin = $this->getPluginBuilder($options)->setMethods(array('runDir'))->getMock();
$mockPlugin->expects($this->exactly(2))->method('runDir')->withConsecutive(
array('/test/directory/one'), array('/test/directory/two')
);
$mockPlugin->execute();
}
public function testProcessResultsFromConfig()
{
$options = array(
'config' => PHPCI_DIR . 'phpunit.xml'
);
$mockPlugin = $this->getPluginBuilder($options)->setMethods(array('processResults'))->getMock();
$mockPlugin->expects($this->once())->method('processResults')->with($this->isType('string'));
$mockPlugin->execute();
}
public function testProcessResultsFromDir()
{
$options = array(
'directory' => PHPCI_DIR . 'Tests'
);
$mockPlugin = $this->getPluginBuilder($options)->setMethods(array('processResults'))->getMock();
$mockPlugin->expects($this->once())->method('processResults')->with($this->isType('string'));
$mockPlugin->execute();
}
}

View file

@ -0,0 +1,10 @@
{
"event": "suiteStart",
"suite": "Money Test Suite",
"tests": 61
}
{
"event": "suiteStart",
"suite": "Tests\\Money\\MoneyTest",
"tests": 15
}

View file

@ -0,0 +1,355 @@
{
"event": "suiteStart",
"suite": "Money Test Suite",
"tests": 61
}{
"event": "suiteStart",
"suite": "Tests\\Money\\MoneyTest",
"tests": 15
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFactoryMethods"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFactoryMethods",
"status": "pass",
"time": 0.051446914672852,
"trace": [],
"message": "",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testJsonEncoding"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testJsonEncoding",
"status": "pass",
"time": 0.00051498413085938,
"trace": [],
"message": "",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testMaxInit"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testMaxInit",
"status": "pass",
"time": 0.0023708343505859,
"trace": [],
"message": "",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure",
"status": "error",
"time": 0.0025370121002197,
"trace": [
{
"file": "\/path\/to\/build\/src\/Money.php",
"line": 335
},
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 43,
"function": "divide",
"class": "Money\\Money",
"type": "->"
}
],
"message": "Division by zero",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure2"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure2",
"status": "fail",
"time": 0.008944034576416,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 61,
"function": "assertEquals",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Failed asserting that two objects are equal.",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure3"
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testMaxInit"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testMaxInit",
"status": "error",
"time": 0.0074319839477539,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 36,
"function": "markTestIncomplete",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Incomplete Test: No yet finished...",
"output": ""
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure3",
"status": "fail",
"time": 0.0014960765838623,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 66,
"function": "assertEquals",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Failed asserting that two arrays are equal.",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure4"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest",
"test": "Tests\\Money\\MoneyTest::testFailure4",
"status": "fail",
"time": 0.0023319721221924,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 71,
"function": "assertTrue",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Really? It should have been true\nFailed asserting that false is true.",
"output": ""
}{
"event": "suiteStart",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"tests": 3
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"test": "Tests\\Money\\MoneyTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6)"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"test": "Tests\\Money\\MoneyTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6)",
"status": "fail",
"time": 0.0025498867034912,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 82,
"function": "assertSame",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Failed asserting that 3 is identical to 1.",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"test": "Tests\\Money\\MoneyTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"test": "Tests\\Money\\MoneyTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')",
"status": "fail",
"time": 0.00087904930114746,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 82,
"function": "assertSame",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Failed asserting that two strings are identical.",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"test": "Tests\\Money\\MoneyTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest::testFailure5",
"test": "Tests\\Money\\MoneyTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))",
"status": "fail",
"time": 0.0010340213775635,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 82,
"function": "assertSame",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Failed asserting that Array &0 (\n 0 => 3\n 1 => 'three'\n) is identical to Array &0 (\n 0 => 1\n 1 => 'one'\n).",
"output": ""
}{
"event": "suiteStart",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"tests": 3
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"test": "Tests\\Money\\MoneyTest::testSkipped with data set #0 (1, 2, 3, 4, 5, 6)"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"test": "Tests\\Money\\MoneyTest::testSkipped with data set #0 (1, 2, 3, 4, 5, 6)",
"status": "error",
"time": 0.0041179656982422,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 99,
"function": "markTestSkipped",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Skipped Test: This test is currently failing",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"test": "Tests\\Money\\MoneyTest::testSkipped with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"test": "Tests\\Money\\MoneyTest::testSkipped with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')",
"status": "error",
"time": 0.00082302093505859,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 99,
"function": "markTestSkipped",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Skipped Test: This test is currently failing",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"test": "Tests\\Money\\MoneyTest::testSkipped with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))"
}{
"event": "test",
"suite": "Tests\\Money\\MoneyTest::testSkipped",
"test": "Tests\\Money\\MoneyTest::testSkipped with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))",
"status": "error",
"time": 0.00070905685424805,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 99,
"function": "markTestSkipped",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Skipped Test: This test is currently failing",
"output": ""
}{
"event": "testStart",
"suite": "",
"test": "Tests\\Money\\MoneyTest::testDepends1"
}{
"event": "test",
"suite": "",
"test": "Tests\\Money\\MoneyTest::testDepends1",
"status": "fail",
"time": 0.00078010559082031,
"trace": [
{
"file": "\/path\/to\/build\/tests\/MoneyTest.php",
"line": 105,
"function": "assertTrue",
"class": "PHPUnit_Framework_Assert",
"type": "::"
}
],
"message": "Failed asserting that false is true.",
"output": ""
}{
"event": "test",
"suite": "",
"test": "Tests\\Money\\MoneyTest::testDepends1",
"status": "error",
"time": 0,
"trace": [],
"message": "Skipped Test: This test depends on \"Tests\\Money\\MoneyTest::testDepends1\" to pass.",
"output": ""
}{
"event": "suiteStart",
"suite": "Tests\\Money\\Parser\\IntlMoneyParserTest",
"tests": 23
}{
"event": "suiteStart",
"suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser",
"tests": 18
}{
"event": "testStart",
"suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser",
"test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #0 ('$1000.50', 100050)"
}{
"event": "test",
"suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser",
"test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #0 ('$1000.50', 100050)",
"status": "pass",
"time": 0.0069050788879395,
"trace": [],
"message": "",
"output": ""
}{
"event": "testStart",
"suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser",
"test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #1 ('$1000.00', 100000)"
}{
"event": "test",
"suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser",
"test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #1 ('$1000.00', 100000)",
"status": "pass",
"time": 0.00067996978759766,
"trace": [],
"message": "",
"output": ""
}

View file

@ -0,0 +1,55 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace Tests\PHPCI\Plugin\Util;
use PHPCI\Plugin\Util\PhpUnitResult;
/**
* Class PhpUnitResultTest parses the results for the PhpUnitV2 plugin
* @author Pablo Tejada <pablo@ptejada.com>
* @package PHPCI
* @subpackage Plugin
*/
class PhpUnitResultTest extends \PHPUnit_Framework_TestCase
{
public function testInitParse()
{
$buildPath = '/path/to/build';
$parser = new PhpUnitResult(PHPCI_DIR . 'Tests/PHPCI/Plugin/SampleFiles/phpunit_money.txt', $buildPath);
$output = $parser->parse()->getResults();
$errors = $parser->getErrors();
$this->assertEquals(8, $parser->getFailures());
$this->assertInternalType('array', $output);
$this->assertInternalType('array', $errors);
$this->assertNotEmpty($output);
$this->assertNotEmpty($errors);
// The trace elements should not include the build path
$this->assertStringStartsNotWith($buildPath, $output[3]['trace'][0]);
$this->assertStringStartsNotWith($buildPath, $output[3]['trace'][1]);
$this->assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[5]['severity']);
$this->assertContains('Incomplete Test:', $output[5]['message']);
$this->assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[11]['severity']);
$this->assertContains('Skipped Test:', $output[11]['message']);
}
public function testParseFailure()
{
$this->setExpectedException('\Exception', 'Failed to parse the JSON output');
$buildPath = '/path/to/build';
$parser = new PhpUnitResult(PHPCI_DIR . 'Tests/PHPCI/Plugin/SampleFiles/invalid_format.txt', $buildPath);
$parser->parse();
}
}