Skip to content

Commit 632a21f

Browse files
committed
Add support for phpunit configure, testsuite and filter options
Covered by tests that use intensively the new ->lastCmd introduced a couple of commits ago. Also, added a TODO about something, pre-existing, that is an incorrect unit tests, some day will be investigated. Not today. Fixes #100
1 parent d230053 commit 632a21f

File tree

4 files changed

+154
-29
lines changed

4 files changed

+154
-29
lines changed

docs/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ The format of this change log follows the advice given at [Keep a CHANGELOG](htt
1010

1111
## [Unreleased]
1212
### Added
13-
- Added support for the `--tags` and `--name` options into the `behat` command.
13+
- Added support for the `--tags` and `--name` options to the `behat` command.
14+
- Added support for the `--configure`, `--testsuite` and `--filter` options to the `phpunit` command.
1415

1516
### Changed
1617
- ACTION SUGGESTED: If you are using GitHub Actions, it's recomended to use `!cancelled()` instead of `always()` for moodle-plugin-ci tests. Adding a final step that always returns failure when the workflow is cancelled will ensure that cancelled workflows are not marked as successful. For a working example, please reference the updated `gha.dist.yml` file.

docs/CLI.md

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,7 @@ Run PHPUnit on a plugin
19751975

19761976
### Usage
19771977

1978-
* `phpunit [-m|--moodle MOODLE] [--coverage-text] [--coverage-clover] [--coverage-pcov] [--coverage-xdebug] [--coverage-phpdbg] [--fail-on-incomplete] [--fail-on-risky] [--fail-on-skipped] [--fail-on-warning] [--testdox] [--] <plugin>`
1978+
* `phpunit [-m|--moodle MOODLE] [-c|--configuration CONFIGURATION] [--testsuite TESTSUITE] [--filter FILTER] [--testdox] [--coverage-text] [--coverage-clover] [--coverage-pcov] [--coverage-xdebug] [--coverage-phpdbg] [--fail-on-incomplete] [--fail-on-risky] [--fail-on-skipped] [--fail-on-warning] [--] <plugin>`
19791979

19801980
Run PHPUnit on a plugin
19811981

@@ -2001,6 +2001,46 @@ Path to Moodle
20012001
* Is negatable: no
20022002
* Default: `'.'`
20032003

2004+
#### `--configuration|-c`
2005+
2006+
PHPUnit configuration XML file (relative to plugin directory)
2007+
2008+
* Accept value: yes
2009+
* Is value required: yes
2010+
* Is multiple: no
2011+
* Is negatable: no
2012+
* Default: `NULL`
2013+
2014+
#### `--testsuite`
2015+
2016+
PHPUnit testsuite option to use (must exist in the configuration file being used)
2017+
2018+
* Accept value: yes
2019+
* Is value required: yes
2020+
* Is multiple: no
2021+
* Is negatable: no
2022+
* Default: `NULL`
2023+
2024+
#### `--filter`
2025+
2026+
PHPUnit filter option to use
2027+
2028+
* Accept value: yes
2029+
* Is value required: yes
2030+
* Is multiple: no
2031+
* Is negatable: no
2032+
* Default: `NULL`
2033+
2034+
#### `--testdox`
2035+
2036+
Enable testdox formatter
2037+
2038+
* Accept value: no
2039+
* Is value required: no
2040+
* Is multiple: no
2041+
* Is negatable: no
2042+
* Default: `false`
2043+
20042044
#### `--coverage-text`
20052045

20062046
Generate and print code coverage report in text format
@@ -2091,16 +2131,6 @@ Treat tests with warnings as failures
20912131
* Is negatable: no
20922132
* Default: `false`
20932133

2094-
#### `--testdox`
2095-
2096-
Enable testdox formatter
2097-
2098-
* Accept value: no
2099-
* Is value required: no
2100-
* Is multiple: no
2101-
* Is negatable: no
2102-
* Default: `false`
2103-
21042134
#### `--help|-h`
21052135

21062136
Display help for the given command. When no command is given display help for the list command

src/Command/PHPUnitCommand.php

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ protected function configure(): void
2929

3030
$this->setName('phpunit')
3131
->setDescription('Run PHPUnit on a plugin')
32+
->addOption(
33+
'configuration',
34+
'c',
35+
InputOption::VALUE_REQUIRED,
36+
'PHPUnit configuration XML file (relative to plugin directory)'
37+
)
38+
->addOption(
39+
'testsuite',
40+
null,
41+
InputOption::VALUE_REQUIRED,
42+
'PHPUnit testsuite option to use (must exist in the configuration file being used)'
43+
)
44+
->addOption('filter', null, InputOption::VALUE_REQUIRED, 'PHPUnit filter option to use')
45+
->addOption('testdox', null, InputOption::VALUE_NONE, 'Enable testdox formatter')
3246
->addOption('coverage-text', null, InputOption::VALUE_NONE, 'Generate and print code coverage report in text format')
3347
->addOption('coverage-clover', null, InputOption::VALUE_NONE, 'Generate code coverage report in Clover XML format')
3448
->addOption('coverage-pcov', null, InputOption::VALUE_NONE, 'Use the pcov extension to calculate code coverage')
@@ -37,8 +51,7 @@ protected function configure(): void
3751
->addOption('fail-on-incomplete', null, InputOption::VALUE_NONE, 'Treat incomplete tests as failures')
3852
->addOption('fail-on-risky', null, InputOption::VALUE_NONE, 'Treat risky tests as failures')
3953
->addOption('fail-on-skipped', null, InputOption::VALUE_NONE, 'Treat skipped tests as failures')
40-
->addOption('fail-on-warning', null, InputOption::VALUE_NONE, 'Treat tests with warnings as failures')
41-
->addOption('testdox', null, InputOption::VALUE_NONE, 'Enable testdox formatter');
54+
->addOption('fail-on-warning', null, InputOption::VALUE_NONE, 'Treat tests with warnings as failures');
4255
}
4356

