프로바이더 테스트 작성

이 튜토리얼은 제로부터 프로바이더 테스트를 작성하는 방법을 안내합니다. 이는 소비자 테스트 튜토리얼의 연속입니다. 우선, 프로바이더 테스트는 pact-ruby를 사용하여 작성됩니다. 이 튜토리얼에서는 discussions.spec.js에서 생성된 계약을 다루는 프로바이더 테스트를 작성합니다. Pact는 소비자 중심의 테스팅 도구이므로, 이 튜토리얼은 이미 우리가 작업할 계약을 생성한 기존의 소비자 테스트가 있다고 가정합니다.

스켈레톤 생성

프로바이더 테스트는 매우 간단합니다. 목표는 테스트 데이터를 설정하고 해당 데이터를 해당 계약과 연결하는 것입니다. get_discussions_helper.rb라는 파일을 spec/contracts/provider/pact_helpers/project/merge_request 폴더 아래 만들어야 합니다. 이 파일들은 Pact에서 Rake 작업에서 호출되는 방식과 일치하기 위해 helpers라고 부릅니다. 이는 이 튜토리얼의 끝에서 설정되는 Rake 작업에 연결됩니다.

계약 테스트 디렉터리 구조에 대한 자세한 정보는 테스트 스위트 폴더 구조를 참조하세요.

service_provider 블록

service_provider 블록은 프로바이더 테스트가 정의되는 곳입니다. 이 블록에서 서비스 제공자에 대한 설명을 넣어야 합니다. 이 이름은 소비자 테스트에서 파생된 계약에서 호출된 것과 정확히 일치해야 합니다.

require_relative '../../../spec_helper'

module Provider
  module DiscussionsHelper
    Pact.service_provider 'GET discussions' do
    
    end
  end
end

honours_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

소비자와 제공자의 이름 정하는 방법에 대한 자세한 내용은 네이밍 규칙을 참조하세요.

테스트 앱 구성

계약을 검증하기 위해 프로바이더 테스트가 사용하는 테스트 앱을 설정해야 합니다. 실제 요청을 수행하고 계약과 일치하는 응답을 반환하는 테스트 앱에 연결해야 합니다. 이를 위해 사용되는 Environment::Test.appapp으로 설정합니다. 이것은 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}"
  )
end

Provider::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 위에 구축된 Pact에서 구성되는 것입니다. 여기서 우리는 테스트 실행 전에 사용자를 구성할 수 있습니다.

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
end

provider_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
end

set_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 { Environments::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의 제공자 테스트는 이제 통과해야 합니다.