我已经为此苦恼了大约三天了。我创建了一个类来模拟 html 页面并告诉黄瓜步骤定义在哪里填充表单数据:
class FlightSearchPage
def initialize(browser, page, brand)
@browser = browser
@start_url = page
#Get reference to config file
config_file = File.join(File.dirname(__FILE__), '..', 'config', 'site_config.yml')
#Store hash of config values in local variable
config = YAML.load_file config_file
@brand = brand #brand is specified by the customer in the features file
#Define instance variables from the hash keys
config.each do |k,v|
instance_variable_set("@#{k}",v)
end
end
def method_missing(sym, *args, &block)
@browser.send sym, *args, &block
end
def page_title
#Returns contents of <title> tag in current page.
@browser.title
end
def visit
@browser.goto(@start_url)
end
def set_origin(origin)
self.text_field(@route[:attribute] => @route[:origin]).set origin
end
def set_destination(destination)
self.text_field(@route[:attribute] => @route[:destination]).set destination
end
def set_departure_date(outbound)
self.text_field(@route[:attribute] => @date[:outgoing_date]).set outbound
end
# [...snip]
end
如您所见,我使用 instance_variable_set 来创建动态保存引用的变量,并且变量名称和值由配置文件提供(该配置文件旨在由不一定熟悉的人编辑红宝石)。
不幸的是,这是一个大而多毛的类,每次我想添加一个新字段时,我都必须编辑源代码,这显然是糟糕的设计,所以我一直在尝试更进一步并创建使用 define_method 动态设置变量名称的方法,这就是过去几个晚上让我一直睡到凌晨 4 点的原因。
这就是我所做的:
require File.expand_path(File.dirname(__FILE__) + '/flight_search_page')
class SetFieldsByType < FlightSearchPage
def text_field(config_hash)
define_method(config_hash) do |data|
self.text_field(config_hash[:attribute] => config_hash[:origin]).set data
end
end
end
这个想法是,添加新字段所需要做的就是向 YAML 文件添加一个新条目,并且 define_method 将创建允许 cucumber 填充它的方法。
目前,我遇到了范围问题——Ruby 认为 define_method 是@browser 的成员。但我想知道的是:这是否可行?我完全误解了define_method吗?