重构大量黄瓜步骤定义

时间:2014-06-03 18:52:35

标签: webdriver refactoring cucumber jruby acceptance-testing

我的团队目前正在使用旧的UI验收测试脚本并自动化它们。为此,我们使用Jruby,Cucumber和Watir-Webdriver。到目前为止,自动化过程一直进展顺利。我们遇到的唯一问题是我们的步骤定义开始变得有点失控。

例如,在我们的大多数情况下都是这样的部分:

Given I press the SEARCH_BUTTON
Then I should land on the SEARCH_PAGE

,步骤定义如下所示:

Given(/I press the (.*)$/) do |buttonName|
  if buttonName == 'SEARCH_BUTTON'
      eval "$browser.#{$DataHash['home']['searchButton']}.when_present.click"
  elsif buttonName == 'LOGIN_BUTTON'
      eval "$b.#{$DataHash['loginPage']['loginButton']}.click"
  elsif buttonName == 'HOME_BUTTON'
     eval "$b.#{$DataHash['mainPage']['HomeButton']}.click"
  elsif buttonName == 'ADD_PRODUCT_BUTTON'
      #This if else ladder goes on like this for another 300+ lines
  ...
  end
end

$DataHash变量引用config.yml,它使用哈希来存储我们正在使用的所有不同的网络元素。

config.yml

home:
  searchButton: "link(:id => 'searchBtn')"
  searchTypeSelectBox: "select_list(:name => 'matchType')"
  searchResetButton: "button(:id => 'resetSearch')"
  #rest of the elements on the home page...

loginPage:
  loginButton: "link(:id => 'login')"
  #rest of the elements on the login page...

....

因此$browser.$DataHash['home']['searchButton'].when_present.click相当于$browser.link(:id => 'searchBtn').when_present.click

我们正在使用每个按钮的基本步骤定义,用户可以单击该按钮,此时此一步定义类似于300多行代码。大多数都是如上所述的单行。我们的其他步骤定义也存在同样的问题。是否有任何好的方法可以重构我们的步骤定义,使其不那么臃肿,或者至少更容易搜索,而不会使实际步骤不再可用?

最初我们认为我们可以根据正在测试的页面在多个文件中使用相同的步骤定义。因此,在searchDefinitions.rb中,Given(/I press the (.*)$/) do |buttonName|会有一个步骤定义,只有在搜索页面上找到不同的按钮。然后在homeDefinitions.rb中将是相同的步骤定义,但仅限于主页按钮的代码。基本上在多个文件中分解if-else梯形图。当然,Cucumber不允许在多个文件中使用相同的步骤定义,所以现在我们有点不知所措。

2 个答案:

答案 0 :(得分:1)

正如您所提到的,您可以重复使用步骤,请参阅Reuse Cucumber steps。但是当我尝试这样做时,我个人发现它非常复杂。所以,在我身边,我建议你实现Page Object模式。这个想法是你描述你的页面甚至是一些模块,比如单独的实体,它们提供了与它们交互的能力。有关理解概念,请参阅herehere你可以找到一些例子。假设你的步骤定义是

Given(/I press the (.*)$/) do |buttonName|
  @my_home_page.click_search_button
    ...
  end
end

click_search_button方法封装了您的'梯子'如果搜索按钮尚不存在,则按下登录按钮的逻辑。

希望这对你有意义。

答案 1 :(得分:0)

假设您显示的eval行中的细微差别无关紧要,请提取变为常量的哈希值

BUTTON_KEYS = {
  'search' => %w(home searchButton),
  'login' => %w(loginPage loginButton)
  # ...
}

并在步骤定义中使用它:

Given(/I press the (.*) button$/) do |button_name|
  keys = BUTTON_KEYS['button_name']
  eval "$browser.#{$DataHash['#{keys[0]}']['#{keys[1]}']}.when_present.click"
end

现在你有一半的代码行和更少的重复。

我将步骤正则表达式更改为包含“按钮”,从按钮名称中删除该复制,并将按钮名称改为小写,如普通英语。无论您是否向非程序员展示您的要素文件,Cucumber步骤名称应该像自然语言一样阅读,以便您在阅读时可以考虑产品要求而不是实施细节。

替代建议,如果不真正需要YAML中的两个关键级别,则有效:

您可以像这样重组YAML

search button: "link(:id => 'searchBtn')"
search type select box: "select_list(:name => 'matchType')"
search reset button: "button(:id => 'resetSearch')"
# rest of the elements on the home page...

login button: "link(:id => 'login')"
# rest of the elements on the login page...

# ...

然后你根本不需要哈希,你的步骤可能只是

Given(/I press the (.*)$/) do |element_name|
  eval "$browser.#{$DataHash['#{element_name}']}.when_present.click"
end

或者您可以将YAML完全转换为哈希(将该方法表示为字符串并使用.send调用它),这可以防止您出现语法错误。