diff --git a/python/cucumber_tag_expressions/parser.py b/python/cucumber_tag_expressions/parser.py index 7db37e47..09787987 100644 --- a/python/cucumber_tag_expressions/parser.py +++ b/python/cucumber_tag_expressions/parser.py @@ -221,8 +221,10 @@ def parse(cls, text): def ensure_expected_token_type(token_type, index): if expected_token_type != token_type: - message = "Syntax error. Expected %s after %s" % \ - (expected_token_type.name.lower(), last_part) + message = ( + 'Tag expression "%s" could not be parsed because of syntax ' + 'error: Expected %s.' % (text, expected_token_type.name.lower()) + ) message = cls._make_error_description(message, parts, index) raise TagExpressionError(message) @@ -262,7 +264,10 @@ def ensure_expected_token_type(token_type, index): if not operations: # -- CASE: TOO FEW OPEN-PARENTHESIS - message = "Missing '(': Too few open-parens in: %s" % text + message = ( + 'Tag expression "%s" could not be parsed because of syntax ' + 'error: Unmatched ).' % text + ) message = cls._make_error_description(message, parts, index) raise TagExpressionError(message) elif operations[-1] is Token.OPEN_PARENTHESIS: @@ -275,7 +280,10 @@ def ensure_expected_token_type(token_type, index): last_operation = operations.pop() if last_operation is Token.OPEN_PARENTHESIS: # -- CASE: TOO MANY OPEN-PARENTHESIS - message = "Unclosed '(': Too many open-parens in: %s" % text + message = ( + 'Tag expression "%s" could not be parsed because of syntax error:' + ' Unmatched (.' % text + ) raise TagExpressionError(message) cls._push_expression(last_operation, expressions) diff --git a/python/tests/data/test_errors.py b/python/tests/data/test_errors.py index b3a6d3fb..6aea794d 100644 --- a/python/tests/data/test_errors.py +++ b/python/tests/data/test_errors.py @@ -39,7 +39,6 @@ def read_testdata(data_filename): # ----------------------------------------------------------------------------- this_testdata = read_testdata(TESTDATA_FILE) -@pytest.mark.skip(reason="TOO MANY DIFFERENCES: Error message here are more specific (IMHO)") @pytest.mark.parametrize("expression, error", this_testdata) def test_errors_with_datafile(expression, error): with pytest.raises(TagExpressionError) as exc_info: diff --git a/python/tests/unit/test_parser.py b/python/tests/unit/test_parser.py index 91177ab8..1741b645 100644 --- a/python/tests/unit/test_parser.py +++ b/python/tests/unit/test_parser.py @@ -193,41 +193,41 @@ def test_parse__with_escape_repr(self, text, expected): # -- BAD CASES: @pytest.mark.parametrize("text, error_message", [ - ("( a and b ))", "Missing '(': Too few open-parens"), - ("( ( a and b )", "Unclosed '(': Too many open-parens"), + ("( a and b ))", "Unmatched )."), + ("( ( a and b )", "Unmatched (."), ]) def test_parse__fails_with_unbalanced_parens(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message) @pytest.mark.parametrize("text, error_message", [ - ("a not ( and )", "Syntax error. Expected operator after a"), + ("a not ( and )", "syntax error: Expected operator"), ]) def test_parse__fails_with_missing_operation_args(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message) @pytest.mark.parametrize("text, error_message", [ - ("or or", "Syntax error. Expected operand after BEGIN"), + ("or or", "syntax error: Expected operand"), ]) def test_parse__fails_with_only_operations(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message) @pytest.mark.parametrize("text, error_message", [ - ("a b", "Syntax error. Expected operator after a"), + ("a b", "syntax error: Expected operator"), ]) def test_parse__fails_for_args_without_operation(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message) @pytest.mark.parametrize("text, error_message", [ - ("(())", "Syntax error. Expected operand after ("), - ("(() ())", "Syntax error. Expected operand after ("), + ("(())", "syntax error: Expected operand"), + ("(() ())", "syntax error: Expected operand"), ]) def test_parse__fails_for_empty_parens_groups(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message) @pytest.mark.parametrize("text, expected", [ - ("a b or", "Syntax error. Expected operator after a"), - ("a and (b not)", "Syntax error. Expected operator after b"), - ("a and (b c) or", "Syntax error. Expected operator after b"), + ("a b or", "syntax error: Expected operator"), + ("a and (b not)", "syntax error: Expected operator"), + ("a and (b c) or", "syntax error: Expected operator"), ]) def test_parse__fails_with_rpn_notation(self, text, expected): # -- NOTE: RPN parsebility due to Shunting-yard algorithm (stack-based). @@ -252,14 +252,14 @@ def test_parse__fails_with_rpn_notation(self, text, expected): # -- BAD CASES: Too few operands @pytest.mark.parametrize("text, error_message", [ ("a and ", "and: Too few operands"), - (" and b", "Syntax error. Expected operand after BEGIN"), + (" and b", "syntax error: Expected operand"), ]) def test_parse__fails_and_operation_with_too_few_args(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message) @pytest.mark.parametrize("text, error_message", [ ("a or ", "or: Too few operands"), - (" or b", "Syntax error. Expected operand after BEGIN"), + (" or b", "syntax error: Expected operand"), ("a and b or ", "or: Too few operands"), ]) def test_parse__fails_or_operation_with_too_few_args(self, text, error_message): @@ -267,9 +267,9 @@ def test_parse__fails_or_operation_with_too_few_args(self, text, error_message): @pytest.mark.parametrize("text, error_message", [ ("not ", "not: Too few operands"), - ("not ()", "Syntax error. Expected operand after ("), - ("not () and b", "Syntax error. Expected operand after ("), - ("not () or b", "Syntax error. Expected operand after ("), + ("not ()", "syntax error: Expected operand"), + ("not () and b", "syntax error: Expected operand"), + ("not () or b", "syntax error: Expected operand"), ]) def test_parse__fails_not_operation_with_too_few_args(self, text, error_message): self.assert_parse_with_error_contains_message(text, error_message)