2016-12-28 63 views
0

我是使用Ruby自动化测试的新手(与Selenium结合使用),并努力在我的test_steps.rb中使用常量的名称而不是它的值。Ruby:如何使用常量名称而不是它的值

我使用了3个文件如下:

LoginPage.rb

class LoginPage < Base 

    FIELDS = { 
    'Username' => '//form[@id="login"]//input[@name="j_username"]', 
    } 

Base.rb

def fill_field(field, value) 
    find(:xpath, field, wait: 15).set(value) 
    #logger("Filling field with xpath '" + field + "' with value '" + 
      value + "'.") > this works fine but prints the xpath 

    p "field: " + field 
    log = field.scan(/\w+(?:'\w+)*/).last 
    logger("Filling field '" + log + "' with value '" + value + "'.") 

test_steps.rb:

And(/^logs in as user "([^"]*)"$/) do |userName| 
    $login_name = search_excel('testdata/accounts.xlsx', userName, 1) 
    @pg.fill_field(LoginPage::FIELDS['Username'], $login_name) 

当execu婷场景我看到这在我的命令提示符:

Given a user is on the oCRM login page # features/step_definitions/test_steps.rb:13 
"field: //form[@id=\"login\"]//input[@name=\"j_username\"]" 
28/12/2016 13:03:50 Filling field 'j_username' with value 'D0X02703'. 

注意,在Base.rb打印为常量匹配“场”

'//form[@id="login"]//input[@name="j_username"]' 

我想它打印的常量本身的价值线:"LoginPage::FIELDS['Username']"。我们的目标是在我的日志记录,以打印:

"Filling field 'Username' with value 'DOX02703'." 

我试着打印"field.name""field.value"local_variables玩耍了,但还没有成功。帮助将非常欢迎!

也尝试了其他方式下面的定义,但ofcourse那么它不会拿起恒定值,并查找的XPath "LoginPage::FIELDS['Username']"

def fill_fields(page, type, field, value) 
      find(:xpath, page + "::" + type + "['" + field + "']", wait: 15).set(value) 
+0

我想,这可能会为你做它,假设你排除值印刷的一部分! http://stackoverflow.com/q/2603617/6090706 –

+0

感谢您的评论!我更喜欢不使用我不明白的代码(或者看起来过于复杂),所以我不会这样做。也许只需在日志中打印xpath即可:-) – Blapmeister

+0

最好不要使用你不明白的代码,但如果你试图理解它,你将会学到一些或未来的事情 –

回答

0

本质上说是叫

@pg.fill_field(LoginPage::FIELDS['Username'], $login_name) 

username = LoginPage::FIELDS['Username'] 
@pg.fill_field(username, $login_name) 

这只是第一个没有没有区别提到临时变量。无论哪种方式,传递给该方法的唯一东西是与哈希中的“用户名”键关联的值。看看你的类结构看起来好像你有许多从页面继承的'Page'类,并且你期望fill_field在继承它的类中使用FIELDS常量。在这种情况下,你可能想

def fill_field(field, value) 
    find(:xpath, self.class::FIELDS[field], wait: 15).set(value) 

    logger("Filling field '" + field + "' with value '" + value + "'.") 
end 

,把它作为

@pg.fill_field('Username', $login_name) 
+0

看起来不错,但恐怕这不适合我。起初我得到了这个消息,因为我们没有在基础中定义常量。rb:'未初始化的常量Base :: FIELDS(NameError)' 在base.rb中添加“FIELDS + {}”后,我得到'InvalidSelectorError:由于以下错误无法找到包含xpath表达式的元素。 (因为在base.rb中没有常量“用户名”) 这应该怎么知道Page类寻找常量?我是否需要在每个Page对象中使用def fill_field而不是在base.rb中? – Blapmeister

+0

@Blapmeister只要你在从Base派生的Page类的对象上调用fill_field,那么'self.class :: FIELDS'应该引用Page类中的FIELDS常量,因为那是实际的类对象,并且对常量的所有访问都需要采用'self.class :: FIELDS'形式。如果你在Base类的纯对象(不是从Base派生的类)上调用它,它将不起作用 –

