我有一个 Sinatra 应用程序,其中包含以下调用;
get '/test' do
@res = Net::HTTP.get_response(URI('http://www.iana.org/domains/reserved'))
erb :test
end
有景观;
<%= @res.body %>
我正在使用 Capybara + Selenium + VCR 测试此调用,它不会创建磁带。测试通过了,但由于 VCR 未正确录制,我没有获得速度优势。
#!/usr/bin/env ruby
require 'test/unit'
require 'capybara'
require 'capybara/dsl'
require 'webdrivers/chromedriver'
require 'webmock'
require 'vcr'
require 'dotenv'
require_relative "../sinatra_app.rb"
class SinatraAppTest < Test::Unit::TestCase
include Capybara::DSL
def setup
Dotenv.load "#{__dir__}/../.env"
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome, options: chrome_options)
end
Capybara.default_driver = :chrome
Capybara.default_max_wait_time = 20
Capybara.app_host = "http://localhost:9393"
VCR.configure do |config|
config.cassette_library_dir = "fixtures/vcr_cassettes2"
config.hook_into :webmock
config.allow_http_connections_when_no_cassette = true
config.default_cassette_options = {re_record_interval: (3600 * (24 * 30))}
config.ignore_localhost = true
end
end
# Settings and profile for the Chrome Browser
# NOTE: still cannot get headless working
def chrome_options
opts = Selenium::WebDriver::Chrome::Options.new
# opts.add_argument('--headless') unless ENV['UI']
opts.add_argument('--no-sandbox')
opts.add_argument('--disable-gpu')
opts.add_argument('--disable-dev-shm-usage')
opts.add_argument('--window-size=1920,1080')
opts
end
def test_iana
VCR.use_cassette("iana") do
visit "/test"
assert page.has_content?("Example domains")
end
end
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
如何捕获 Sinatra 的内部通话并通过 VCR 进行录制?
如果我在测试中放置 Net::HTTP 调用,那么我会得到正确的记录,但这不是我想要驱动测试的方式。
有两个问题需要回答,一个是你问的问题,另一个是臭名昭著的 XY 问题,这就是我要开始的地方。
如果我在测试中放置 Net::HTTP 调用,那么我会得到正确的记录,但这不是我想要驱动测试的方式。
您想要捕获响应以进行单元测试,但您还决定将其包装在集成测试中(通过使用
visit
)。最好只获取响应,然后分离出您想要测试的级别。对于集成测试,我认为 VCR 不合适,这种测试应该在没有任何模拟的情况下运行(或“绝对”最小值)。它是集成的,即它将一切整合在一起,测试中不应遗漏任何内容。因此,他们预计需要时间。他们的作用是自动化并取代您手动检查网站,它应该尽可能真实。
单元测试测试一个小单元,并且可能应该对事情进行模拟和重播。他们首先测试功能,因此拥有罐装数据是件好事——它的速度也是一件好事。您可能也有非模拟、非边缘情况单元测试,对于边缘情况等,显然有一个范围,但集成和单元测试位于该范围的两端。
如何捕获 Sinatra 的内部通话并通过 VCR 进行录制?我查看了 VCR 源。它使用中间件和挂钩来获取响应。例如,这是 Typhoeus 钩子:
::Typhoeus.on_complete do |response|
request = response.request
restore_body_from_chunks(response, request) if request.streaming?
unless VCR.library_hooks.disabled?(:typhoeus)
vcr_response = vcr_response_from(response)
typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
unless request.response.mock
http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
VCR.record_http_interaction(http_interaction)
end
VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
end
end
它需要一个
response
,将其更改为
vcr_response
,然后使用它来获取 http_interaction
,然后通过 VCR.record_http_interaction(http_interaction)
进行记录。我看不到 Selenium 或 Capybara 的钩子,因此没有调用 record_http_interaction
,这可能是因为我在上面 XY 问题中概述的内容,它不合适,所以没有人写它。当然,您可以按照 VCR 存储库中已有的 hooks 和中间件目录中的示例进行操作。我可能只是使用 Rack::Test 并使用其他人的工作,我发现这个有用的 rack-vcr