Skip to content

Commit 554ec2d

Browse files
authored
feat: add configurable support of outputing a reportfile per suite (#7)
contributors: @grEvenX
1 parent c892d4a commit 554ec2d

File tree

10 files changed

+230
-49
lines changed

10 files changed

+230
-49
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ php:
55
- 7.0
66
- 7.1
77

8-
before_script: composer install --prefer-source --no-interaction
8+
before_script: COMPOSER_MEMORY_LIMIT=-1 composer install --prefer-source --no-interaction
99

10-
script: composer run-script test
10+
script: composer run-script test

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Behat Cucumber Json Formatter
1+
# Behat Cucumber Json Formatter
22

33
*Note*: this is a fork of [Vanare/behat-cucumber-formatter](https://github.com/Vanare/behat-cucumber-formatter). As the original project seems unmaintained and there is no possibility to contact the owner, I publish the library under my handle. Many thanks to the original team of Vanare for starting this great library!
44

@@ -27,6 +27,7 @@ default:
2727
extensions:
2828
Vanare\BehatCucumberJsonFormatter\Extension:
2929
fileNamePrefix: report
30+
resultFilePerSuite: true
3031
outputDir: %paths.base%/build/tests
3132
```
3233

@@ -41,7 +42,10 @@ bin/behat -f cucumber_json
4142
- `fileNamePrefix`: Filename prefix of generated report
4243
- `outputDir`: Generated report will be placed in this directory
4344
- `fileName` _(optional)_: Filename of generated report - current feature name will be used by default.
45+
Only applicable when `resultFilePerSuite` is not enabled.
46+
- `resultFilePerSuite` _(optional)_: The default behaviour is to generate a single report named `all.json`.
47+
If this option is set to `true`, a report will be created per behat suite.
4448

4549
## Licence
4650

47-
MIT Licence
51+
MIT Licence

features/bootstrap/FeatureContext.php

Lines changed: 115 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ class FeatureContext implements Context
1717
/** @var string */
1818
private $workingDir;
1919

20+
/** @var string */
21+
private $reportsDir;
22+
23+
/** @var bool */
24+
protected $resultFilePerSuiteEnabled;
25+
2026
/**
2127
* Cleans test folders in the temporary directory.
2228
*
@@ -60,7 +66,8 @@ public function prepareTestFolders()
6066
{
6167
$dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR .
6268
md5(microtime() . rand(0, 10000));
63-
$reportsDir = $dir . DIRECTORY_SEPARATOR . 'reports';
69+
$this->reportsDir = $dir . DIRECTORY_SEPARATOR . 'reports';
70+
6471
// create directories
6572
mkdir(
6673
sprintf(
@@ -72,23 +79,9 @@ public function prepareTestFolders()
7279
true
7380
);
7481
mkdir($dir . DIRECTORY_SEPARATOR . 'junit');
75-
mkdir($reportsDir);
82+
mkdir($this->reportsDir);
7683

77-
// create configuration
78-
file_put_contents($dir . DIRECTORY_SEPARATOR . 'behat.yml', <<<EOF
79-
default:
80-
suites:
81-
default:
82-
paths:
83-
- "$dir"
84-
contexts:
85-
- ExampleFeatureContext
86-
extensions:
87-
Vanare\BehatCucumberJsonFormatter\Extension:
88-
fileNamePrefix: report
89-
outputDir: "$reportsDir"
90-
EOF
91-
);
84+
$this->writeBehatConfigForTests($dir);
9285

9386
// copy context
9487
copy(
@@ -120,21 +113,59 @@ public function prepareTestFolders()
120113
*/
121114
public function iHaveTheFollowingFeature(PyStringNode $string)
122115
{
123-
file_put_contents($this->workingDir . '/features/feature.feature', $string->getRaw());
116+
$this->iHaveTheFollowingFeatureFileStoredIn('feature.feature', 'default', $string);
117+
}
118+
119+
/**
120+
* @Given I have the following feature file :fileName stored in :subDirectory:
121+
*/
122+
public function iHaveTheFollowingFeatureFileStoredIn($fileName, $subDirectory = '', PyStringNode $string)
123+
{
124+
$filePath = $this->workingDir . '/features' . (!empty($subDirectory) ? '/' . $subDirectory : '') . '/' . $fileName;
125+
if (!empty($subDirectory) && !file_exists($subDirectory)) {
126+
mkdir(dirname($filePath), 0777, true);
127+
}
128+
file_put_contents($filePath, $string->getRaw());
129+
}
130+
131+
/**
132+
* @Given I have the enabled the "resultFilePerSuite" option
133+
*/
134+
public function iHaveTheEnabledTheResultFilePerSuiteOption()
135+
{
136+
// manipulate the behat config
137+
$this->resultFilePerSuiteEnabled = true;
138+
$this->writeBehatConfigForTests($this->workingDir, [
139+
'resultFilePerSuite' => 'true'
140+
]);
141+
}
142+
143+
/**
144+
* @When I run behat with the converter and no specific suite is specified
145+
*/
146+
public function iRunBehatWithTheConverterAndNoSpecificSuiteIsSpecified()
147+
{
148+
$this->runBehatWithConverter();
124149
}
125150

126151
/**
127152
* @When I run behat with the converter
128153
*/
129154
public function iRunBehatWithTheConverter()
155+
{
156+
$this->runBehatWithConverter('-s default');
157+
}
158+
159+
protected function runBehatWithConverter($extraParameters = '')
130160
{
131161
$this->process->setWorkingDirectory($this->workingDir);
132162
$this->process->setCommandLine(
133163
sprintf(
134-
'%s %s -c %s -s default --no-interaction -f cucumber_json',
164+
'%s %s -c %s %s --no-interaction -f cucumber_json',
135165
$this->phpBin,
136166
escapeshellarg(BEHAT_BIN_PATH),
137-
$this->workingDir . DIRECTORY_SEPARATOR . 'behat.yml'
167+
$this->workingDir . DIRECTORY_SEPARATOR . 'behat.yml',
168+
!empty($extraParameters) ? $extraParameters : ''
138169
)
139170
);
140171
// Don't reset the LANG variable on HHVM, because it breaks HHVM itself
@@ -152,13 +183,7 @@ public function iRunBehatWithTheConverter()
152183
*/
153184
public function theResultFileWillBe(PyStringNode $string)
154185
{
155-
$reportFiles = glob(
156-
sprintf(
157-
'%1$s%2$sreports%2$sreport*.json',
158-
$this->workingDir,
159-
DIRECTORY_SEPARATOR
160-
)
161-
);
186+
$reportFiles = $this->generatedReportFiles();
162187

163188
$expected = json_decode($string->getRaw(), true);
164189
$actual = json_decode(file_get_contents(sprintf($reportFiles[0])), true);
@@ -169,6 +194,28 @@ public function theResultFileWillBe(PyStringNode $string)
169194
);
170195
}
171196

197+
/**
198+
* @Then there should be :featureCount features in the report :reportName
199+
* @Then there should be :featureCount feature in the report :reportName
200+
*/
201+
public function thereShouldBeFeaturesInTheReport(int $featureCount, string $reportName)
202+
{
203+
$reportFiles = $this->generatedReportFiles($reportName);
204+
205+
$reportData = json_decode(file_get_contents(sprintf($reportFiles[0])), true);
206+
PHPUnit_Framework_Assert::assertCount($featureCount, $reportData);
207+
}
208+
209+
/**
210+
* @Then :count result file should be generated
211+
* @Then :count result files should be generated
212+
*/
213+
public function resultFileShouldBeGenerated(int $count)
214+
{
215+
$reportFiles = $this->generatedReportFiles();
216+
PHPUnit_Framework_Assert::assertCount($count, $reportFiles);
217+
}
218+
172219
/**
173220
* Removes the dynamic parts of a result, like the feature path and durations.
174221
*
@@ -187,4 +234,45 @@ private static function removeDynamics(array $array)
187234
}
188235
return $array;
189236
}
237+
238+
private function generatedReportFiles($reportName = 'report*.json'): array
239+
{
240+
return glob(
241+
sprintf(
242+
'%1$s%2$sreports%2$s%3$s',
243+
$this->workingDir,
244+
DIRECTORY_SEPARATOR,
245+
$reportName
246+
)
247+
);
248+
}
249+
250+
private function writeBehatConfigForTests(string $dir, array $extraOptions = [])
251+
{
252+
// create configuration
253+
$reportsDir = $this->reportsDir;
254+
$content = <<<EOF
255+
default:
256+
suites:
257+
default:
258+
paths:
259+
- "$dir/features/default"
260+
contexts:
261+
- ExampleFeatureContext
262+
othersuite:
263+
paths:
264+
- "$dir/features/othersuite"
265+
contexts:
266+
- ExampleFeatureContext
267+
extensions:
268+
Vanare\BehatCucumberJsonFormatter\Extension:
269+
fileNamePrefix: report-
270+
outputDir: "$reportsDir"
271+
EOF;
272+
$content .= implode("", array_map(function ($key, $value) {
273+
return "\n $key: $value";
274+
}, array_keys($extraOptions), $extraOptions));
275+
276+
file_put_contents($dir . DIRECTORY_SEPARATOR . 'behat.yml', $content);
277+
}
190278
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
Feature: Calculator example
2+
3+
Scenario: Default to only output a single result file
4+
Given I have the following feature:
5+
"""
6+
Feature: Calculator
7+
8+
Scenario: Adding numbers
9+
Given I have numbers 1 and 2
10+
When I sum the numbers
11+
Then I should have 3 as result
12+
"""
13+
And I have the following feature file "eat-cukes.feature" stored in "othersuite":
14+
"""
15+
Feature: Eat cukes in lot
16+
17+
Scenario: Eating many cukes
18+
Given I have 10 cukes
19+
When I eat 5 cukes
20+
Then Am I hungry? false
21+
"""
22+
When I run behat with the converter and no specific suite is specified
23+
Then 1 result file should be generated
24+
And there should be 2 features in the report "report-all.json"
25+
26+
Scenario: Output to a result file per suite
27+
Given I have the enabled the "resultFilePerSuite" option
28+
And I have the following feature:
29+
"""
30+
Feature: Calculator
31+
32+
Scenario: Adding numbers
33+
Given I have numbers 1 and 2
34+
When I sum the numbers
35+
Then I should have 3 as result
36+
"""
37+
And I have the following feature file "eat-cukes.feature" stored in "othersuite":
38+
"""
39+
Feature: Eat cukes in lot
40+
41+
Scenario: Eating many cukes
42+
Given I have 10 cukes
43+
When I eat 5 cukes
44+
Then Am I hungry? false
45+
"""
46+
When I run behat with the converter and no specific suite is specified
47+
Then 2 result files should be generated
48+
And there should be 1 feature in the report "report-default.json"
49+
And there should be 1 feature in the report "report-othersuite.json"

src/Extension.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ public function initialize(ExtensionManager $extensionManager)
3737
*/
3838
public function configure(ArrayNodeDefinition $builder)
3939
{
40-
$builder->children()->scalarNode('fileNamePrefix')->defaultValue('report');
40+
$builder->children()->scalarNode('fileNamePrefix')->defaultValue('');
4141
$builder->children()->scalarNode('outputDir')->defaultValue('build/tests');
4242
$builder->children()->scalarNode('fileName');
43+
$builder->children()->booleanNode('resultFilePerSuite')->defaultFalse();
4344
}
4445

4546
/**
@@ -56,6 +57,7 @@ public function load(ContainerBuilder $container, array $config)
5657
if (!empty($config['fileName'])) {
5758
$definition->addMethodCall('setFileName', [$config['fileName']]);
5859
}
60+
$definition->addMethodCall('setResultFilePerSuite', [$config['resultFilePerSuite']]);
5961

6062
$container
6163
->setDefinition('json.formatter', $definition)

src/Formatter/Formatter.php

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class Formatter implements FormatterInterface
4343
/** @var Node\Scenario */
4444
private $currentScenario;
4545

46+
/** @var bool */
47+
private $resultFilePerSuite = false;
48+
4649
/**
4750
* @param string $fileNamePrefix
4851
* @param string $outputDir
@@ -78,6 +81,11 @@ public function setFileName($fileName) {
7881
$this->printer->setResultFileName($fileName);
7982
}
8083

84+
/** @inheritdoc */
85+
public function setResultFilePerSuite(bool $enabled) {
86+
$this->resultFilePerSuite = $enabled;
87+
}
88+
8189
/** @inheritdoc */
8290
public function getDescription()
8391
{
@@ -128,14 +136,18 @@ public function onAfterExercise(TestworkEvent\ExerciseCompleted $event)
128136
$this->timer->stop();
129137

130138
$this->renderer->render();
139+
140+
if ($this->resultFilePerSuite) {
141+
foreach ($this->suites as $suite) {
142+
$this->printer->setResultFileName($suite->getFilenameForReport());
143+
$suiteResult = $this->renderer->getResultForSuite($suite->getName());
144+
$this->printer->write($suiteResult);
145+
}
146+
return;
147+
}
148+
131149
if (!$this->printer->getResultFileName()) {
132-
$this->printer->setResultFileName(
133-
str_replace(
134-
DIRECTORY_SEPARATOR,
135-
FileOutputPrinter::FILE_SEPARATOR,
136-
$this->currentFeature->getFilenameForReport()
137-
)
138-
);
150+
$this->printer->setResultFileName('all');
139151
}
140152

141153
$this->printer->write($this->renderer->getResult());

src/Node/Feature.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,6 @@ public function setFile($file)
194194
$this->file = $file;
195195
}
196196

197-
/**
198-
* @return string
199-
*/
200-
public function getFilenameForReport()
201-
{
202-
return dirname($this->file) . FileOutputPrinter::FILE_SEPARATOR . basename($this->file, '.feature');
203-
}
204-
205197
/**
206198
* @return Scenario[]
207199
*/

src/Node/Suite.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,12 @@ public function addFeature($feature)
5353
{
5454
$this->features[] = $feature;
5555
}
56+
57+
/**
58+
* @return string
59+
*/
60+
public function getFilenameForReport()
61+
{
62+
return $this->getName();
63+
}
5664
}

0 commit comments

Comments
 (0)