编写提供者测试
本教程将指导你从头开始编写提供者测试。这是消费者测试教程的延续。首先,提供者测试使用 pact-ruby 编写。在本教程中,你将编写一个针对 discussions.spec.js 生成的契约的提供者测试。由于 Pact 是一个消费者驱动的测试工具,本教程假设已经存在一个消费者测试,它已经为我们生成了可供使用的契约。
创建骨架
提供者测试相当简单。目标是设置测试数据,然后将其与相应的契约关联。首先,在 spec/contracts/provider/pact_helpers/project/merge_request 目录下创建一个名为 get_discussions_helper.rb 的文件。这些文件被称为 helpers,以匹配它们在本教程末尾设置的 Rake 任务中被 Pact 调用的方式。
有关契约测试目录结构的更多信息,请参阅测试套件文件夹结构。
service_provider 块
service_provider 块是定义提供者测试的地方。在此块中,放入服务提供者的描述。命名方式与从消费者测试派生的契约中的调用方式完全一致。
require_relative '../../../spec_helper'
module Provider
module DiscussionsHelper
Pact.service_provider 'GET discussions' do
end
end
endhonours_pact_with 块
honours_pact_with 块描述了此提供者测试所针对的消费者。与 service_provider 块类似,命名方式与从消费者测试派生的契约中的调用方式完全一致。
require_relative '../../../spec_helper'
module Provider
module DiscussionsHelper
Pact.service_provider 'GET discussions' do
honours_pact_with 'MergeRequests#show' do
end
end
end
end有关如何命名消费者和提供者的更多信息,请参阅命名约定。
配置测试应用
为了使提供者测试能够验证契约,你必须将其连接到一个测试应用,该应用会发出实际请求并返回响应以供验证契约。为此,将测试使用的 app 配置为 Environment::Test.app,它定义在 spec/contracts/provider/environments/test.rb 中。
require_relative '../../../spec_helper'
module Provider
module DiscussionsHelper
Pact.service_provider 'GET discussions' do
app { Environment::Test.app }
honours_pact_with 'MergeRequests#show' do
end
end
end
end定义要验证的契约
现在测试应用已配置,剩下的就是定义此提供者测试要验证哪个契约。为此,设置 pact_uri。
require_relative '../../../spec_helper'
module Provider
module DiscussionsHelper
Pact.service_provider 'GET discussions' do
app { Environment::Test.app }
honours_pact_with 'MergeRequests#show' do
pact_uri '../contracts/project/merge_requests/show/mergerequests#show-merge_request_discussions_endpoint.json'
end
end
end
end添加/更新 Rake 任务
现在你已经创建了一个测试,你必须创建运行此测试的 Rake 任务。Rake 任务定义在 lib/tasks/contracts/merge_requests.rake 中,这里我们有运行单个测试的单独 Rake 任务,也有运行一组测试的 Rake 任务。
在 contracts:merge_requests 命名空间下,引入专门运行此新测试的 Rake 任务。在其中,调用 pact.uri 来定义契约的位置和测试该契约的提供者测试。注意这里 pact_uri 有一个名为 pact_helper 的参数。这就是为什么提供者测试被称为 _helper.rb 的原因。
Pact::VerificationTask.new(:get_discussions) do |pact|
provider = File.expand_path('../../../spec/contracts/provider', __dir__)
pact_helper_location = "pact_helpers/project/merge_requests/show/get_discussions_helper.rb"
pact.uri(
Provider::ContractSourceHelper.contract_location(:rake, pact_helper_location),
pact_helper: "#{provider}/#{pact_helper_location}"
)
endProvider::ContractSourceHelper 是一个辅助模块,它有 #contract_location 方法,该方法解析 pact_helper_location 并根据传入的 requester 确定契约是存储在本地还是 Pact Broker 上。
同时,将你的新 :get_discussions Rake 任务添加到要包含在 test:merge_requests Rake 任务中。在该 Rake 任务中,定义了一个数组(%w[get_diffs_batch get_diffs_metadata])。你必须在该列表中添加 get_discussions。
创建测试数据
作为最后一步,创建允许提供者测试返回契约预期响应的测试数据。你可能会疑惑为什么最后才创建测试数据。这实际上是个偏好问题。测试已经配置好,你可以轻松运行测试来验证,并确保创建了所有必要的测试数据来产生预期响应。
你可以阅读更多关于提供者状态的信息。我们可以做全局提供者状态,但本教程中,提供者状态是针对一个特定的 state。
要创建测试数据,在 spec/contracts/provider/states/project/merge_requests 下创建 show_state.rb。确保也在 get_discussions_helper.rb 文件中导入此状态文件。
spec/contracts/provider/spec_helper.rb 中的默认用户
在创建测试数据之前,在 spec_helper 中创建了一个默认用户,这是用于测试运行的用户。该用户使用 RSpec.configure 进行配置,因为 Pact 实际上是构建在 RSpec 之上的。这一步允许我们在任何测试运行之前配置用户。
RSpec.configure do |config|
config.include Devise::Test::IntegrationHelpers
config.include FactoryBot::Syntax::Methods
config.before do
user = create(:user, name: Provider::UsersHelper::CONTRACT_USER_NAME).tap do |user|
user.current_sign_in_at = Time.current
end
sign_in user
end
end对用户所需的任何进一步修改都可以通过各个提供者状态文件来完成。
provider_states_for 块
在状态文件中,你必须定义此提供者状态针对的消费者。你可以使用 provider_states_for 来实现这一点。确保提供的 name 与为消费者定义的名称匹配。
Pact.provider_states_for 'MergeRequests#show' do
endprovider_state 块
在 provider_states_for 块中,然后定义测试数据针对的状态。这些状态也在消费者测试中定义。在这种情况下,有一个 'a merge request with discussions exists' 状态。
Pact.provider_states_for "MergeRequests#show" do
provider_state "a merge request with discussions exists" do
end
endset_up 块
在这里你定义测试数据创建步骤。使用 FactoryBot 创建数据。在创建测试数据时,你可以继续运行提供者测试来检查测试状态,并找出数据设置中还缺少什么。
Pact.provider_states_for "MergeRequests#show" do
provider_state "a merge request with discussions exists" do
set_up do
user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
namespace = create(:namespace, name: 'gitlab-org')
project = create(:project, name: 'gitlab-qa', namespace: namespace)
project.add_maintainer(user)
merge_request = create(:merge_request_with_diffs, id: 1, source_project: project, author: user)
create(:discussion_note_on_merge_request, noteable: merge_request, project: project, author: user)
end
end
end使用测试数据
现在提供者状态文件已创建,你需要将状态文件导入到提供者测试中。
# frozen_string_literal: true
require_relative '../../../spec_helper'
require_relative '../../../states/project/merge_requests/show_state'
module Provider
module DiscussionsHelper
Pact.service_provider "GET discussions" do
app { Environment::Test.app }
honours_pact_with 'Merge Request#show' do
pact_uri '../contracts/project/merge_requests/show/mergerequests#show-merge_request_discussions_endpoint.json'
end
end
end
end就这样。get_discussions_helper.rb 的提供者测试现在应该可以通过了。