Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions cucumber-cpp-example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ add_executable(cucumber-cpp-example ${CCR_EXCLUDE_FROM_ALL})

target_sources(cucumber-cpp-example PRIVATE
fixtures/Fixture.hpp
hooks/hooks.cpp
steps/steps.cpp
)

target_link_libraries(cucumber-cpp-example PRIVATE
cucumber-cpp-runner
cucumber-cpp-example.hooks
cucumber-cpp-example.steps
)

add_subdirectory(hooks)
add_subdirectory(steps)
11 changes: 11 additions & 0 deletions cucumber-cpp-example/hooks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(CMAKE_COMPILE_WARNING_AS_ERROR On)

add_library(cucumber-cpp-example.hooks OBJECT ${CCR_EXCLUDE_FROM_ALL})

target_sources(cucumber-cpp-example.hooks PRIVATE
hooks.cpp
)

target_link_libraries(cucumber-cpp-example.hooks PRIVATE
cucumber-cpp-runner
)
6 changes: 3 additions & 3 deletions cucumber-cpp-example/hooks/hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ HOOK_BEFORE_ALL()
// spawn eventdispatcher
}

HOOK_BEFORE()
HOOK_BEFORE_SCENARIO()
{
}

HOOK_BEFORE_COND("@dingus")
HOOK_BEFORE_SCENARIO("@dingus")
{
std::cout << "running only for dingus tests\n";
}
Expand All @@ -41,7 +41,7 @@ HOOK_AFTER_STEP()
{
}

HOOK_AFTER()
HOOK_AFTER_SCENARIO()
{
}

Expand Down
11 changes: 11 additions & 0 deletions cucumber-cpp-example/steps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(CMAKE_COMPILE_WARNING_AS_ERROR On)

add_library(cucumber-cpp-example.steps OBJECT ${CCR_EXCLUDE_FROM_ALL})

target_sources(cucumber-cpp-example.steps PRIVATE
steps.cpp
)

target_link_libraries(cucumber-cpp-example.steps PRIVATE
cucumber-cpp-runner
)
14 changes: 7 additions & 7 deletions cucumber-cpp-example/steps/steps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ GIVEN(R"(a background step)")

GIVEN(R"(a simple data table)")
{
auto fixture = context->Get<NordicBleFixture>();
auto fixture = context.Get<NordicBleFixture>();
}

GIVEN(R"(there are ([0-9]+) cucumbers)", (std::uint32_t num))
{
context->InsertAt("cucumbers_before", num);
context.InsertAt("cucumbers_before", num);
}

STEP(R"(I eat {int} cucumbers)", (std::uint32_t num))
{
context->InsertAt("cucumbers_eaten", num);
context.InsertAt("cucumbers_eaten", num);
}