+0

非常感谢Thomas!得到它的工作方式,请参阅下面的设置。现在唯一困扰我的是我必须在每个页面对象上放置def fill_field。以前页面对象不包含类,只包含常量。但是由于实际的功能仍然在base.rb中,我不认为这是一个问题。 – Blapmeister

1

常量不是Ruby对象。既然你只能传递对象作为参数,并且只能调用对象的方法(而对象是唯一的值,而方法调用是唯一的方法),所以传递一个常量作为参数或者询问它是不可能的为它的名字。

你唯一可以做的就是不断的通过名作为参数的代替或补充对象不断点。

+0

绝对常数是Ruby中的对象,只是用户已经在常量哈希上调用了'#[]'方法并且检索了给定键的值,所以没有对传递给该方法的常量的引用。 –

+0

常量是* not *对象。例如。请参阅ISO Ruby语言规范的第6.2.1节,它明确指出(** bold ** emphasis mine):“一个变量用名称表示,而**表示**一个对象,它被称为变量 **变量本身不是对象**。“或者,请参阅matz本人(** bold **强调我自己)合着的书“Ruby编程语言”:“每个**值**都是一个对象”。注意:它表示每个*值*,变量不是值。常量是各种变量。为什么'Module#constants'返回'Symbol'的'Array'而不是'Constants'的'Array'? –

+0

因为它不能!它不能返回'常量'数组,因为常量不是对象,数组必须包含对象。为什么'Module#const_get','Module#const_set','Module#const_defined?','Module#const_get','Module#deprecate_constant','Module#private_constant','Module#public_constant'和'Module#remove_const ',把表示常数名称的'Symbol'作为一个参数,而不是简单地直接表示常量?因为方法只能将对象作为参数,常量不是对象。我不知道为什么这是如此有争议。 *任何*主流主流语言的常量和变量不是对象 –

0

你可以使用与const_get的字符串:

class LoginPage # <Base 
    FIELDS = { 
    'Username' => '//form[@id="login"]//input[@name="j_username"]', 
    } 
end 

def get_constant_from_string(param) 
    puts "Parameter is #{param}" 
    Object.const_get(param) if param.is_a?(String) 
end 

get_constant_from_string(LoginPage::FIELDS) 
# Parameter is {"Username"=>"//form[@id=\"login\"]//input[@name=\"j_username\"]"} 
# method returns nil 

puts get_constant_from_string("LoginPage::FIELDS")['Username'] 
# Parameter is LoginPage::FIELDS 
# //form[@id="login"]//input[@name="j_username"] 
+0

我已经尝试过这一点,但无法使其工作。要设置参数,我将不得不连接值,导致它将查找xpath“LoginPage :: FIELDS ['Username']”而不是常量。我的Ruby体验(总体编程经验)很少,所以我可能会误解。 – Blapmeister

0

工作液根据托马斯·沃波尔的评论:

Base.rb

def find_field(field) 
    @fieldToFill = find(:xpath, self.class::FIELDS[field], wait: 15) 
end 

def set_value(value) 
    @fieldToFill.set(value) 
end 

def fill_field_log(field, value) 
    logger("Filling field '" + field + "' with value '" + value + "'.")   
end 

LoginPage.rb

def fill_field(field, value) 
    find_field(field) 
    set_value(value) 
    fill_field_log(field, value) 
end 

test_steps.rb

Given(/^a user is on the login page$/) do 
    @pg = Base.new 
    @lp = LoginPage.new 
    @pg.visit_loginpage 
end 

And(/^logs in as user "([^"]*)"$/) do |userName| 
    $login_name = search_excel('testdata/accounts.xlsx', userName, 1) 
    login_password = search_excel('testdata/accounts.xlsx', userName, 2) 

    @lp.fill_field('Username', $login_name) 
    @lp.fill_field('Password', login_password) 
相关问题