2014-05-18 69 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