【问题标题】:Using Watir to check for bad links使用 Watir 检查坏链接
【发布时间】:2012-07-07 19:23:35
【问题描述】:

我有一个无序列表的链接,我保存在一边,我想点击每个链接并确保它进入一个真实的页面,而不是 404、500 等。

问题是我不知道该怎么做。是否有一些我可以检查的对象会给我 http 状态代码或任何东西?

mylinks = Browser.ul(:id, 'my_ul_id').links

mylinks.each do |link|
  link.click

  # need to check for a 200 status or something here! how?

  Browser.back
end

【问题讨论】:

标签: ruby watir


【解决方案1】:

我的回答与铁皮人的想法相似。

需要'net/http' 需要'uri' mylinks = Browser.ul(:id, 'my_ul_id').links mylinks.each 做 |link| u = URI.parse 链接.href status_code = Net::HTTP.start(u.host,u.port){|http| http.head(u.request_uri).code } # 使用 rspec 进行测试 status_code.should == '200' 结尾

如果你使用 Test::Unit 来测试框架,你可以像下面这样测试,我想

assert_equal '200',status_code

另一个示例(包括 Chuck van der Linden 的想法):检查状态代码并在状态不好时注销 URL。

需要'net/http' 需要'uri' mylinks = Browser.ul(:id, 'my_ul_id').links mylinks.each 做 |link| u = URI.parse 链接.href status_code = Net::HTTP.start(u.host,u.port){|http| http.head(u.request_uri).code } 除非 status_code == '200' File.open('error_log.txt','a+'){|file| file.puts "#{link.href} is #{status_code}" } 结尾 结尾

【讨论】:

  • 就我个人而言,我认为检查有限数量的“ok”返回码之一(可能只有 200 个)比查看它不等于潜在大数据中的一小部分要好一组“错误”代码。例如,您是否将 401 视为通过? 410呢?如果是我,我会在 200 上传递它,如果返回码是其他任何东西,请将其(和 URL)吐出到某种可以由人类查看的错误日志文件中。
  • @chuck-van-der-linden 我编辑了我的答案,包括你的建议:)
【解决方案2】:

没有必要为此使用 Watir。 HTTP HEAD 请求将让您了解 URL 是否解析并且会更快。

Ruby 的Net::HTTP 可以,也可以使用Open::URI

使用 Open::URI 可以请求一个 URI,然后返回一个页面。因为你并不真正关心页面包含什么,所以你可以扔掉那部分,只返回是否有东西:

require 'open-uri'

if (open('http://www.example.com').read.any?)
  puts "is"
else
  puts "isn't"
end

好处是 Open::URI 可以解析 HTTP 重定向。缺点是它会返回整页,因此速度会很慢。

Ruby 的 Net::HTTP 可以提供一些帮助,因为它可以使用 HTTP HEAD 请求,它不会返回整个页面,只返回一个标题。这本身不足以知道实际页面是否可访问,因为 HEAD 响应可能会重定向到无法解析的页面,因此您必须遍历重定向,直到您 获得重定向,否则您会收到错误消息。 Net::HTTP 文档有一个 example 来帮助您入门:

require 'net/http'
require 'uri'

def fetch(uri_str, limit = 10)
  # You should choose better exception.
  raise ArgumentError, 'HTTP redirect too deep' if limit == 0

  response = Net::HTTP.get_response(URI.parse(uri_str))
  case response
  when Net::HTTPSuccess     then response
  when Net::HTTPRedirection then fetch(response['location'], limit - 1)
  else
    response.error!
  end
end

print fetch('http://www.ruby-lang.org')

同样,该示例正在返回页面,这可能会减慢您的速度。您可以将get_response 替换为request_head,它会返回类似get_response 的响应,这应该会有所帮助。

在任何一种情况下,您都必须考虑另一件事。许多网站使用“meta refreshes”,这会导致浏览器在解析页面后使用备用 URL 刷新页面。处理这些需要请求页面并对其进行解析,寻找<meta http-equiv="refresh" content="5" /> 标签。

TyphoeusPatron 等其他 HTTP gem 也可以轻松执行 HEAD 请求,因此也可以看看它们。特别是,Typhoeus 可以通过其伙伴Hydra 处理一些繁重的负载,让您轻松使用并行请求。


编辑:

require 'typhoeus'

response = Typhoeus::Request.head("http://www.example.com")
response.code # => 302

