使用伟大的Behave框架,但我缺乏OOP技能。
Behave有一个内置的上下文命名空间,可以在测试执行步骤之间共享对象。初始化我的WebDriver会话后,我会继续使用此context
在我的步骤之间传递它以保存所有内容。功能很好,但正如你在下面看到的那样,除了DRY之外什么都不是。
我如何/在何处将这些属性仅添加到step_impl()
或context
一次?
environment.py
from selenium import webdriver
def before_feature(context, scenario):
"""Initialize WebDriver instance"""
driver = webdriver.PhantomJS(service_args=service_args, desired_capabilities=dcap)
"""
Do my login thing..
"""
context.driver = driver
context.wait = wait
context.expected_conditions = expected_conditions
context.xenv = env_data
steps.py
@given('that I have opened the blah page')
def step_impl(context):
driver = context.driver
wait = context.wait
expected_conditions = context.expected_conditions
xenv = context.xenv
driver.get("http://domain.com")
driver.find_element_by_link_text("blah").click()
wait.until(expected_conditions.title_contains("Blah page"))
@given(u'am on the yada subpage')
def step_impl(context):
driver = context.driver
wait = context.wait
expected_conditions = context.expected_conditions
xenv = context.xenv
if driver.title is not "MySubPage/":
driver.get("http://domain.MySubPage/")
wait.until(expected_conditions.title_contains("Blah | SubPage"))
@given(u'that I have gone to another page')
def step_impl(context):
driver = context.driver
wait = context.wait
expected_conditions = context.expected_conditions
xenv = context.xenv
driver.get("http://domain.com/MyOtherPahge/")
答案 0 :(得分:6)
首先,您可以跳过此解包并在任何地方使用context
属性,例如context.driver.get("http://domain.com")
如果你不喜欢它并且你真的想拥有局部变量,你可以使用元组解包来使代码更好:
import operator
def example_step(context):
driver, xenv = operator.attrgetter('driver', 'xenv')(context)
你可以将这类属性的默认列表分解出来,但这会让整个事情变得有点暗示:
import operator
def unpack(context, field_list=('driver', 'xenv')):
return operator.attrgetter(*field_list)(context)
def example_step(context):
driver, xenv = unpack(context)
如果您仍然不喜欢,可以使用globals()
进行修改。比如crate这样的函数:
def unpack(context, loc, field_list):
for field in field_list:
loc[field] = getattr(context, field, None)
在你的步骤中使用它:
def example_step(context):
unpack(context, globals(), ('driver', 'xenv'))
# now you can use driver and xenv local variables
driver.get('http://domain.com')
这会减少代码中的重复次数,但是非常隐式,可能会很危险。因此不建议这样做。
我只是使用元组拆包。它简单明了,不会造成其他错误。
答案 1 :(得分:2)
您可以定义一个“解包”'为您提供的背景信息,并通过了“解压缩”的信息。值作为参数:
<强> environment.py 强>
def before_feature(context, feature):
context.spam = 'spam'
def after_feature(context, feature):
del context.spam
<强> test.feature 强>
Scenario: Test global env
Then spam should be "spam"
<强> step.py 强>
def add_context_attrs(func):
@functools.wraps(func) # wrap it neatly
def wrapper(context, *args, **kwargs): # accept arbitrary args/kwargs
kwargs['spam'] = context.spam # unpack 'spam' and add it to the kwargs
return func(context, *args, **kwargs) # call the wrapped function
return wrapper
@step('spam should be "{val}"')
@add_context_attrs
def assert_spam(context, val, spam):
assert spam == val
答案 2 :(得分:1)