Skip to content

Commit 1331877

Browse files
authored
feat: replace custom CucumberAssertHelper with custom EmptyTestEventListener implementation (#220)
1 parent d8b8c03 commit 1331877

26 files changed

+482
-187
lines changed

.github/workflows/static-analysis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ jobs:
4242
env:
4343
GTEST_OUTPUT: "xml:${{ github.workspace }}/testresults/"
4444

45+
- name: Run acceptance tests
46+
run: |
47+
bats --formatter junit cucumber_cpp/acceptance_test/coverage.bats | tee test-report.xml
48+
4549
- name: Collect coverage
4650
run: |
4751
gcovr --sonarqube=coverage.xml --exclude-lines-by-pattern '.*assert\(.*\);|.*really_assert\(.*\);|.*std::abort();' --exclude-unreachable-branches --exclude-throw-branches -j "$(nproc)" --exclude=.*/example/.* --exclude=.*/external/.* --exclude=.*/test/.*

.vscode/launch.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@keyword-asterisk",
1515
"@result:UNDEFINED",
1616
"@result:FAILED",
17+
"@result:OK",
1718
"@fail_feature"
1819
]
1920
},
@@ -58,6 +59,24 @@
5859
"ignoreFailures": true
5960
}
6061
]
62+
},
63+
{
64+
"name": "(gdb) Debug Test",
65+
"type": "cppdbg",
66+
"request": "launch",
67+
"program": "${command:cmake.launchTargetPath}",
68+
"stopAtEntry": false,
69+
"cwd": "${workspaceFolder}",
70+
"environment": [],
71+
"externalConsole": false,
72+
"MIMode": "gdb",
73+
"setupCommands": [
74+
{
75+
"description": "Enable pretty-printing for gdb",
76+
"text": "-enable-pretty-printing",
77+
"ignoreFailures": true
78+
}
79+
]
6180
}
6281
]
6382
}

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@
2424
"sonarlint.connectedMode.project": {
2525
"connectionId": "philips-software",
2626
"projectKey": "philips-software_amp-cucumber-cpp-runner"
27-
}
27+
},
28+
"cmake.postRunCoverageTarget": "generate-coverage-report"
2829
}
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#!/usr/bin/env bats
2+
3+
setup() {
4+
load '/usr/local/bats-support/load'
5+
load '/usr/local/bats-assert/load'
6+
}
7+
8+
teardown() {
9+
rm -rf ./out/
10+
}
11+
12+
@test "Successful test" {
13+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --tag "@result:OK" --feature cucumber_cpp/acceptance_test/features --report console
14+
assert_success
15+
}
16+
17+
@test "Parse tag expression" {
18+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --tag @smoke @result:OK --feature cucumber_cpp/acceptance_test/features --report console
19+
assert_success
20+
}
21+
22+
@test "Failed tests" {
23+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --tag "@result:FAILED" --feature cucumber_cpp/acceptance_test/features --report console
24+
assert_failure
25+
assert_output --partial "failed \"cucumber_cpp/acceptance_test/features/test_scenarios.feature\""
26+
assert_output --partial "skipped Then a then step"
27+
}
28+
29+
@test "Undefined tests" {
30+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --tag "@result:UNDEFINED" --feature cucumber_cpp/acceptance_test/features --report console
31+
assert_failure
32+
assert_output --partial "undefined \"cucumber_cpp/acceptance_test/features/test_scenarios.feature\""
33+
assert_output --partial "skipped Then this should be skipped"
34+
}
35+
36+
@test "No tests" {
37+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --tag "@invalidtag" --feature cucumber_cpp/acceptance_test/features --report console
38+
assert_success
39+
}
40+
41+
@test "All features in a folder" {
42+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features/subfolder --report console
43+
assert_success
44+
assert_output --partial "test1 scenario"
45+
assert_output --partial "test2 scenario"
46+
}
47+
48+
@test "Missing mandatory feature argument" {
49+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --report console
50+
assert_failure
51+
assert_output --partial "--feature is required"
52+
}
53+
54+
@test "Missing mandatory report argument" {
55+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features
56+
assert_failure
57+
assert_output --partial "--report is required"
58+
}
59+
60+
@test "Missing mandatory custom argument" {
61+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test.custom run --feature cucumber_cpp/acceptance_test/features --report console
62+
assert_failure
63+
assert_output --partial "--required is required"
64+
}
65+
66+
@test "Second feature file does not overwrite success with an undefined status" {
67+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --tag "@undefinedsuccess and @result:success" --feature cucumber_cpp/acceptance_test/features/test_undefined_success_1.feature cucumber_cpp/acceptance_test/features/test_undefined_success_2.feature --report console
68+
assert_success
69+
}
70+
71+
@test "Valid reporters only" {
72+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --report doesnotexist
73+
assert_failure
74+
assert_output --partial "--report: 'doesnotexist' is not a reporter"
75+
}
76+
77+
@test "Run Program hooks" {
78+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag @bats and @program_hooks --report console
79+
assert_success
80+
81+
assert_output --partial "HOOK_BEFORE_ALL"
82+
assert_output --partial "HOOK_AFTER_ALL"
83+
}
84+
85+
@test "Run Scenario hooks" {
86+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag @bats and @scenariohook and not @stephook --report console
87+
assert_success
88+
89+
assert_output --partial "HOOK_BEFORE_SCENARIO"
90+
assert_output --partial "HOOK_AFTER_SCENARIO"
91+
92+
refute_output --partial "HOOK_BEFORE_STEP"
93+
refute_output --partial "HOOK_AFTER_STEP"
94+
}
95+
96+
@test "Run Step hooks" {
97+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag @bats and @stephook and not @scenariohook --report console
98+
assert_success
99+
100+
refute_output --partial "HOOK_BEFORE_SCENARIO"
101+
refute_output --partial "HOOK_AFTER_SCENARIO"
102+
103+
assert_output --partial "HOOK_BEFORE_STEP"
104+
assert_output --partial "HOOK_AFTER_STEP"
105+
}
106+
107+
@test "Run Scenario and Step hooks" {
108+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@bats and (@scenariohook or @stephook)" --report console
109+
assert_success
110+
111+
assert_output --partial "HOOK_BEFORE_SCENARIO"
112+
assert_output --partial "HOOK_AFTER_SCENARIO"
113+
114+
assert_output --partial "HOOK_BEFORE_STEP"
115+
assert_output --partial "HOOK_AFTER_STEP"
116+
}
117+
118+
@test "Dry run with known failing steps" {
119+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@result:FAILED" --report console
120+
assert_failure
121+
122+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@result:FAILED" --report console --dry
123+
assert_success
124+
}
125+
126+
@test "Dry run with known missing steps" {
127+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@result:UNDEFINED" --report console --dry
128+
assert_failure
129+
assert_output --partial "undefined \"cucumber_cpp/acceptance_test/features/test_scenarios.feature\""
130+
assert_output --partial "skipped Then this should be skipped"
131+
}
132+
133+
@test "Test the and keyword" {
134+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@keyword-and" --report console
135+
assert_success
136+
assert_output --partial "--when--"
137+
assert_output --partial "--and--"
138+
}
139+
140+
@test "Test the but keyword" {
141+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@keyword-but" --report console
142+
assert_success
143+
assert_output --partial "--when--"
144+
assert_output --partial "--but--"
145+
}
146+
147+
@test "Test the asterisk keyword - will fail" {
148+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@keyword-asterisk" --report console
149+
assert_failure
150+
}
151+
152+
@test "Test passing scenario after failed scenario reports feature as failed" {
153+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@fail_feature" --report console
154+
assert_failure
155+
assert_output --partial "tests : 1/2 passed"
156+
}
157+
158+
@test "Test failing hook before results in error" {
159+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@fail_scenariohook_before" --report console
160+
assert_failure
161+
assert_output --partial "skipped Given a given step"
162+
assert_output --partial "tests : 0/1 passed"
163+
}
164+
165+
@test "Test failing hook after results in error" {
166+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@fail_scenariohook_after" --report console
167+
assert_failure
168+
assert_output --partial "Given a given step"
169+
assert_output --partial "done"
170+
assert_output --partial "failed"
171+
assert_output --partial "tests : 0/1 passed"
172+
}
173+
174+
@test "Test throwing hook results in error" {
175+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@throw_scenariohook" --report console
176+
assert_failure
177+
assert_output --partial "skipped Given a given step"
178+
assert_output --partial "tests : 0/1 passed"
179+
}
180+
181+
182+
@test "Test error program hook results in error and skipped steps" {
183+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test.custom run --feature cucumber_cpp/acceptance_test/features --tag "@smoke and @result:OK" --report console --required --failprogramhook
184+
assert_failure
185+
refute_output --partial "skipped Given a given step"
186+
refute_output --partial "should not be executed"
187+
assert_output --partial "tests : 0/0 passed"
188+
}
189+
190+
@test "Test unicode" {
191+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@unicode" --report console
192+
assert_success
193+
assert_output --partial "tests : 1/1 passed"
194+
}
195+
196+
@test "TestExceptionContinuesWithNextScenario" {
197+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@stepthrowcontinues" --report console
198+
assert_failure
199+
assert_output --partial "Exception thrown"
200+
refute_output --partial "Should Not Be Thrown"
201+
assert_output --partial "tests : 1/2 passed"
202+
}
203+
204+
@test "RunFeatureFileWithError" {
205+
run .build/Coverage/cucumber_cpp/acceptance_test/cucumber_cpp.acceptance_test run --feature cucumber_cpp/acceptance_test/features --tag "@fail_scenario" --report console
206+
assert_failure
207+
assert_output --partial "tests : 1/2 passed"
208+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@fail_scenario
2+
Feature: Simple feature file
3+
Rule: Test rule
4+
Scenario: Test scenario1
5+
Given 5 and 5 are equal
6+
Scenario: Test scenario2
7+
Given 4 and 5 are equal
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@stepthrowcontinues
2+
Feature: Test feature
3+
Scenario: Test scenario
4+
When I throw an exception
5+
Then the exception is caught
6+
7+
Scenario: Test scenario
8+
Then the next scenario is executed

cucumber_cpp/acceptance_test/steps/Steps.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include "cucumber_cpp/CucumberCpp.hpp"
22
#include "gmock/gmock.h"
33
#include "gtest/gtest.h"
4+
#include <cstdint>
45
#include <iostream>
6+
#include <stdexcept>
57
#include <string>
68

79
GIVEN("a background step")
@@ -60,3 +62,23 @@ GIVEN("Next block of text enclosed in \"\"\" characters")
6062

6163
ASSERT_THAT(docString, testing::Eq("Multiline\nDocstring"));
6264
}
65+
66+
WHEN("I throw an exception")
67+
{
68+
throw std::runtime_error{ "Exception thrown" };
69+
}
70+
71+
THEN("the exception is caught")
72+
{
73+
throw std::runtime_error{ "Should Not Be Thrown" };
74+
}
75+
76+
THEN("the next scenario is executed")
77+
{
78+
/* do nothing */
79+
}
80+
81+
GIVEN("{int} and {int} are equal", (std::int32_t a, std::int32_t b))
82+
{
83+
EXPECT_THAT(a, testing::Eq(b));
84+
}

