Skip to content

Commit 36bd74b

Browse files
Mark90youtux
authored andcommitted
Implement parsing escaped pipe characters in outline parameters (#337)
* Implement parsing escaped pipe characters in outline parameters * Use unicode_literals to fix test_outline error in Python 2
1 parent 3f1ba96 commit 36bd74b

File tree

2 files changed

+77
-10
lines changed

2 files changed

+77
-10
lines changed

pytest_bdd/feature.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
STEP_PARAM_RE = re.compile(r"\<(.+?)\>")
6161
COMMENT_RE = re.compile(r"(^|(?<=\s))#")
62+
SPLIT_LINE_RE = re.compile(r"(?<!\\)\|")
6263

6364

6465
def get_step_type(line):
@@ -141,6 +142,16 @@ def get_tags(line):
141142
return set((tag.lstrip("@") for tag in line.strip().split(" @") if len(tag) > 1))
142143

143144

145+
def split_line(line):
146+
"""Split the given Examples line.
147+
148+
:param str|unicode line: Feature file Examples line.
149+
150+
:return: List of strings.
151+
"""
152+
return [cell.replace("\\|", "|").strip() for cell in SPLIT_LINE_RE.split(line[1:-1])]
153+
154+
144155
def get_features(paths, **kwargs):
145156
"""Get features for given paths.
146157
@@ -361,14 +372,12 @@ def __init__(self, basedir, filename, encoding="utf-8", strict_gherkin=True):
361372
mode = types.EXAMPLE_LINE_VERTICAL
362373
(scenario or self).examples.line_number = line_number
363374
elif mode == types.EXAMPLES_HEADERS:
364-
(scenario or self).examples.set_param_names(
365-
[l.strip() for l in parsed_line.split("|")[1:-1] if l.strip()]
366-
)
375+
(scenario or self).examples.set_param_names([l for l in split_line(parsed_line) if l])
367376
mode = types.EXAMPLE_LINE
368377
elif mode == types.EXAMPLE_LINE:
369-
(scenario or self).examples.add_example([l.strip() for l in stripped_line.split("|")[1:-1]])
378+
(scenario or self).examples.add_example([l for l in split_line(stripped_line)])
370379
elif mode == types.EXAMPLE_LINE_VERTICAL:
371-
param_line_parts = [l.strip() for l in stripped_line.split("|")[1:-1]]
380+
param_line_parts = [l for l in split_line(stripped_line)]
372381
try:
373382
(scenario or self).examples.add_example_row(param_line_parts[0], param_line_parts[1:])
374383
except exceptions.ExamplesNotValidError as exc:

tests/feature/test_outline.py

+63-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Scenario Outline tests."""
2+
from __future__ import unicode_literals
23
import re
34
import textwrap
45

@@ -11,7 +12,7 @@
1112

1213
@scenario("outline.feature", "Outlined given, when, thens", example_converters=dict(start=int, eat=float, left=str))
1314
def test_outlined(request):
14-
assert get_parametrize_markers_args(request.node) == ([u"start", u"eat", u"left"], [[12, 5.0, "7"], [5, 4.0, "1"]])
15+
assert get_parametrize_markers_args(request.node) == (["start", "eat", "left"], [[12, 5.0, "7"], [5, 4.0, "1"]])
1516

1617

1718
@given("there are <start> cucumbers")
@@ -56,7 +57,7 @@ def test_wrong_vertical_examples_scenario(testdir):
5657
feature = features.join("test.feature")
5758
feature.write_text(
5859
textwrap.dedent(
59-
u"""
60+
"""
6061
Scenario Outline: Outlined with wrong vertical example table
6162
Given there are <start> cucumbers
6263
When I eat <eat> cucumbers
@@ -89,7 +90,7 @@ def test_wrong_vertical_examples_feature(testdir):
8990
feature = features.join("test.feature")
9091
feature.write_text(
9192
textwrap.dedent(
92-
u"""
93+
"""
9394
Feature: Outlines
9495
9596
Examples: Vertical
@@ -133,7 +134,7 @@ def test_outlined_with_other_fixtures(other_fixture):
133134
)
134135
def test_vertical_example(request):
135136
"""Test outlined scenario with vertical examples table."""
136-
assert get_parametrize_markers_args(request.node) == ([u"start", u"eat", u"left"], [[12, 5.0, "7"], [2, 1.0, "1"]])
137+
assert get_parametrize_markers_args(request.node) == (["start", "eat", "left"], [[12, 5.0, "7"], [2, 1.0, "1"]])
137138

138139

139140
@given("there are <start> <fruits>")
@@ -164,5 +165,62 @@ def test_outlined_feature(request):
164165
["start", "eat", "left"],
165166
[[12, 5.0, "7"], [5, 4.0, "1"]],
166167
["fruits"],
167-
[[u"oranges"], [u"apples"]],
168+
[["oranges"], ["apples"]],
168169
)
170+
171+
172+
def test_outline_with_escaped_pipes(testdir):
173+
"""Test parametrized feature example table with escaped pipe characters in input."""
174+
features = testdir.mkdir("features")
175+
feature = features.join("test.feature")
176+
feature.write_text(
177+
textwrap.dedent(
178+
r"""
179+
Feature: Outline With Special characters
180+
181+
Scenario Outline: Outline with escaped pipe character
182+
Given We have strings <string1> and <string2>
183+
Then <string2> should be the base64 encoding of <string1>
184+
185+
Examples:
186+
| string1 | string2 |
187+
| bork | Ym9yaw== |
188+
| \|bork | fGJvcms= |
189+
| bork \| | Ym9yayB8 |
190+
| bork\|\|bork | Ym9ya3x8Ym9yaw== |
191+
| \| | fA== |
192+
| bork \\ | Ym9yayAgICAgIFxc |
193+
| bork \\\| | Ym9yayAgICBcXHw= |
194+
"""
195+
),
196+
"utf-8",
197+
ensure=True,
198+
)
199+
200+
testdir.makepyfile(
201+
textwrap.dedent(
202+
"""
203+
import base64
204+
205+
from pytest_bdd import scenario, given, when, then
206+
from pytest_bdd.utils import get_parametrize_markers_args
207+
208+
209+
@scenario("features/test.feature", "Outline with escaped pipe character")
210+
def test_outline_with_escaped_pipe_character(request):
211+
pass
212+
213+
214+
@given("We have strings <string1> and <string2>")
215+
def we_have_strings_string1_and_string2(string1, string2):
216+
pass
217+
218+
219+
@then("<string2> should be the base64 encoding of <string1>")
220+
def string2_should_be_base64_encoding_of_string1(string2, string1):
221+
assert string1.encode() == base64.b64decode(string2.encode())
222+
"""
223+
)
224+
)
225+
result = testdir.runpytest()
226+
result.stdout.fnmatch_lines(["* 7 passed *"])

0 commit comments

Comments
 (0)