【问题标题】:How to test a ruby application which uses mechanize如何测试使用 mechanize 的 ruby​​ 应用程序
【发布时间】:2011-01-10 05:52:06
【问题描述】:

我写了一个小程序,使用 Mechanize 来遍历一个站点。

我想为它编写测试,但不希望它在每次运行测试时都登录网站。我想模拟互联网,这样当它访问某个站点时,它只会返回存储的结果。

这是一个小例子,假设我的代码的目的是从谷歌主页中提取链接,所以我编写了一个测试来确保我的代码找到的第一个链接包含文本“图片”。我可能会这样写:

require 'rubygems'
require 'mechanize'
require 'test/unit'

def my_code_to_find_links
  google = WWW::Mechanize.new.get('http://www.google.com')
  # ...
  # some code to figure out which links it wants
  # ...
  google.links
end

class TestGoogle < Test::Unit::TestCase
  def test_first_link_is_images
    assert_equal 'Images' , my_code_to_find_links.first.text
  end
end

如何模拟 google.com 以便我可以测试 my_code_to_find_links 而无需实际上访问互联网的所有开销?

谢谢 -乔什

【问题讨论】:

    标签: ruby testing mocking mechanize


    【解决方案1】:

    使用 Fakeweb 删除互联网响应。

    对于 Google 示例,首先访问网站并保存所需页面的 html。在这种情况下,假设您通过浏览器或 curl 保存了 www.google.com。将 Fakeweb gem 添加到您的 test.rb 文件中

    那么你的代码是

    stream = File.read("saved_google_page.html")
    FakeWeb.register_uri(:get, 
        "http://www.google.com", 
        :body => stream, 
        :content_type => "text/html")
    

    当您执行标准的机械化调用时

    agent = Mechanize.New
    page = agent.get("http://www.google.com/")
    

    Fakeweb 将返回您保存的带有 content_type 标头设置的页面,Mechanize 会认为它已成功访问互联网。确保设置了 content_type 标头,否则 Mechanize 会将响应视为 Mechanize::File 而不是 Mechanize::Page。您可以通过在拔下网络连接的机器上运行测试来测试它是否完全正常工作。

    附言我在问这个问题 6 个月后回答这个问题,因为这是谷歌的最高结果,但没有得到回答。我自己花了 30 分钟来解决这个问题,并认为我会分享解决方案。

    【讨论】:

    【解决方案2】:

    如果您正在编写单元测试,那么您正在寻找错误的一端,您不需要模拟 google.com,但您应该模拟/存根 Mechanize 对象,即。创建一个机械化对象,在带有参数http://www.google.com的对象上调用get方法。是的,您确实需要通过访问页面来测试您正在对结果执行的操作,您可以通过存根响应轻松完成该页面,然后进行所有测试。例如,如果您使用的是 mocha,那么

    mechanize = stub('WWW::Mechanize')
    WWW::Mechanize.stubs(:new).returns(mechanize)
    mechanize.stubs(:get).with('http://www.google.com').returns('What ever out put you are expecting so that you can test')
    

    我认为您真的不需要测试您的请求是否发送到 google.com,因为这已经在 Mechanize gem 中进行了测试。

    另一方面,如果您正在进行集成/黄瓜测试,那么您可以使用 sinatra 来伪造网站。 Sinatra 使编写单页脚本并将该脚本作为网站运行变得非常容易。

    编辑:

    如果您不使用 mocha,则需要安装它并在测试中使用它

    sudo gem install mocha
    

    在你的测试中

    require 'rubygems'
    require 'mocha'
    

    【讨论】:

    • 老实说,我认为这是见仁见智的问题。鉴于结果对象的复杂性,与 FakeWeb 之类的东西相比,Stubbing Mechanize 将是一个痛苦的过程。您很可能最终会遇到非常脆弱/高度维护的测试,这些测试与确切的实现高度相关,只需将其剔除即可。虽然我通常同意您不应该测试外部依赖项——我认为这是该规则的一个例外。
    【解决方案3】:

    如果您正在编写功能测试并且服务器不需要花哨的东西,您可以编写一个仅用于测试的小型 HTTP 服务器;测试代码将被测代码配置为联系 localhost: 上的小型 HTTP 服务器。

    我推荐WEBrick。搭建一个 HTTP 服务器是一件轻而易举的事。

    【讨论】:

      【解决方案4】:

      您也可以使用 Mechanize 的测试助手。一旦 Mechanize::TestCase 被加载,将不会在 mechanize 本身之外发出任何 HTTP 请求。所有请求都通过WEBrick servlet 处理。

      创建一个夹具,要求测试用例,然后存根/模拟您的请求以返回:

      require 'mechanize/test_case'
      
      ...
      
      Mechanize::TestCase.new('http://google.com').html_page(html_fixture)
      

      更多选项 见:https://www.rubydoc.info/gems/mechanize/Mechanize/TestCase

      【讨论】:

        猜你喜欢
        • 2011-02-21
        • 2018-02-21
        • 1970-01-01
        • 2011-04-05
        • 2013-07-04
        • 1970-01-01
        • 2013-07-21
        • 1970-01-01
        • 2020-04-20
        相关资源
        最近更新 更多