为什么在此RSpec脚本中未正确传递对象引用?

时间:2012-12-30 21:45:26

标签: 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

后一种情况的问题是,在与“it”方法关联的代码块中,网站被评估为nil。 但是当我这样做时:

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

零问题已经消失但测试失败的原因是“浏览器已关闭” 显然我缺少一些非常基本的Ruby知识 - 因为浏览器引用在修改后的脚本中无法正常工作。我哪里做错了?应该采用什么重构来完成这项工作? 谢谢你的帮助!

2 个答案:

答案 0 :(得分:0)

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

看看这是否有所作为:

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

答案 1 :(得分:0)

了解RSpec与许多ruby程序一样,有两个运行时阶段非常重要:

  1. 在第一阶段,RSpec加载每个spec文件,并执行每个describecontext块。在此阶段,代码的执行定义了您的示例,钩子等。但是您的示例和挂钩在此阶段不会执行。
  2. 一旦RSpec完成加载spec文件(并且所有示例都已定义),它就会执行它们。
  3. 所以...将你的例子简化为一个更简单的形式,这里有你所拥有的:

    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. (稍后,在定义了所有示例之后......)示例运行
    5. 正如O.Powell的回答所示,您可以在after(:all)挂钩中关闭浏览器以延迟关闭,直到此示例组中的所有示例都运行完毕。也就是说,我问你是否真的需要在示例定义时间使用浏览器实例。通常情况下,当示例在运行时需要它们时,懒得创建资源(例如浏览器实例),而不是在示例定义阶段。