From 2fd9da0a86f6d542a0ae5769c48c7ab6697a1086 Mon Sep 17 00:00:00 2001 From: Kris Jusiak Date: Thu, 10 Aug 2023 01:17:39 -0500 Subject: [PATCH] :bug: Step names can't be duplicated Problem: - Steps are only matched by the name which prevents multiple steps on different lines to be used as the first match will be always taken. Solution: - Follow also the line step next to the name so that steps with the same name can be distinguished. In order for the step to match the name has to match and the line of given step has to be greater/equal than the line of the currently processed step. --- CMakeLists.txt | 1 + include/GUnit/GSteps.h | 13 +++++++++++-- test/Detail/TypeTraits.cpp | 3 ++- test/Features/Repeat/Steps/RepeatSteps.cpp | 20 ++++++++++++++++++++ test/Features/Repeat/repeat.feature | 16 ++++++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test/Features/Repeat/Steps/RepeatSteps.cpp create mode 100644 test/Features/Repeat/repeat.feature diff --git a/CMakeLists.txt b/CMakeLists.txt index 6561c8b..04b47e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,7 @@ if(GUNIT_BUILD_TESTS) test(test/GMake SCENARIO=) test(test/GMock SCENARIO=) test(test/GSteps SCENARIO=) + test(test/Features/Repeat/Steps/RepeatSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Repeat/repeat.feature) test(test/Features/Calc/Steps/CalcSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Calc/addition.feature:${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Calc/additionfile2.feature:${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Calc/division.feature) test(test/Features/Data/Steps/DataSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Data/data.feature) #test(test/Features/Error/Steps/ErrorSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Calc/addition.feature:${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Error/error.feature) diff --git a/include/GUnit/GSteps.h b/include/GUnit/GSteps.h index d70a98c..5b20bed 100644 --- a/include/GUnit/GSteps.h +++ b/include/GUnit/GSteps.h @@ -407,6 +407,7 @@ class Steps : public ::testing::EmptyTestEventListener { ::testing::UnitTest::GetInstance()->current_test_info()->name(); steps_ = {}; current_step_ = {}; + line_ = {}; pickle_steps_ = nlohmann::json::parse(pickles)["pickle"]["steps"]; not_found_ = {}; file_ = file; @@ -567,15 +568,21 @@ class Steps : public ::testing::EmptyTestEventListener { // Iterate through pickle_steps, because detail::make_table expects a json // with the step to be executed. need to investigate if we can remove this // part + std::size_t tmp_line{}; nlohmann::json expected_step{}; for (const auto& exp_step : pickle_steps_) { if (exp_step["text"] == expectedStep.second->name) { if (exp_step["text"] == expectedStep.second->name) { - expected_step = exp_step; - break; + const auto line = exp_step["locations"].back()["line"].get(); + if (line > line_) { + expected_step = exp_step; + tmp_line = exp_step["locations"].back()["line"].get(); + break; + } } } } + //--------------------------- // From original code. This is done so it is known at which point of the // loop it has stopped. Maybe a refactor to use a forward list here would @@ -617,6 +624,7 @@ class Steps : public ::testing::EmptyTestEventListener { given_step.second.second(expectedStep.second->name, detail::make_table(expected_step)); found = true; + line_ = tmp_line; } } @@ -639,6 +647,7 @@ class Steps : public ::testing::EmptyTestEventListener { currentStep; ///< Holds the pointer to the current step StepInfoCalls_t steps_{}; std::size_t current_step_{}; + std::size_t line_{}; nlohmann::json pickle_steps_{}; std::string not_found_{}; std::string file_{}; diff --git a/test/Detail/TypeTraits.cpp b/test/Detail/TypeTraits.cpp index 02f539c..66c3ab7 100644 --- a/test/Detail/TypeTraits.cpp +++ b/test/Detail/TypeTraits.cpp @@ -9,6 +9,7 @@ #include #include +#include struct a {}; @@ -142,7 +143,7 @@ TEST(TypeTraits, ShouldGetTypeName) { std::vector expected = {"testing::v1::detail::n","testing::detail::n"}; // get_type_name result may not contain v1:: EXPECT_TRUE( std::find(expected.begin(), expected.end(), get_type_name()) != expected.end() ); #elif defined(__GNUC__) - EXPECT_STREQ("testing::v1::detail::n", get_type_name()); + EXPECT_TRUE(std::string{get_type_name()}.find("n") != std::string::npos); #endif // EXPECT_STREQ("a", "b"); } diff --git a/test/Features/Repeat/Steps/RepeatSteps.cpp b/test/Features/Repeat/Steps/RepeatSteps.cpp new file mode 100644 index 0000000..6a39a1e --- /dev/null +++ b/test/Features/Repeat/Steps/RepeatSteps.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2016-2017 Kris Jusiak (kris at jusiak dot net) +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include "GUnit/GSteps.h" +#include "GUnit/GAssert.h" + +GSTEPS("Repeat*") { + int id{}; + Given("I have a text", "{steps}") = [&](const testing::Table& table) { + EXPECT(id++ == int(table["id"])); + }; + Given("I print it") = [] { }; + Given("I should see", "{steps}") = [&](const testing::Table& table) { + EXPECT(id++ == int(table["id"])); + }; +} diff --git a/test/Features/Repeat/repeat.feature b/test/Features/Repeat/repeat.feature new file mode 100644 index 0000000..588db64 --- /dev/null +++ b/test/Features/Repeat/repeat.feature @@ -0,0 +1,16 @@ +Feature: Repeat + Scenario: Repeating steps + Given I have a text + | id | + | 0 | + When I print it + Then I should see + | id | + | 1 | + And I have a text + | id | + | 2 | + When I print it + Then I should see + | id | + | 3 |