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

Undefined method error for a class when used with class variables

我正在使用 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

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

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

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

通常,当您调用 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")

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

此外,在测试中使用class变量共享数据可能容易出错。一个测试的状态可能会影响另一个测试的结果,使得测试不是孤立的。

您可以将其重写为

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

使用现有的测试框架可能会更好,例如minitest, rspec