debian-mirror-gitlab/doc/development/testing_guide/contract/provider_tests.md

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

211 lines
9.1 KiB
Markdown
Raw Normal View History

2022-07-23 23:45:48 +05:30
---
stage: none
group: Development
2022-11-25 23:54:43 +05:30
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
2022-07-23 23:45:48 +05:30
---
# Writing provider tests
2022-08-13 15:12:31 +05:30
This tutorial guides you through writing a provider test from scratch. It is a continuation of the [consumer test tutorial](consumer_tests.md). To start, the provider tests are written using [`pact-ruby`](https://github.com/pact-foundation/pact-ruby). In this tutorial, you write a provider test that addresses the contract generated by `discussions.spec.js`. As Pact is a consumer-driven testing tool, this tutorial assumes that there is an existing consumer test that had already generated a contract for us to work with.
2022-07-23 23:45:48 +05:30
## Create the skeleton
2023-03-17 16:20:25 +05:30
Provider tests are quite simple. The goal is to set up the test data and then link that with the corresponding contract. Start by creating a file called `get_discussions_helper.rb` under `spec/contracts/provider/pact_helpers/project/merge_request`. Note that the files are called `helpers` to match how they are called by Pact in the Rake tasks, which are set up at the end of this tutorial.
2022-08-13 15:12:31 +05:30
2023-04-23 21:23:45 +05:30
For more information about how the contract test directory is structured, see [Test suite folder structure](index.md#test-suite-folder-structure).
2022-07-23 23:45:48 +05:30
### The `service_provider` block
The `service_provider` block is where the provider test is defined. For this block, put in a description of the service provider. Name it exactly as it is called in the contracts that are derived from the consumer tests.
```ruby
2022-08-13 15:12:31 +05:30
require_relative '../../../spec_helper'
2022-07-23 23:45:48 +05:30
module Provider
module DiscussionsHelper
2023-03-17 16:20:25 +05:30
Pact.service_provider 'GET discussions' do
2022-08-13 15:12:31 +05:30
2022-07-23 23:45:48 +05:30
end
end
end
```
### The `honours_pact_with` block
The `honours_pact_with` block describes which consumer this provider test is addressing. Similar to the `service_provider` block, name this exactly the same as it's called in the contracts that are derived from the consumer tests.
```ruby
2022-08-13 15:12:31 +05:30
require_relative '../../../spec_helper'
2022-07-23 23:45:48 +05:30
module Provider
module DiscussionsHelper
2023-03-17 16:20:25 +05:30
Pact.service_provider 'GET discussions' do
honours_pact_with 'MergeRequests#show' do
2022-08-13 15:12:31 +05:30
2022-07-23 23:45:48 +05:30
end
end
end
end
```
2023-04-23 21:23:45 +05:30
For more information about how to name consumers and providers, see [Naming conventions](index.md#naming-conventions).
2022-08-13 15:12:31 +05:30
2022-07-23 23:45:48 +05:30
## Configure the test app
For the provider tests to verify the contracts, you must hook it up to a test app that makes the actual request and return a response to verify against the contract. To do this, configure the `app` the test uses as `Environment::Test.app`, which is defined in [`spec/contracts/provider/environments/test.rb`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/spec/contracts/provider/environments/test.rb).
```ruby
2022-08-13 15:12:31 +05:30
require_relative '../../../spec_helper'
2022-07-23 23:45:48 +05:30
module Provider
module DiscussionsHelper
2023-03-17 16:20:25 +05:30
Pact.service_provider 'GET discussions' do
2022-07-23 23:45:48 +05:30
app { Environment::Test.app }
2022-08-13 15:12:31 +05:30
2023-03-17 16:20:25 +05:30
honours_pact_with 'MergeRequests#show' do
2022-08-13 15:12:31 +05:30
2022-07-23 23:45:48 +05:30
end
end
end
end
```
## Define the contract to verify
Now that the test app is configured, all that is left is to define which contract this provider test is verifying. To do this, set the `pact_uri`.
```ruby
2022-08-13 15:12:31 +05:30
require_relative '../../../spec_helper'
2022-07-23 23:45:48 +05:30
module Provider
module DiscussionsHelper
2023-03-17 16:20:25 +05:30
Pact.service_provider 'GET discussions' do
2022-07-23 23:45:48 +05:30
app { Environment::Test.app }
2022-08-13 15:12:31 +05:30
2023-03-17 16:20:25 +05:30
honours_pact_with 'MergeRequests#show' do
pact_uri '../contracts/project/merge_requests/show/mergerequests#show-merge_request_discussions_endpoint.json'
2022-07-23 23:45:48 +05:30
end
end
end
end
```
## Add / update the Rake tasks
2023-03-17 16:20:25 +05:30
Now that you have a test created, you must create Rake tasks that run this test. The Rake tasks are defined in [`lib/tasks/contracts/merge_requests.rake`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/tasks/contracts/merge_requests.rake) where we have individual Rake tasks to run individual tests, but also Rake tasks that run a group of tests.
2022-07-23 23:45:48 +05:30
2023-03-17 16:20:25 +05:30
Under the `contracts:merge_requests` namespace, introduce the Rake task to run this new test specifically. In it, call `pact.uri` to define the location of the contract and the provider test that tests that contract. Notice here that `pact_uri` has a parameter called `pact_helper`. This is why the provider tests are called `_helper.rb`.
2022-07-23 23:45:48 +05:30
```ruby
2023-03-17 16:20:25 +05:30
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"
2022-07-23 23:45:48 +05:30
pact.uri(
2023-03-17 16:20:25 +05:30
Provider::ContractSourceHelper.contract_location(:rake, pact_helper_location),
pact_helper: "#{provider}/#{pact_helper_location}"
2022-07-23 23:45:48 +05:30
)
end
```
2023-03-17 16:20:25 +05:30
[`Provider::ContractSourceHelper`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/spec/contracts/provider/helpers/contract_source_helper.rb) is a helper module that has the `#contract_location` method which parses `pact_helper_location` and determines where the contract is stored locally or on the Pact Broker depending on the `requester` passed in.
At the same time, add your new `:get_discussions` Rake task to be included in the `test:merge_requests` Rake task. In that Rake task, there is an array defined (`%w[get_diffs_batch get_diffs_metadata]`). You must add `get_discussions` in that list.
2022-07-23 23:45:48 +05:30
## Create test data
As the last step, create the test data that allows the provider test to return the contract's expected response. You might wonder why you create the test data last. It's really a matter of preference. With the test already configured, you can easily run the test to verify and make sure all the necessary test data are created to produce the expected response.
You can read more about [provider states](https://docs.pact.io/implementation_guides/ruby/provider_states). We can do global provider states but for this tutorial, the provider state is for one specific `state`.
2023-03-17 16:20:25 +05:30
To create the test data, create `show_state.rb` under `spec/contracts/provider/states/project/merge_requests`. Be sure to also import this state file in the `get_discussions_helper.rb` file.
2022-07-23 23:45:48 +05:30
### Default user in `spec/contracts/provider/spec_helper.rb`
Before you create the test data, note that a default user is created in the [`spec_helper`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/spec/contracts/provider/spec_helper.rb), which is the user being used for the test runs. This user is configured using `RSpec.configure`, as Pact actually is built on top of RSpec. This step allows us to configure the user before any of the test runs.
```ruby
RSpec.configure do |config|
config.include Devise::Test::IntegrationHelpers
2022-08-13 15:12:31 +05:30
config.include FactoryBot::Syntax::Methods
2022-07-23 23:45:48 +05:30
config.before do
2022-08-13 15:12:31 +05:30
user = create(:user, name: Provider::UsersHelper::CONTRACT_USER_NAME).tap do |user|
2022-07-23 23:45:48 +05:30
user.current_sign_in_at = Time.current
end
2022-08-13 15:12:31 +05:30
2022-07-23 23:45:48 +05:30
sign_in user
end
end
```
Any further modifications to the user that's needed can be done through the individual provider state files.
### The `provider_states_for` block
In the state file, you must define which consumer this provider state is for. You can do that with `provider_states_for`. Make sure that the `name` provided matches the name defined for the consumer.
```ruby
2023-03-17 16:20:25 +05:30
Pact.provider_states_for 'MergeRequests#show' do
2022-07-23 23:45:48 +05:30
end
```
### The `provider_state` block
In the `provider_states_for` block, you then define the state the test data is for. These states are also defined in the consumer test. In this case, there is a `'a merge request with discussions exists'` state.
```ruby
2023-03-17 16:20:25 +05:30
Pact.provider_states_for "MergeRequests#show" do
2022-07-23 23:45:48 +05:30
provider_state "a merge request with discussions exists" do
end
end
```
### The `set_up` block
This is where you define the test data creation steps. Use `FactoryBot` to create the data. As you create the test data, you can keep [running the provider test](index.md#run-the-provider-tests) to check on the status of the test and figure out what else is missing in your data setup.
```ruby
2023-03-17 16:20:25 +05:30
Pact.provider_states_for "MergeRequests#show" do
2022-07-23 23:45:48 +05:30
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
```
2022-08-13 15:12:31 +05:30
## Using the test data
Now that the provider state file is created, you need to import the state file to the provider test.
```ruby
# frozen_string_literal: true
require_relative '../../../spec_helper'
2023-03-17 16:20:25 +05:30
require_relative '../../../states/project/merge_requests/show_state'
2022-08-13 15:12:31 +05:30
module Provider
module DiscussionsHelper
2023-03-17 16:20:25 +05:30
Pact.service_provider "GET discussions" do
2022-08-13 15:12:31 +05:30
app { Environments::Test.app }
honours_pact_with 'Merge Request#show' do
2023-03-17 16:20:25 +05:30
pact_uri '../contracts/project/merge_requests/show/mergerequests#show-merge_request_discussions_endpoint.json'
2022-08-13 15:12:31 +05:30
end
end
end
end
```
2022-07-23 23:45:48 +05:30
2023-03-17 16:20:25 +05:30
And there we have it. The provider test for `get_discussions_helper.rb` should now pass with this.