Skip to content

Commit 2986964

Browse files
authored
Merge pull request #17 from ltamshen/feature/add-feature-tag
Add tag feature
2 parents 8e6b57f + 189b312 commit 2986964

File tree

5 files changed

+110
-8
lines changed

5 files changed

+110
-8
lines changed

planterbox/feature.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class FeatureTestCase(TestCase):
6262
"""A test case generated from the scenarios in a feature file."""
6363

6464
def __init__(self, feature_path, scenarios_to_run=None, feature_text=None,
65-
config=None):
65+
config=None, tag_list=()):
6666
super(FeatureTestCase, self).__init__('nota')
6767
self.feature_path = feature_path
6868
self.scenarios_to_run = scenarios_to_run
@@ -79,6 +79,8 @@ def __init__(self, feature_path, scenarios_to_run=None, feature_text=None,
7979
self.feature_doc = [doc.strip() for doc in header_text[1:]]
8080
self.step_inventory = list(self.harvest_steps())
8181
self.check_scenarios()
82+
self.tag_list = check_tag_list(tag_list)
83+
8284

8385
def id(self):
8486
if self.scenarios_to_run:
@@ -144,16 +146,22 @@ def run(self, result=None):
144146
run_hooks(module, self, result, 'before', 'feature')
145147
try:
146148
for i, scenario in enumerate(self.scenarios):
147-
if (
148-
self.scenarios_to_run and
149-
not self.should_run_scenario(i, scenario)
150-
):
151-
continue
149+
152150
(
153151
self.scenario_name,
154152
scenario_steps,
155153
scenario_examples,
154+
scenario_tags,
156155
) = scenario
156+
157+
if (not matches_tag(scenario_tags, self.tag_list) or
158+
(
159+
self.scenarios_to_run and
160+
not self.should_run_scenario(i, scenario)
161+
)):
162+
continue
163+
164+
157165
if scenario_examples:
158166
scenario_examples = list(
159167
self.load_examples(scenario_examples))
@@ -208,6 +216,7 @@ def check_scenarios(self):
208216
self.scenario_name,
209217
scenario_steps,
210218
scenario_examples,
219+
scenario_tags,
211220
) = scenario
212221
if scenario_examples:
213222
# Do the example thing
@@ -402,3 +411,20 @@ def run_hook(tester, result, hook):
402411
except Exception as e:
403412
result.addError(tester, sys.exc_info())
404413
raise HookFailedException('Error')
414+
415+
416+
def matches_tag(scenario_tags, tag_list):
417+
''' If tags indicated on command line, returns True if a Scenario_tag matches
418+
one given on the command line'''
419+
if not tag_list:
420+
return True
421+
else:
422+
return set(scenario_tags).intersection(tag_list)
423+
424+
425+
def check_tag_list(tag_list):
426+
''' Makes a list of any tags entered on the command line. '''
427+
tags = []
428+
if len(tag_list) !=0:
429+
tags = tag_list[0].split(',')
430+
return tags

planterbox/parsing.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
INDENT = re.compile(r'^\s+')
77
SCENARIO = re.compile(r'^\s+Scenario(?: Outline)?:')
8+
SCENARIO_TAG = re.compile(r'^\s+Scenario Tag:')
89
EXAMPLES = re.compile(r'^\s+Examples:')
910

1011

@@ -32,6 +33,11 @@ def starts_scenario(line):
3233
return SCENARIO.match(line)
3334

3435

36+
def starts_scenario_tag(line):
37+
"""Determine if a line signals the start of a scenario."""
38+
return SCENARIO_TAG.match(line)
39+
40+
3541
def starts_examples(line):
3642
"""Determine if a line signals the start of an example block."""
3743
return EXAMPLES.match(line)
@@ -57,6 +63,7 @@ def parse_feature(feature_text):
5763
scenarios = []
5864
scenario = None
5965
append_index = 1
66+
scenario_tag_index = 3
6067
scenario_indent = 0
6168
in_multiline = False
6269

