-
Notifications
You must be signed in to change notification settings - Fork 46
/
environment.py
131 lines (102 loc) · 4.06 KB
/
environment.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from copy import copy
from behave import step_registry as module_step_registry
from behave.runner import Context, ModelRunner
from django.shortcuts import resolve_url
class PatchedContext(Context):
"""Provides methods for Behave's ``context`` variable."""
@property
def base_url(self):
try:
return self.test.live_server_url
except AttributeError as err:
msg = (
'Web browser automation is not available. '
'This scenario step can not be run with the --simple or -S flag.'
)
raise RuntimeError(msg) from err
def get_url(self, to=None, *args, **kwargs):
return self.base_url + (resolve_url(to, *args, **kwargs) if to else '')
def load_registered_fixtures(context):
"""
Apply fixtures that are registered with the @fixtures decorator.
"""
# -- SELECT STEP REGISTRY:
# HINT: Newer behave versions use runner.step_registry
# to be able to support multiple runners, each with its own step_registry.
runner = context._runner
step_registry = getattr(runner, 'step_registry', None)
if not step_registry:
# -- BACKWARD-COMPATIBLE: Use module_step_registry
step_registry = module_step_registry.registry
# -- SETUP SCENARIO FIXTURES:
for step in context.scenario.all_steps:
match = step_registry.find_match(step)
if match and hasattr(match.func, 'registered_fixtures'):
if not context.test.fixtures:
context.test.fixtures = []
context.test.fixtures.extend(match.func.registered_fixtures)
class BehaveHooksMixin:
"""
Provides methods that run during test execution.
These methods are attached to behave via monkey patching.
"""
testcase_class = None
def patch_context(self, context):
"""
Patches the context to add utility functions
Sets up the base_url, and the get_url() utility function.
"""
context.__class__ = PatchedContext
# Simply setting __class__ directly doesn't work
# because behave.runner.Context.__setattr__ is implemented wrongly.
object.__setattr__(context, '__class__', PatchedContext)
def setup_testclass(self, context):
"""
Adds the test instance to context
"""
context.test = self.testcase_class()
def setup_fixtures(self, context):
"""
Sets up fixtures
"""
if getattr(context, 'fixtures', None):
context.test.fixtures = copy(context.fixtures)
if getattr(context, 'reset_sequences', None):
context.test.reset_sequences = context.reset_sequences
if getattr(context, 'databases', None):
context.test.__class__.databases = context.databases
if hasattr(context, 'scenario'):
load_registered_fixtures(context)
def setup_test(self, context):
"""
Sets up the Django test
This method runs the code necessary to create the test database, start
the live server, etc.
"""
context.test._pre_setup(run=True)
context.test.setUpClass()
context.test()
def teardown_test(self, context):
"""
Tears down the Django test
"""
context.test.tearDownClass()
context.test._post_teardown(run=True)
del context.test
def monkey_patch_behave(django_test_runner):
"""
Integrate behave_django in behave via before/after scenario hooks
"""
behave_run_hook = ModelRunner.run_hook
def run_hook(self, name, context, *args):
if name == 'before_all':
django_test_runner.patch_context(context)
behave_run_hook(self, name, context, *args)
if name == 'before_scenario':
django_test_runner.setup_testclass(context)
django_test_runner.setup_fixtures(context)
django_test_runner.setup_test(context)
behave_run_hook(self, 'django_ready', context)
if name == 'after_scenario':
django_test_runner.teardown_test(context)
ModelRunner.run_hook = run_hook