THEN(R"(^I should have ([0-9]+) cucumbers$)", (std::uint32_t num))
{
const auto& before = context->Get<std::uint32_t>("cucumbers_before");
const auto& eaten = context->Get<std::uint32_t>("cucumbers_eaten");
const auto& before = context.Get<std::uint32_t>("cucumbers_before");
const auto& eaten = context.Get<std::uint32_t>("cucumbers_eaten");

const auto actual = before - eaten;

Expand All @@ -41,8 +41,8 @@ THEN(R"(^I should have ([0-9]+) cucumbers$)", (std::uint32_t num))

THEN(R"(I should have ([0-9]+) cucumbers left)", (std::uint32_t num))
{
const auto& before = context->Get<std::uint32_t>("cucumbers_before");
const auto& eaten = context->Get<std::uint32_t>("cucumbers_eaten");
const auto& before = context.Get<std::uint32_t>("cucumbers_before");
const auto& eaten = context.Get<std::uint32_t>("cucumbers_eaten");

const auto actual = before - eaten;

Expand Down
4 changes: 2 additions & 2 deletions cucumber-cpp/Application.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "cucumber-cpp/Application.hpp"
#include "cucumber-cpp/Context.hpp"
#include "cucumber-cpp/FeatureRunner.hpp"
#include "cucumber-cpp/CucumberRunner.hpp"
#include "cucumber-cpp/ResultStates.hpp"
#include "cucumber-cpp/report/JsonReport.hpp"
#include "cucumber-cpp/report/JunitReport.hpp"
Expand Down Expand Up @@ -186,7 +186,7 @@ namespace cucumber_cpp

const auto tagExpression = options.tags.empty() ? std::string() : std::accumulate(std::next(options.tags.begin()), options.tags.end(), std::string(options.tags.front()), JoinStringWithSpace);

CucumberRunner cucumberRunner{ GetForwardArgs(), hooks, stepRepository, tagExpression, contextStorageFactory };
CucumberRunner cucumberRunner{ GetForwardArgs(), tagExpression, contextStorageFactory };
cucumberRunner.Run(root);

if (!root.contains("result"))
Expand Down
5 changes: 0 additions & 5 deletions cucumber-cpp/Application.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#ifndef CUCUMBER_CPP_APPLICATION_HPP
#define CUCUMBER_CPP_APPLICATION_HPP

#include "cucumber-cpp/CucumberRunner.hpp"
#include "cucumber-cpp/Hooks.hpp"
#include "cucumber-cpp/Steps.hpp"
#include "cucumber-cpp/report/Report.hpp"
#include "gherkin/app.hpp"
#include <map>
Expand Down Expand Up @@ -38,9 +36,6 @@ namespace cucumber_cpp
Options options;
nlohmann::json root;

cucumber_cpp::Hooks hooks;
cucumber_cpp::StepRepository stepRepository;

gherkin::app app;
gherkin::app::callbacks cbs;
};
Expand Down
50 changes: 50 additions & 0 deletions cucumber-cpp/Body.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#ifndef CUCUMBER_CPP_BODY_HPP
#define CUCUMBER_CPP_BODY_HPP

#include "nlohmann/json.hpp"
#include <cstddef>
#include <utility>

namespace cucumber_cpp
{
template<class To>
inline To StringTo(const std::string& s)
{
std::istringstream stream{ s };
To to;
stream >> to;
if (stream.fail())
{
throw std::invalid_argument("Cannot convert parameter");
}
return to;
}

template<>
inline std::string StringTo<std::string>(const std::string& s)
{
return s;
}

struct Body
{
virtual ~Body() = default;

virtual void Execute(const nlohmann::json& parameters = {}) = 0;

protected:
template<class T, class... Args, std::size_t... I>
void InvokeWithArgImpl(T* t, const nlohmann::json& json, void (T::*ptr)(Args...), std::index_sequence<I...>)
{
(t->*ptr)(StringTo<Args>(json[I])...);
}

template<class T, class... Args>
void InvokeWithArg(T* t, const nlohmann::json& json, void (T::*ptr)(Args...))
{
InvokeWithArgImpl(t, json, ptr, std::make_index_sequence<sizeof...(Args)>{});
}
};
}

#endif
34 changes: 34 additions & 0 deletions cucumber-cpp/BodyMacro.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef CUCUMBER_CPP_BODYMACRO_HPP
#define CUCUMBER_CPP_BODYMACRO_HPP

#include "cucumber-cpp/Body.hpp"

#define BODY_MATCHER(matcher, ...) matcher
#define BODY_ARGS(matcher, args, ...) args

#define CONCAT_(lhs, rhs) lhs##rhs
#define CONCAT(lhs, rhs) CONCAT_(lhs, rhs)

#define BODY_STRUCT CONCAT(BodyImpl, __LINE__)

#define BODY(matcher, type, args, registration, base) \
namespace \
{ \
struct BODY_STRUCT : cucumber_cpp::Body \
, cucumber_cpp::base \
{ \
using cucumber_cpp::base::base; \
void Execute(const nlohmann::json& parameters = {}) override \
{ \
InvokeWithArg(this, parameters, &BODY_STRUCT::ExecuteWithArgs); \
} \
\
private: \
void ExecuteWithArgs args; \
static std::size_t ID; \
}; \
} \
std::size_t BODY_STRUCT::ID = cucumber_cpp::registration<BODY_STRUCT>(matcher, type); \
void BODY_STRUCT::ExecuteWithArgs args

#endif
14 changes: 11 additions & 3 deletions cucumber-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,31 @@ add_library(cucumber-cpp STATIC ${CCR_EXCLUDE_FROM_ALL})
target_sources(cucumber-cpp PRIVATE
Application.cpp
Application.hpp
BodyMacro.hpp
Body.hpp
Context.hpp
CucumberRunner.cpp
CucumberRunner.hpp
FeatureRunner.cpp
FeatureRunner.hpp
Hooks.cpp
HookRegistry.cpp
HookRegistry.hpp
Hooks.hpp
HookScopes.cpp
HookScopes.hpp
JsonTagToSet.cpp
JsonTagToSet.hpp
OnTestPartResultEventListener.cpp
OnTestPartResultEventListener.hpp
Rtrim.cpp
Rtrim.hpp
ScenarioRunner.cpp
ScenarioRunner.hpp
Steps.hpp
StepRegistry.cpp
StepRegistry.hpp
StepRunner.cpp
StepRunner.hpp
Steps.cpp
Steps.hpp
TagExpression.cpp
TagExpression.hpp
TraceTime.cpp
Expand Down
12 changes: 6 additions & 6 deletions cucumber-cpp/CucumberRunner.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
#include "cucumber-cpp/CucumberRunner.hpp"
#include "cucumber-cpp/FeatureRunner.hpp"
#include "cucumber-cpp/HookScopes.hpp"
#include "cucumber-cpp/ResultStates.hpp"
#include "cucumber-cpp/ScenarioRunner.hpp"
#include "cucumber-cpp/TraceTime.hpp"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"

namespace cucumber_cpp
{
CucumberRunner::CucumberRunner(const std::vector<std::string_view>& args, Hooks& hooks, StepRepository& stepRepository, const std::string& tagExpr, std::shared_ptr<ContextStorageFactory> contextStorageFactory)
: hooks{ hooks }
, stepRepository{ stepRepository }
, tagExpr{ tagExpr }
CucumberRunner::CucumberRunner(const std::vector<std::string_view>& args, const std::string& tagExpr, std::shared_ptr<ContextStorageFactory> contextStorageFactory)
: tagExpr{ tagExpr }
, programContext(contextStorageFactory)
{
programContext.InsertAt("args", args);
}

void CucumberRunner::Run(nlohmann::json& json)
{
BeforeAfterAllScope programHookeScope{ hooks, programContext };
BeforeAfterAllScope programHookeScope{ programContext };

double totalTime = 0.0;

std::ranges::for_each(json["features"], [this, &json, &totalTime](nlohmann::json& featureJson)
{
FeatureRunner featureRunner{ hooks, stepRepository, programContext, tagExpr };
FeatureRunner featureRunner{ programContext, tagExpr };
featureRunner.Run(featureJson);

totalTime += featureJson.value("elapsed", 0.0);
Expand Down
5 changes: 1 addition & 4 deletions cucumber-cpp/CucumberRunner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "cucumber-cpp/Context.hpp"
#include "cucumber-cpp/Hooks.hpp"
#include "cucumber-cpp/Steps.hpp"
#include "nlohmann/json_fwd.hpp"
#include <memory>
#include <string>
Expand All @@ -12,13 +11,11 @@ namespace cucumber_cpp
{
struct CucumberRunner
{
CucumberRunner(const std::vector<std::string_view>& args, Hooks& hooks, StepRepository& stepRepository, const std::string& tagExpr, std::shared_ptr<ContextStorageFactory> contextStorageFactory);
CucumberRunner(const std::vector<std::string_view>& args, const std::string& tagExpr, std::shared_ptr<ContextStorageFactory> contextStorageFactory);

void Run(nlohmann::json& json);

private:
Hooks& hooks;
StepRepository& stepRepository;
std::string tagExpr;
Context programContext;
};
Expand Down
14 changes: 7 additions & 7 deletions cucumber-cpp/FeatureRunner.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
#include "cucumber-cpp/FeatureRunner.hpp"
#include "cucumber-cpp/Hooks.hpp"
#include "cucumber-cpp/HookScopes.hpp"
#include "cucumber-cpp/JsonTagToSet.hpp"
#include "cucumber-cpp/ResultStates.hpp"
#include "cucumber-cpp/ScenarioRunner.hpp"
#include "cucumber-cpp/TagExpression.hpp"
#include "cucumber-cpp/TraceTime.hpp"
#include "nlohmann/json.hpp"
#include <iomanip>
#include <ranges>

namespace cucumber_cpp
{
FeatureRunner::FeatureRunner(Hooks& hooks, StepRepository& stepRepository, Context& programContext, const std::string& tagExpr)
: hooks{ hooks }
, tagExpr{ tagExpr }
, stepRepository{ stepRepository }
FeatureRunner::FeatureRunner(Context& programContext, const std::string& tagExpr)
: tagExpr{ tagExpr }
, featureContext{ &programContext }
{}

void FeatureRunner::Run(nlohmann::json& json)
{
BeforeAfterFeatureHookScope featureHookScope{ hooks, featureContext, json };
BeforeAfterFeatureHookScope featureHookScope{ featureContext, JsonTagsToSet(json["ast"]["feature"]["tags"]) };

const auto isTagExprSelected = [this](const auto& json)
{
Expand All @@ -28,7 +28,7 @@ namespace cucumber_cpp
double totalTime = 0.0;
std::ranges::for_each(json["scenarios"] | std::views::filter(isTagExprSelected), [this, &json, &totalTime](nlohmann::json& scenarioJson)
{
ScenarioRunner scenarioRunner{ hooks, stepRepository, featureContext };
ScenarioRunner scenarioRunner{ featureContext };
scenarioRunner.Run(scenarioJson);

totalTime += scenarioJson.value("elapsed", 0.0);
Expand Down
5 changes: 1 addition & 4 deletions cucumber-cpp/FeatureRunner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@
#define CUCUMBER_CPP_FEATURERUNNER_HPP

#include "cucumber-cpp/Hooks.hpp"
#include "cucumber-cpp/Steps.hpp"
#include <string>

namespace cucumber_cpp
{
struct FeatureRunner
{
FeatureRunner(Hooks& hooks, StepRepository& stepRepository, Context& programContext, const std::string& tagExpr);
FeatureRunner(Context& programContext, const std::string& tagExpr);

void Run(nlohmann::json& json);

private:
Hooks& hooks;
StepRepository& stepRepository;
std::string tagExpr;
Context featureContext;
};
Expand Down
Loading