case response.code
when (200 .. 299)
  #
when (300 .. 399)
  headers = Hash[*response.headers.split(/[\r\n]+/).map{ |h| h.split(' ', 2) }.flatten]
  puts "Redirected to: #{ headers['Location:'] }"
when (400 .. 499)
  #
when (500 .. 599) 
  #
end
# >> Redirected to: http://www.iana.org/domains/example/

以防万一您还没有玩过,下面是响应的样子。它对您正在查看的那种情况很有用:

(rdb:1) pp response
#<Typhoeus::Response:0x00000100ac3f68
 @app_connect_time=0.0,
 @body="",
 @code=302,
 @connect_time=0.055054,
 @curl_error_message="No error",
 @curl_return_code=0,
 @effective_url="http://www.example.com",
 @headers=
  "HTTP/1.0 302 Found\r\nLocation: http://www.iana.org/domains/example/\r\nServer: BigIP\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n",
 @http_version=nil,
 @mock=false,
 @name_lookup_time=0.001436,
 @pretransfer_time=0.055058,
 @request=
  :method => :head,
    :url => http://www.example.com,
    :headers => {"User-Agent"=>"Typhoeus - http://github.com/dbalatero/typhoeus/tree/master"},
 @requested_http_method=nil,
 @requested_url=nil,
 @start_time=nil,
 @start_transfer_time=0.109741,
 @status_message=nil,
 @time=0.109822>

如果您有很多 URL 需要检查,请查看属于 Typhoeus 的 Hydra example

【讨论】:

  • 感谢详细的回复!这并不是说我试图使用 Watir 来解决这个特定的问题。它更像是我们使用 Watir 测试框架进行前端测试,我们想要测试的一件事是这个动态生成的链接列表转到了真实的端点。 ..所以我想我可以在 Watir 测试框架内 Open::URI ..
  • 你应该能够,因为 Watir 都是在 Ruby 中完成的,任何运行 watir 代码的东西通常都无法区分通用 ruby​​、Watir 库中的方法和类之间的区别,或者来自其他一些图书馆
【解决方案3】:

关于 watir 或 watir-webdriver 是否应该提供 HTTP 返回代码信息存在一些哲学争论。前提是 Watir 在 DOM 上模拟的普通“用户”不知道 HTTP 返回码。我不一定同意这一点,因为我的用例可能与主要的(性能测试等)略有不同......但它就是这样。这个帖子表达了一些关于区别的意见=> http://groups.google.com/group/watir-general/browse_thread/thread/26486904e89340b7

目前,如果不使用代理/Fiddler/HTTPWatch/TCPdump 等补充工具,或者降级到脚本中间测试的 net/http 级别...我个人喜欢使用 firebug netexport 插件,用于回顾测试。

【讨论】:

  • 其中一件事是我不一定需要状态码..我只需要验证这些动态生成的链接是否到达真实端点,或者端点没有出错等。我认为状态码很容易检查
  • 除非您知道每个链接的端点会发生什么,并且想要编写基于 watir 的特定测试脚本以在页面上查找该特定内容,否则我不得不说,为了您的目的,仅查看结果代码将是进行简单链接检查的方法。
【解决方案4】:

如果您有大量链接,所有以前的解决方案都效率低下,因为对于每个链接,它都会与托管该链接的服务器建立一个新的 HTTP 连接。

我编写了一个单行 bash 命令,它将使用 curl 命令获取从标准输入提供的链接列表,并返回与每个链接对应的状态代码列表。这里的关键点是 curl 在同一次调用中获取所有链接,它将重用 HTTP 连接,这将显着提高速度。

但是,curl 会将列表分成 256 个块,这仍然远远大于 1!为确保重复使用连接,请先对链接进行排序(只需使用 sort 命令)。

cat <YOUR_LINKS_FILE_ONE_PER_LINE> | xargs curl --head --location -w '---HTTP_STATUS_CODE:%{http_code}\n\n' -s --retry 10 --globoff | grep HTTP_STATUS_CODE | cut -d: -f2 > <RESULTS_FILE>

值得注意的是,上面的命令会跟随 HTTP 重定向,对临时错误(超时或 5xx)重试 10 次,当然只会获取 headers。

更新:添加了 --globoff 以便 curl 在包含 {} 或 [] 时不会扩展任何 url

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2010-12-08
    • 2011-07-04
    • 1970-01-01
    相关资源
    最近更新 更多