@@ -83,11 +90,16 @@ def parse_feature(feature_text):
8390
elif starts_examples(line):
8491
append_index = 2
8592
else:
86-
scenario[append_index].append(line)
93+
if starts_scenario_tag(line):
94+
scenario[scenario_tag_index] += list(
95+
line.replace(' ','').split('ScenarioTag:')[1].split(','))
96+
continue
97+
else:
98+
scenario[append_index].append(line)
8799

88100
if scenario is None: # Not elif - want to handle end-of-scenario
89101
if starts_scenario(line):
90-
scenario = [line, [], []]
102+
scenario = [line, [], [], []]
91103
append_index = 1
92104
scenario_indent = indent_level(line)
93105
scenarios.append(scenario)

planterbox/plugin.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Planterbox(Plugin):
3636
commandLineSwitch = (None, 'with-planterbox',
3737
'Load tests from .feature files')
3838
checkOnly = False
39+
tag_list=[]
3940

4041
def __init__(self):
4142
super(Plugin, self).__init__()
@@ -46,6 +47,14 @@ def __init__(self):
4647
Don't run planterbox tests.""",
4748
)
4849

50+
self.addOption(
51+
self.tag_list, None, 'tag',
52+
help_text="""tag allows selective running of scenarios
53+
Examples: tag=abc or tag=abc,def""",
54+
nargs=1
55+
)
56+
57+
4958
def register(self):
5059
super(Planterbox, self).register()
5160

@@ -65,6 +74,7 @@ def register(self):
6574
def setCheckOnly(self, *args):
6675
self.checkOnly = True
6776

77+
6878
def makeSuiteFromFeature(self, module, feature_path,
6979
scenarios_to_run=None):
7080
MyTestSuite = transplant_class(TestSuite, module.__name__)
@@ -85,6 +95,7 @@ def makeSuiteFromFeature(self, module, feature_path,
8595
feature_path=feature_path,
8696
scenarios_to_run=scenarios_to_run,
8797
config=self.config,
98+
tag_list=self.tag_list,
8899
),
89100
],
90101
)

planterbox/tests/test_feature/basic.feature

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
Feature: Basic Tests
22
I want to exercise generation of a simple test from a feature.
33

4+
45
Scenario: I need to verify basic arithmetic.
6+
Scenario Tag: math1, math2
57
Given I add 1 and 1
68
Then the result should be 2
79

planterbox/tests/test_scenario_test_case.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,54 @@ def mock_addFailure(result, exc):
305305
self.fail(formatted)
306306

307307
self.assertEqual(mock_world.test_thing.call_count, 2)
308+
309+
310+
def test_scenario_tag(self):
311+
from planterbox.feature import FeatureTestCase
312+
from planterbox import step
313+
314+
test_feature = """Feature: A Scenario Tag Feature
315+
316+
Scenario: A Test Scenario.
317+
Scenario Tag: math2
318+
When I test a thing
319+
320+
Scenario: An Untagged Test Scenario.
321+
When I test a thing
322+
"""
323+
324+
@step(r'I test a thing')
325+
def test_thing(test):
326+
pass
327+
328+
mock_world = Mock(
329+
spec=['test_thing'],
330+
return_value=None,
331+
)
332+
mock_world.__name__ = 'mock'
333+
mock_world.test_thing = step(r'I test a thing')(Mock(
334+
planterbox_patterns=[],
335+
))
336+
337+
338+
def mock_addFailure(result, exc):
339+
self.exc_info = exc
340+
341+
mock_result = Mock(addFailure=Mock(side_effect=mock_addFailure))
342+
343+
with patch('planterbox.feature.import_module',
344+
Mock(return_value=mock_world)):
345+
test_case = FeatureTestCase(
346+
feature_path='foobar.feature',
347+
feature_text=test_feature,
348+
tag_list = ("math2",)
349+
)
350+
351+
test_case.__module__ = 'mock'
352+
test_case.run(mock_result)
353+
354+
if hasattr(self, 'exc_info'):
355+
formatted = test_case.formatTraceback(self.exc_info)
356+
self.fail(formatted)
357+
358+
mock_world.test_thing.assert_called_once()

0 commit comments

Comments
 (0)