2014-05-18 38 views
6

使用伟大的Behave框架,但遇到我缺乏OOP技能的麻烦。将常见属性添加到Behave方法

行为具有内置的上下文命名空间,其中可以在测试执行步骤之间共享对象。在初始化我的WebDriver会话之后,我一直使用这个context来保存所有内容。功能很好,但正如你可以在下面看到的,它是干的。

如何/在哪里可以将这些属性添加到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/") 
+1

就是如何避免一切从'拆包的问题每个'step_impl'函数中的上下文吗?我想说,你可以通过跳过稍后不打算使用的项目(例如,上个版本中的'xenv','wait'和'expected_conditions')来删除一堆。除此之外,您可以跳过一些拆包,并直接使用上下文的属性,例如'context.driver.get(无论)'。我对Behave一无所知,所以我不确定这是否是一个答案。 – Blckknght

+0

谢谢。是的,为了避免所有的拆包*和*每次都通过调用'context.attribute.something'来避免重复,这两者都没有感觉到Pythonic –

回答

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()来破解。例如箱子的功能类似:

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') 

这将减少重复在你的代码,但它是非常隐含,可能是危险的。所以不建议这样做。

我只是使用tuple解包。它很简单明确,所以不会引起额外的错误。

+0

谢谢,希望能够使用tuple解包,但在这种情况下收到:'return [ getattr(上下文,字段)上下文中的字段] TypeError:'上下文'对象不可迭代' –

+1

是的,对不起。我编辑了答案。它必须是'field_list',而不是'context' –

+0

请注意,在最近的Python版本中,你不能(有用地)分配给'locals()'的返回值。 'locals()'返回的字典在你调用它时是局部变量的副本,但你所做的改变不会反映在实际的本地名字空间中。 – Blckknght

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" 

步骤。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 
1

坚持到干燥的原则,我通常使用:
*背景故事:http://pythonhosted.org/behave/gherkin.html#background
*或环境控制:http://pythonhosted.org/behave/tutorial.html#environmental-controls

+0

下面是一个示例功能文件[twilio_handler.feature](https://github.com/kowalcj0/flaskrilio/blob/master/flaskrilio/features/twilio_handler.feature)与背景故事和这里:[twilio_handler_steps.py](https ://github.com/kowalcj0/flaskrilio/blob/master/flaskrilio/features/steps/twilio_handler_steps.py)是其执行步骤。 – kowalcj0