Skip to content

Commit 8e3d6d4

Browse files
committed
🆕 Nicely catch and print parsing errors
1 parent a9d7bd9 commit 8e3d6d4

File tree

4 files changed

+52
-24
lines changed

4 files changed

+52
-24
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ test(test/GMake SCENARIO=)
7676
test(test/GMock SCENARIO=)
7777
test(test/GSteps SCENARIO=)
7878
test(test/Features/Calc/Steps/CalcSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Calc/addition.feature:${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Calc/division.feature)
79+
#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)
7980
test(test/Features/Table/Steps/TableSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Table/table.feature)
8081
test(test/Features/Tags/Steps/TagsSteps SCENARIO=${CMAKE_CURRENT_SOURCE_DIR}/test/Features/Tags/tags.feature)
8182
test(test/GTest SCENARIO=)

include/GUnit/GSteps.h

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <unordered_map>
1818
#include <utility>
1919
#include <vector>
20+
#include <cstdlib>
2021
#include "GUnit/Detail/FileUtils.h"
2122
#include "GUnit/Detail/Preprocessor.h"
2223
#include "GUnit/Detail/RegexUtils.h"
@@ -168,7 +169,8 @@ class Steps {
168169
steps.Init(pickles, file);
169170
static_cast<TCRTP&>(steps).Run();
170171
if (steps.current_step_ != steps.pickle_steps_.size()) {
171-
throw StepIsNotImplemented{"STEP \"" + steps.not_found_ + "\" not implemented!"};
172+
throw StepIsNotImplemented{"STEP \"" + steps.not_found_ +
173+
"\" not implemented!"};
172174
}
173175
std::cout << '\n';
174176
}
@@ -365,30 +367,40 @@ class Steps {
365367
}
366368

367369
void ParseAndRegister(const std::string& name, const std::string& feature) {
368-
const auto content = read_file(feature);
369-
gherkin::parser parser{L"en"};
370-
gherkin::compiler compiler{feature};
371-
const auto gherkin_document = parser.parse(content);
372-
const auto pickles = compiler.compile(gherkin_document);
373-
const auto ast = nlohmann::json::parse(compiler.ast(gherkin_document));
374-
375-
for (const auto& pickle : pickles) {
376-
const std::string feature_name = ast["document"]["feature"]["name"];
377-
const auto pickle_json = nlohmann::json::parse(pickle)["pickle"];
378-
const std::string scenario_name = pickle_json["name"];
379-
const auto tags = detail::make_tags(pickle_json["tags"]);
380-
const auto disabled = tags.first ? "DISABLED_" : "";
381-
const auto full_name = feature_name + "." + scenario_name;
382-
383-
if (PatternMatchesString(name.c_str(), full_name.c_str())) {
384-
info_.feature = feature_name;
385-
386-
detail::MakeAndRegisterTestInfo(
387-
new TestFactory{*this, pickle, feature},
388-
disabled + feature_name + tags.second, scenario_name, __FILE__,
389-
__LINE__,
390-
detail::type<decltype(internal::MakeAndRegisterTestInfo)>{});
370+
try {
371+
const auto content = read_file(feature);
372+
gherkin::parser parser{L"en"};
373+
gherkin::compiler compiler{feature};
374+
const auto gherkin_document = parser.parse(content);
375+
const auto pickles = compiler.compile(gherkin_document);
376+
const auto ast = nlohmann::json::parse(compiler.ast(gherkin_document));
377+
378+
for (const auto& pickle : pickles) {
379+
const std::string feature_name = ast["document"]["feature"]["name"];
380+
const auto pickle_json = nlohmann::json::parse(pickle)["pickle"];
381+
const std::string scenario_name = pickle_json["name"];
382+
const auto tags = detail::make_tags(pickle_json["tags"]);
383+
const auto disabled = tags.first ? "DISABLED_" : "";
384+
const auto full_name = feature_name + "." + scenario_name;
385+
386+
if (PatternMatchesString(name.c_str(), full_name.c_str())) {
387+
info_.feature = feature_name;
388+
389+
detail::MakeAndRegisterTestInfo(
390+
new TestFactory{*this, pickle, feature},
391+
disabled + feature_name + tags.second, scenario_name, __FILE__,
392+
__LINE__,
393+
detail::type<decltype(internal::MakeAndRegisterTestInfo)>{});
394+
}
391395
}
396+
} catch (const gherkin::v1::parsing_error& err) {
397+
const auto err_json = nlohmann::json::parse(err.what());
398+
const auto line = err_json["source"]["start"]["line"];
399+
const auto column = err_json["source"]["start"]["column"];
400+
const std::string error = err_json["data"];
401+
402+
std::cerr << feature << ":" << line << ":" << column << ": error: " << error << std::endl;
403+
std::exit(-1);
392404
}
393405
}
394406

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//
2+
// Copyright (c) 2016-2017 Kris Jusiak (kris at jusiak dot net)
3+
//
4+
// Distributed under the Boost Software License, Version 1.0.
5+
// (See accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt)
7+
//
8+
#include "GUnit/GSteps.h"
9+
10+
GSTEPS("Error*") { }

test/Features/Error/error.feature

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
feature_parsing_error: Error
2+
3+
Scenario: Parsing error
4+
Given I have a parsing error
5+
Then An exception should be thrown

0 commit comments

Comments
 (0)