4457
protected function initialize(InputInterface $input, OutputInterface $output): void
@@ -80,6 +93,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8093
private function resolveOptions(InputInterface $input): array
8194
{
8295
$options = [];
96+
97+
if ($input->getOption('configuration')) {
98+
$options[] = [
99+
'--configuration',
100+
$this->plugin->directory . '/' . $input->getOption('configuration'),
101+
];
102+
}
103+
104+
if ($input->getOption('testsuite')) {
105+
$options[] = [
106+
'--testsuite',
107+
$input->getOption('testsuite'),
108+
];
109+
}
110+
111+
if ($input->getOption('filter')) {
112+
$options[] = [
113+
'--filter',
114+
$input->getOption('filter'),
115+
];
116+
}
117+
83118
if ($this->supportsCoverage() && $input->getOption('coverage-text')) {
84119
$options[] = [
85120
'--coverage-text',
@@ -103,16 +138,25 @@ private function resolveOptions(InputInterface $input): array
103138
];
104139
}
105140
}
106-
if (is_file($this->plugin->directory . '/phpunit.xml')) {
107-
$options[] = [
108-
'--configuration',
109-
$this->plugin->directory,
110-
];
111-
} else {
112-
$options[] = [
113-
'--testsuite',
114-
$this->plugin->getComponent(),
115-
];
141+
142+
// Only can set configuration or testsuite here (auto) if the former has not been set via command line option.
143+
if (!$input->getOption('configuration')) {
144+
// Use default configuration (phpunit.xml) only if it exists.
145+
if (is_file($this->plugin->directory . '/phpunit.xml')) {
146+
$options[] = [
147+
'--configuration',
148+
$this->plugin->directory . '/phpunit.xml',
149+
];
150+
} else {
151+
// Fallback to try to use the best testsuite potentially available.
152+
// Only can set automatic testsuite if it has not been passed via command line option.
153+
if (!$input->getOption('testsuite')) {
154+
$options[] = [
155+
'--testsuite',
156+
$this->plugin->getComponent() . '_testsuite', // This is our best guess.
157+
];
158+
}
159+
}
116160
}
117161

118162
return array_merge(...$options); // Merge all options into a single array.

tests/Command/PHPUnitCommandTest.php

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
class PHPUnitCommandTest extends MoodleTestCase
2323
{
24-
protected function executeCommand($pluginDir = null, $moodleDir = null): CommandTester
24+
protected function executeCommand($pluginDir = null, $moodleDir = null, array $cmdOptions = []): CommandTester
2525
{
2626
if ($pluginDir === null) {
2727
$pluginDir = $this->pluginDir;
@@ -37,10 +37,15 @@ protected function executeCommand($pluginDir = null, $moodleDir = null): Command
3737
$application->add($command);
3838

3939
$commandTester = new CommandTester($application->find('phpunit'));
40-
$commandTester->execute([
41-
'plugin' => $pluginDir,
42-
'--moodle' => $moodleDir,
43-
]);
40+
$cmdOptions = array_merge(
41+
[
42+
'plugin' => $pluginDir,
43+
'--moodle' => $moodleDir,
44+
],
45+
$cmdOptions
46+
);
47+
$commandTester->execute($cmdOptions);
48+
$this->lastCmd = $command->execute->lastCmd; // We need this for assertions against the command run.
4449

4550
return $commandTester;
4651
}
@@ -49,6 +54,50 @@ public function testExecute()
4954
{
5055
$commandTester = $this->executeCommand();
5156
$this->assertSame(0, $commandTester->getStatusCode());
57+
$this->assertMatchesRegularExpression('/vendor.bin.phpunit/', $this->lastCmd);
58+
$this->assertMatchesRegularExpression('/--testsuite.*local_ci_testsuite/', $this->lastCmd);
59+
$this->assertDoesNotMatchRegularExpression('/--configuration.*local\/ci/', $this->lastCmd);
60+
}
61+
62+
public function testExecuteWithCustomPHPUnitXMLFile()
63+
{
64+
$commandTester = $this->executeCommand(null, null, ['--configuration' => 'some_config.xml']);
65+
$this->assertSame(0, $commandTester->getStatusCode());
66+
$this->assertMatchesRegularExpression('/vendor.bin.phpunit/', $this->lastCmd);
67+
$this->assertMatchesRegularExpression('/--configuration.*.*local\/ci\/some_config.xml/', $this->lastCmd);
68+
$this->assertDoesNotMatchRegularExpression('/--configuration.*local\/ci\/phpunit.xml/', $this->lastCmd);
69+
$this->assertDoesNotMatchRegularExpression('/--testsuite.*local_ci_testsuite/', $this->lastCmd);
70+
}
71+
72+
public function testExecuteWithGeneratedPHPUnitXMLFile()
73+
{
74+
$fs = new Filesystem();
75+
$fs->touch($this->pluginDir . '/phpunit.xml');
76+
$commandTester = $this->executeCommand();
77+
$this->assertSame(0, $commandTester->getStatusCode());
78+
$this->assertMatchesRegularExpression('/vendor.bin.phpunit/', $this->lastCmd);
79+
$this->assertMatchesRegularExpression('/--configuration.*local\/ci\/phpunit.xml/', $this->lastCmd);
80+
$this->assertDoesNotMatchRegularExpression('/--testsuite.*local_ci_testsuite/', $this->lastCmd);
81+
}
82+
83+
public function testExecuteWithTestSuite()
84+
{
85+
$commandTester = $this->executeCommand(null, null, ['--testsuite' => 'some_testsuite']);
86+
$this->assertSame(0, $commandTester->getStatusCode());
87+
$this->assertMatchesRegularExpression('/vendor.bin.phpunit/', $this->lastCmd);
88+
$this->assertMatchesRegularExpression('/--testsuite.*some_testsuite/', $this->lastCmd);
89+
$this->assertDoesNotMatchRegularExpression('/--configuration.*local\/ci/', $this->lastCmd);
90+
$this->assertDoesNotMatchRegularExpression('/--testsuite.*local_ci_testsuite/', $this->lastCmd);
91+
}
92+
93+
public function testExecuteWithFilter()
94+
{
95+
$commandTester = $this->executeCommand(null, null, ['--filter' => 'some_filter']);
96+
$this->assertSame(0, $commandTester->getStatusCode());
97+
$this->assertMatchesRegularExpression('/vendor.bin.phpunit/', $this->lastCmd);
98+
$this->assertMatchesRegularExpression('/--filter.*some_filter/', $this->lastCmd);
99+
$this->assertMatchesRegularExpression('/--testsuite.*local_ci_testsuite/', $this->lastCmd);
100+
$this->assertDoesNotMatchRegularExpression('/--configuration.*local\/ci/', $this->lastCmd);
52101
}
53102

54103
public function testExecuteNoTests()
@@ -70,6 +119,7 @@ public function testExecuteNoPlugin()
70119
public function testExecuteNoMoodle()
71120
{
72121
$this->expectException(\InvalidArgumentException::class);
122+
// TODO: Check what's happening here. moodleDir should be the 2nd parameter, but then the test fails.
73123
$this->executeCommand($this->moodleDir . '/no/moodle');
74124
}
75125
}

0 commit comments

Comments
 (0)