为什么在这个RSpec脚本中没有正确传递对象引用

  • 本文关键字:对象引用 脚本 RSpec ruby rspec
  • 更新时间 :
  • 英文 :


我不得不说我对Ruby和RSpec都是新手。无论如何,我完成了一个RSpec脚本,但重构后失败了。以下是原始工作版本:

describe Site do
  browser = Watir::Browser.new :ie
  site    = Site.new(browser, "http://localhost:8080/site")
  it "can navigate to any page at the site" do
    site.pages_names.each do |page_name|
      site.goto(page_name)
      site.actual_page.name.should eq page_name
    end
  end
  browser.close
end

,这里是修改后的版本-我想报告在测试期间访问的所有页面:

describe Site do
  browser = Watir::Browser.new :ie
  site    = Site.new(browser, "http://localhost:8080/site")
  site.pages_names.each do |page_name|
    it "can navigate to #{page_name}" do
      site.goto(page_name)
      site.actual_page.name.should eq page_name
    end
  end
  browser.close
end

后一种情况下的问题是,site在与'it'方法相关的代码块中被评估为nil。但是当我这样做的时候:

...
s = site
it "can navigate to #{page_name}" do
  s.goto(page_name)
  s.actual_page.name.should eq page_name
end
...

nil问题已经解决,但测试失败的原因是"浏览器已关闭"显然,我错过了一些非常基本的Ruby知识-因为浏览器引用在修改后的脚本中不能正常工作。我哪里做错了?应该应用什么样的重构来完成这项工作?谢谢你的帮助!

重要的是要理解RSpec,像许多ruby程序一样,有两个运行时阶段:

    在第一阶段,RSpec加载每个规范文件,并执行每个describecontext块。在这个阶段,代码的执行定义了示例、钩子等。但是你的例子和钩子不会在这个阶段执行。
  1. 一旦RSpec加载完spec文件(所有的例子都定义好了),它就会执行它们。

所以…将您的示例简化为更简单的形式,下面是您得到的:

describe Site do
  browser = Watir::Browser.new :ie
  it 'does something with the browser' do
    # do something with the browser
  end
  browser.close
end

虽然从视觉上看,它看起来像浏览器实例被实例化,然后在示例中使用,然后关闭,但实际情况是这样的:

  1. 浏览器实例被实例化
  2. 示例已定义(但未运行)
  3. 浏览器已关闭
  4. (稍后,在定义了所有示例之后…)示例如下:运行

正如O.Powell的回答所示,您可以在after(:all)钩子中关闭浏览器以延迟关闭,直到本示例组中的所有示例都运行之后。也就是说,我怀疑在定义示例时是否真的需要浏览器实例。一般来说,最好在示例运行时需要资源时惰性地创建资源(例如浏览器实例),而不是在示例定义阶段。

我在Site和Watir中使用假类复制了上面的代码。它工作得很好。因此,我唯一的结论是,问题一定在于上述两类中的任何一类。我注意到站点实例只需要访问您的第一个工作版本中的一个页面,但必须访问非工作版本中的多个页面。这里可能存在一个涉及实例内部发生的突变的问题。

看看这是否有区别:

describe Site do
    uri = "http://localhost:8080/site" 
    browser = Watir::Browser.new :ie 
    page_names = Site.new(browser, uri).page_names 
    before(:each) { @site = Site.new(browser, uri) }
    after(:all) { browser.close }
    pages_names.each do |page_name|
      it "can navigate to #{page_name}" do
        @site.goto(page_name)
        @site.actual_page.name.should eq page_name
      end
    end  
  end

相关内容

最新更新