cucumber_cpp/library/Application.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ namespace cucumber_cpp::library
9090
})
9191
{}
9292

93-
Application::Application(std::shared_ptr<ContextStorageFactory> contextStorageFactory)
93+
Application::Application(std::shared_ptr<ContextStorageFactory> contextStorageFactory, bool removeDefaultGoogleTestListener)
9494
: contextManager{ std::move(contextStorageFactory) }
9595
, reporters{ contextManager }
9696
, reportHandlerValidator{ reporters }
97+
, removeDefaultGoogleTestListener{ removeDefaultGoogleTestListener }
9798

9899
{
99100
gherkin.include_source(false);
@@ -198,12 +199,17 @@ namespace cucumber_cpp::library
198199

199200
const auto& runPolicy = (options.dryrun) ? static_cast<const engine::TestExecution::Policy&>(engine::dryRunPolicy)
200201
: static_cast<const engine::TestExecution::Policy&>(engine::executeRunPolicy);
201-
engine::TestExecutionImpl testExecution{ contextManager, reporters, hookExecution, runPolicy };
202+
203+
std::unique_ptr<engine::TestExecutionImpl> testExecution;
204+
if (removeDefaultGoogleTestListener)
205+
testExecution = std::make_unique<engine::TestExecutionImplWithoutDefaultGoogleListener>(contextManager, reporters, hookExecution, runPolicy);
206+
else
207+
testExecution = std::make_unique<engine::TestExecutionImpl>(contextManager, reporters, hookExecution, runPolicy);
202208

203209
StepRegistry stepRegistry{ parameterRegistry };
204210
engine::FeatureTreeFactory featureTreeFactory{ stepRegistry };
205211

206-
engine::TestRunnerImpl testRunner{ featureTreeFactory, testExecution };
212+
engine::TestRunnerImpl testRunner{ featureTreeFactory, *testExecution };
207213

208214
testRunner.Run(GetFeatureTree(featureTreeFactory, tagExpression));
209215

cucumber_cpp/library/Application.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace cucumber_cpp::library
4242
bool dryrun{ false };
4343
};
4444

45-
explicit Application(std::shared_ptr<ContextStorageFactory> contextStorageFactory = std::make_shared<ContextStorageFactoryImpl>());
45+
explicit Application(std::shared_ptr<ContextStorageFactory> contextStorageFactory = std::make_shared<ContextStorageFactoryImpl>(), bool removeDefaultGoogleTestListener = true);
4646

4747
int Run(int argc, const char* const* argv);
4848

@@ -72,6 +72,7 @@ namespace cucumber_cpp::library
7272
cucumber::gherkin::app gherkin;
7373

7474
cucumber_expression::ParameterRegistry parameterRegistry;
75+
bool removeDefaultGoogleTestListener;
7576
};
7677
}
7778

cucumber_cpp/library/Body.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#define CUCUMBER_CPP_BODY_HPP
33

44
#include <any>
5-
#include <concepts>
65
#include <string>
76
#include <variant>
87
#include <vector>

0 commit comments

Comments
 (0)