Skip to content

Commit ca918d5

Browse files
authored
fix: catch exceptions while constructing a step fixture (#364)
Exceptions were already caught when executing a step (hook implementation or step implementation). But custom step test fixtures could also throw (missing context values, ASSERT_'s etc). These were not caught. This PR ensures both the construction of a step and the execution of a step are properly inside a try/catch block.
1 parent 0b2e0e8 commit ca918d5

21 files changed

Lines changed: 218 additions & 252 deletions

cucumber_cpp/Steps.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "cucumber_cpp/library/cucumber_expression/MatchRange.hpp"
99
#include "cucumber_cpp/library/cucumber_expression/ParameterRegistry.hpp"
1010
#include "cucumber_cpp/library/engine/ExecutionContext.hpp"
11+
#include "cucumber_cpp/library/engine/Hook.hpp"
1112
#include "cucumber_cpp/library/util/DocString.hpp"
1213
#include "cucumber_cpp/library/util/Table.hpp"
1314

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
@nested_steps
21
Feature: Nested Steps
2+
@nested_steps
33
Scenario: Call other steps from within a step
44
Given a step calls another step with "cucumber"
55
Then the stored string is "cucumber"
6+
7+
@nested_failing_steps
8+
Scenario: Call other steps from within a step
9+
When a step calls another step that will fail
10+
Then this should be skipped
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@fail_step_fixture
2+
Feature: Simple feature file
3+
Rule: Test rule
4+
Scenario: Test scenario without failing step fixture
5+
Given step fixture does not fail
6+
Scenario: Test with failing step fixture
7+
Given step fixture fails

cucumber_cpp/acceptance_test/steps/Steps.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "cucumber_cpp/CucumberCpp.hpp"
1+
#include "cucumber_cpp/Steps.hpp"
22
#include "fmt/format.h"
33
#include "gmock/gmock.h"
44
#include "gtest/gtest.h"
@@ -107,7 +107,7 @@ THEN("the exception is caught")
107107

108108
THEN("the next scenario is executed")
109109
{
110-
/* do nothing */
110+
// empty
111111
}
112112

113113
GIVEN("{int} and {int} are equal", (std::int32_t a, std::int32_t b))
@@ -140,3 +140,30 @@ GIVEN(R"(I attach a link to {string})", (const std::string& url))
140140
{
141141
Link(url, "title");
142142
}
143+
144+
GIVEN(R"(step fixture does not fail)")
145+
{
146+
// empty
147+
}
148+
149+
struct FailingStepFixture : cucumber_cpp::StepBase
150+
{
151+
using StepBase::StepBase;
152+
153+
bool nonExistentKey = context.Get<bool>("nonExistentKey");
154+
};
155+
156+
GIVEN_F(FailingStepFixture, R"(step fixture fails)")
157+
{
158+
// empty
159+
}
160+
161+
GIVEN("a nested step that fails")
162+
{
163+
ASSERT_THAT(false, testing::IsTrue());
164+
}
165+
166+
GIVEN("a step calls another step that will fail")
167+
{
168+
Step("a nested step that fails");
169+
}

cucumber_cpp/acceptance_test/steps/UsedUnused.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "cucumber_cpp/CucumberCpp.hpp"
1+
#include "cucumber_cpp/Steps.hpp"
22

33
STEP("This step is unused")
44
{

cucumber_cpp/acceptance_test/test.bats

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,21 @@ teardown() {
222222
assert_output --partial "| this step is used | - |"
223223
assert_output --partial "| This step is unused | UNUSED |"
224224
}
225+
226+
@test "Test failure in step fixture results in error" {
227+
run $acceptance_test --format summary --format-options "{ \"summary\": {\"theme\":\"plain\"} }" --tags "@fail_step_fixture" -- cucumber_cpp/acceptance_test/features
228+
assert_failure
229+
assert_output --partial "key not found: \"nonExistentKey\""
230+
assert_output --partial "2 scenarios 1 passed, 1 failed"
231+
assert_output --partial "2 steps 1 passed, 1 failed"
232+
}
233+
234+
@test "Test nested failures propagate properly" {
235+
run $acceptance_test --format summary --format-options "{ \"summary\": {\"theme\":\"plain\"} }" --tags "@nested_failing_steps" -- cucumber_cpp/acceptance_test/features
236+
assert_failure
237+
assert_output --partial "FAILED nested step: \"* a nested step that fails\""
238+
assert_output --partial "Value of: false"
239+
assert_output --partial "Expected: is true"
240+
assert_output --partial "Actual: false (of type bool)"
241+
assert_output --partial "↷ Then this should be skipped"
242+
}

cucumber_cpp/example/steps/Steps.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "cucumber_cpp/library/Steps.hpp"
2-
#include "cucumber_cpp/CucumberCpp.hpp"
2+
#include "cucumber_cpp/Steps.hpp"
33
#include "cucumber_cpp/library/Context.hpp"
44
#include "gmock/gmock.h"
55
#include "gtest/gtest.h"

cucumber_cpp/library/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ add_subdirectory(tag_expression)
4848
add_subdirectory(util)
4949

5050
if (CCR_BUILD_TESTS)
51-
# add_subdirectory(test)
51+
add_subdirectory(test)
5252
endif()

cucumber_cpp/library/engine/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ target_link_libraries(cucumber_cpp.library.engine PUBLIC
2424

2525
if (CCR_BUILD_TESTS)
2626
add_subdirectory(test)
27-
# add_subdirectory(test_helper)
27+
add_subdirectory(test_helper)
2828
endif()

cucumber_cpp/library/engine/test_helper/StepImplementations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ WHEN("I call a nested step")
6262
{
6363
ASSERT_THAT(context.Contains("nested"), testing::IsFalse());
6464

65-
Given("I am a nested step");
65+
Step("I am a nested step");
6666
}
6767

6868
THEN("the nested step was called")

0 commit comments

Comments
 (0)