与类变量一起使用时,类的未定义方法错误

时间:2015-07-25 07:37:48

标签: ruby watir watir-webdriver

我正在使用ruby和watir测试应用程序。我有一个带有此代码的文件init.rb

 class Init_Test
   def initialize
     @browser = Watir::Browser.new :firefox
   end 

   def login_with_creds username,password
     @browser.goto 'https://54.69.254.137/webui#/landing'
     sleep(2)
     @browser.driver.manage.window.maximize
     @browser.button(:class => 'sign-in md-button md-default-
     theme').when_present.click
     sleep(2)
     @browser.text_field(:id =>'input_001').set(username)
     sleep(2)
     @browser.text_field(:id =>'input_002').set(password)
     sleep(2)
     @browser.button(:class =>'md-primary md-raised md-button md-default-theme').click
     sleep(2)
     return @browser
   end
 end

我将此文件继承到名为ann.rb

的文件中
require "watir"
require "watir-webdriver"
require_relative 'init'
class Post < Init_Test
  @@b = login_with_creds("abcadmin@example.com","password")

  def test_discuss
    @@b.input(:id =>'input_002').when_present.click
    sleep(1)
    @@b.element(aria_label:'What do you want to do?').when_present.click
    sleep(1)
    @@b.element(:id =>'select_option_00G').when_present.click
    sleep(1)
    @@b.element(aria_label:'About what?').when_present.click
    sleep(1)
    @@b.element(:id =>'select_option_00P').when_present.click
    sleep(1)
    @@b.textarea(:id =>'input_00N').when_present.set('Discuss about java script and later test the    application??')
    sleep(1)
    @@b.span(:text, 'Submit').when_present.click
    sleep(1)
  end

  def test_question
    @@b.input(:id =>'input_002').when_present.click
    sleep(1)
    @@b.element(aria_label:'What do you want to do?').when_present.click
    sleep(2)
    @@b.element(:id =>'select_option_014').when_present.click
    sleep(2)
    @@b.element(:id =>'select_017').when_present.click
    sleep(1)
    @@b.element(:id =>'select_option_01D').when_present.click
    sleep(1)
    @@b.textarea(:class =>'ng-pristine md-input ng-invalid ng-invalid-
    required ng-touched').when_present.set('test question')
    sleep(1)
    @@b.span(:text, 'Submit').when_present.click
  end
end

a = Post.new
a.test_discuss
a.test_question

如您所见,我使用了类变量@@b并为其分配了方法log_in_creds,然后使用类变量执行其他活动。但是,当我运行它时,它不会引发log_In_creds

的方法错误
a.rb:6:in `<class:Post>': undefined method `login_with_creds' for 
Post:Class (NoMethodError)
from a.rb:4:in `<main>'

为什么它会为类变量抛出错误。我需要使用浏览器对象调用每个方法,因为我只想初始化浏览器一次并稍后执行所需的操作。

1 个答案:

答案 0 :(得分:0)

通常,当您在没有显式接收器的情况下调用Ruby方法(methodA)时,它与调用self.methodA相同。根据代码的位置,对象self可能会更改。

class Init_Test
  # self refers to Init_Test, a class object
  def login_with_creds username,password # define a method for the instances of Init_Test
    # self refers to an instance of Init_Test
  end
end

现在,在Post

class Post < Init_Test
  @@b = login_with_creds("abcadmin@example.com","password")

它会尝试使用login_with_creds调用self来引用Post,这是一个类(单例)对象。但是,login_with_creds被定义为Init_Test的所有实例的实例方法,由于继承,可以在Post类的所有实例上调用它。它不适用于Post对象或Init_Test对象。

此外,在测试中使用类变量来共享数据可能容易出错。一次测试的状态可能会影响另一次测试的结果,这使得测试不会被隔离。

您可以将其重写为

class Post < Init_Test
  def initialize
    super
    @b = login_with_creds("abcadmin@example.com","password")
  end

  def test_discuss
    @b.input(:id =>'input_002').when_present.click
    sleep(1)
    ...
  end

  def test_question
    @b.input(:id =>'input_002').when_present.click
    sleep(1)
    ...
  end
end

a = Post.new
a.test_discuss
a = Post.new # ensure clean state
a.test_question

最好使用现有的测试框架,例如minitestrspec等。