sbmt-pact 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +62 -0
- data/Appraisals +23 -0
- data/CHANGELOG.md +96 -0
- data/Dockerfile +14 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +212 -0
- data/Rakefile +12 -0
- data/dip.yml +86 -0
- data/docker-compose.yml +40 -0
- data/docs/sbmt-pact-arch.png +0 -0
- data/lefthook-local.dip_example.yml +4 -0
- data/lefthook.yml +6 -0
- data/lib/sbmt/pact/configuration.rb +23 -0
- data/lib/sbmt/pact/consumer/grpc_interaction_builder.rb +193 -0
- data/lib/sbmt/pact/consumer/http_interaction_builder.rb +149 -0
- data/lib/sbmt/pact/consumer/interaction_contents.rb +47 -0
- data/lib/sbmt/pact/consumer/message_interaction_builder.rb +285 -0
- data/lib/sbmt/pact/consumer/mock_server.rb +92 -0
- data/lib/sbmt/pact/consumer/pact_config/base.rb +24 -0
- data/lib/sbmt/pact/consumer/pact_config/grpc.rb +26 -0
- data/lib/sbmt/pact/consumer/pact_config/http.rb +26 -0
- data/lib/sbmt/pact/consumer/pact_config/message.rb +17 -0
- data/lib/sbmt/pact/consumer/pact_config.rb +24 -0
- data/lib/sbmt/pact/consumer.rb +8 -0
- data/lib/sbmt/pact/matchers/base.rb +67 -0
- data/lib/sbmt/pact/matchers/v1/equality.rb +19 -0
- data/lib/sbmt/pact/matchers/v2/regex.rb +19 -0
- data/lib/sbmt/pact/matchers/v2/type.rb +17 -0
- data/lib/sbmt/pact/matchers/v3/boolean.rb +17 -0
- data/lib/sbmt/pact/matchers/v3/date.rb +18 -0
- data/lib/sbmt/pact/matchers/v3/date_time.rb +18 -0
- data/lib/sbmt/pact/matchers/v3/decimal.rb +17 -0
- data/lib/sbmt/pact/matchers/v3/each.rb +42 -0
- data/lib/sbmt/pact/matchers/v3/include.rb +17 -0
- data/lib/sbmt/pact/matchers/v3/integer.rb +17 -0
- data/lib/sbmt/pact/matchers/v3/number.rb +17 -0
- data/lib/sbmt/pact/matchers/v3/time.rb +18 -0
- data/lib/sbmt/pact/matchers/v4/each_key.rb +26 -0
- data/lib/sbmt/pact/matchers/v4/each_key_value.rb +32 -0
- data/lib/sbmt/pact/matchers/v4/each_value.rb +33 -0
- data/lib/sbmt/pact/matchers/v4/not_empty.rb +17 -0
- data/lib/sbmt/pact/matchers.rb +94 -0
- data/lib/sbmt/pact/native/blocking_verifier.rb +17 -0
- data/lib/sbmt/pact/native/logger.rb +25 -0
- data/lib/sbmt/pact/provider/async_message_verifier.rb +32 -0
- data/lib/sbmt/pact/provider/base_verifier.rb +158 -0
- data/lib/sbmt/pact/provider/grpc_verifier.rb +42 -0
- data/lib/sbmt/pact/provider/gruf_server.rb +75 -0
- data/lib/sbmt/pact/provider/http_server.rb +66 -0
- data/lib/sbmt/pact/provider/http_verifier.rb +46 -0
- data/lib/sbmt/pact/provider/message_provider_servlet.rb +80 -0
- data/lib/sbmt/pact/provider/pact_broker_proxy.rb +85 -0
- data/lib/sbmt/pact/provider/pact_broker_proxy_runner.rb +71 -0
- data/lib/sbmt/pact/provider/pact_config/async.rb +25 -0
- data/lib/sbmt/pact/provider/pact_config/base.rb +92 -0
- data/lib/sbmt/pact/provider/pact_config/grpc.rb +30 -0
- data/lib/sbmt/pact/provider/pact_config/http.rb +25 -0
- data/lib/sbmt/pact/provider/pact_config.rb +24 -0
- data/lib/sbmt/pact/provider/provider_server_runner.rb +89 -0
- data/lib/sbmt/pact/provider/provider_state_configuration.rb +32 -0
- data/lib/sbmt/pact/provider/provider_state_servlet.rb +84 -0
- data/lib/sbmt/pact/provider.rb +8 -0
- data/lib/sbmt/pact/railtie.rb +13 -0
- data/lib/sbmt/pact/rspec/support/pact_consumer_helpers.rb +46 -0
- data/lib/sbmt/pact/rspec/support/pact_message_helpers.rb +42 -0
- data/lib/sbmt/pact/rspec/support/pact_provider_helpers.rb +87 -0
- data/lib/sbmt/pact/rspec/support/waterdrop/pact_waterdrop_client.rb +27 -0
- data/lib/sbmt/pact/rspec/support/webmock/webmock_helpers.rb +30 -0
- data/lib/sbmt/pact/rspec.rb +17 -0
- data/lib/sbmt/pact/tasks/pact.rake +13 -0
- data/lib/sbmt/pact/version.rb +7 -0
- data/lib/sbmt/pact.rb +48 -0
- data/sbmt-pact.gemspec +59 -0
- metadata +462 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4e25420695b0554f5f33b616489005f728e0181586e0406da057fbd50bed1d06
|
4
|
+
data.tar.gz: 84972279401ef1a085806fc7e19a678bdd9b919edb306050c8c0432cf60c1cb3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa7672e3b37b7ed48827fca27ce7eb433318a1bc03e1ad9d41b00fde572d718d2989ab57ae90c298bbab991b0277565d5bc23ddb2862d1a762268256357e3f50
|
7
|
+
data.tar.gz: 1e3ae269dd85853864be55b2131556c09f16f61d81b8308a9b112a86d2ad834e3bf159bf80d3ac34b868a8d9dc232f5601fb18ccd18e724cb1535b0f4440d713
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# We want Exclude directives from different
|
2
|
+
# config files to get merged, not overwritten
|
3
|
+
inherit_mode:
|
4
|
+
merge:
|
5
|
+
- Exclude
|
6
|
+
|
7
|
+
AllCops:
|
8
|
+
TargetRubyVersion: 2.7
|
9
|
+
TargetRailsVersion: 6.0
|
10
|
+
NewCops: enable
|
11
|
+
SuggestExtensions: false
|
12
|
+
Exclude:
|
13
|
+
- spec/internal/pkg/**/*
|
14
|
+
|
15
|
+
require:
|
16
|
+
# Performance cops are bundled with Standard
|
17
|
+
- rubocop-performance
|
18
|
+
- rubocop-rails
|
19
|
+
- rubocop-rspec
|
20
|
+
# Standard's config uses custom cops,
|
21
|
+
# so it must be loaded
|
22
|
+
- standard
|
23
|
+
|
24
|
+
inherit_gem:
|
25
|
+
standard: config/base.yml
|
26
|
+
|
27
|
+
# rubocop-rails
|
28
|
+
Rails/SkipsModelValidations:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
# rubocop-rspec
|
32
|
+
RSpec/AnyInstance:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
RSpec/MultipleExpectations:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
RSpec/LetSetup:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
RSpec/StubbedMock:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
RSpec/MessageSpies:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
RSpec/NestedGroups:
|
48
|
+
Max: 10
|
49
|
+
|
50
|
+
RSpec/ExampleLength:
|
51
|
+
Max: 70
|
52
|
+
|
53
|
+
RSpec/MultipleMemoizedHelpers:
|
54
|
+
Max: 15
|
55
|
+
|
56
|
+
RSpec/DescribeClass:
|
57
|
+
Exclude:
|
58
|
+
- spec/sbmt/pact/tasks/*
|
59
|
+
|
60
|
+
RSpec/EmptyExampleGroup:
|
61
|
+
Exclude:
|
62
|
+
- spec/pact/**/*
|
data/Appraisals
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# See compatibility table at https://www.fastruby.io/blog/ruby/rails/versions/compatibility-table.html
|
4
|
+
|
5
|
+
versions_map = {
|
6
|
+
"6.0" => %w[2.7],
|
7
|
+
"6.1" => %w[2.7 3.0],
|
8
|
+
"7.0" => %w[3.1],
|
9
|
+
"7.1" => %w[3.2],
|
10
|
+
"7.2" => %w[3.3]
|
11
|
+
}
|
12
|
+
|
13
|
+
current_ruby_version = RUBY_VERSION.split(".").first(2).join(".")
|
14
|
+
|
15
|
+
versions_map.each do |rails_version, ruby_versions|
|
16
|
+
ruby_versions.each do |ruby_version|
|
17
|
+
next if ruby_version != current_ruby_version
|
18
|
+
|
19
|
+
appraise "rails-#{rails_version}" do
|
20
|
+
gem "rails", "~> #{rails_version}.0"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
6
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
7
|
+
|
8
|
+
## [Unreleased] - yyyy-mm-dd
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
- Remove sbmt-dev
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
## [0.11.1] - 2024-08-22
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
- the `verify_only` config option is now set based on the `PACT_CONSUMER_FULL_NAME` environment variable.
|
22
|
+
- if the current `consumer_name` does not match the `verify_only` option, then the consumer verification is skipped
|
23
|
+
|
24
|
+
## [0.11.0] - 2024-08-07
|
25
|
+
|
26
|
+
### Added
|
27
|
+
- async messages support
|
28
|
+
- collection matchers
|
29
|
+
- support of additional includes of proto-files for grpc plugin
|
30
|
+
|
31
|
+
## [0.10.0] - 2024-08-15
|
32
|
+
|
33
|
+
### Added
|
34
|
+
- HTTP Rspec DSL
|
35
|
+
|
36
|
+
## [0.9.0] - 2024-08-03
|
37
|
+
|
38
|
+
### Added
|
39
|
+
- pact-broker-proxy to filter proper transport types in specs
|
40
|
+
- ability to run pact-tests on CI + dip
|
41
|
+
|
42
|
+
### Fixed
|
43
|
+
- refactor matchers
|
44
|
+
|
45
|
+
## [0.8.0] - 2024-07-04
|
46
|
+
|
47
|
+
### Added
|
48
|
+
- Use `deployed: true` for default consumer selectors instead master branch
|
49
|
+
|
50
|
+
## [0.7.0] - 2024-06-21
|
51
|
+
|
52
|
+
### Added
|
53
|
+
- Ability to limit consumers to verify with provider
|
54
|
+
|
55
|
+
### Fixed
|
56
|
+
- Changed pact-specs rspec meta (`type: :pact` => `pact: true`) for compatibility with legacy pact-ruby / older rspec
|
57
|
+
- Bump used pact-protobuf-plugin version to 0.4.0
|
58
|
+
- `match_any_string` now matches empty strings
|
59
|
+
- limit pact:verify specs only to consumer pact-tests dir
|
60
|
+
|
61
|
+
## [0.6.0] - 2024-06-05
|
62
|
+
|
63
|
+
### Fixed
|
64
|
+
- GRPC producer DSL (rspec) refined
|
65
|
+
|
66
|
+
## [0.5.0] - 2024-06-05
|
67
|
+
|
68
|
+
### Fixed
|
69
|
+
- GRPC consumer DSL (rspec) refined
|
70
|
+
- plugin matchers refined
|
71
|
+
|
72
|
+
## [0.4.1] - 2024-06-06
|
73
|
+
|
74
|
+
### Fixed
|
75
|
+
- Use proper consumer version for provider verification
|
76
|
+
|
77
|
+
## [0.4.0] - 2024-05-29
|
78
|
+
|
79
|
+
### Added
|
80
|
+
- Ability to verify provider specs against pact-broker
|
81
|
+
|
82
|
+
## [0.3.0] - 2024-05-03
|
83
|
+
|
84
|
+
### Added
|
85
|
+
- Provider specs base DSL/helpers
|
86
|
+
|
87
|
+
## [0.2.0] - 2024-04-18
|
88
|
+
|
89
|
+
### Added
|
90
|
+
- Consumer specs base DSL/helpers
|
91
|
+
|
92
|
+
## [Unreleased]
|
93
|
+
|
94
|
+
## [0.1.0] - 2024-04-12
|
95
|
+
|
96
|
+
- Initial release
|
data/Dockerfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ARG RUBY_VERSION
|
2
|
+
|
3
|
+
FROM ruby:$RUBY_VERSION
|
4
|
+
|
5
|
+
ARG BUNDLER_VERSION
|
6
|
+
ARG RUBYGEMS_VERSION
|
7
|
+
|
8
|
+
ENV BUNDLE_JOBS=4 \
|
9
|
+
BUNDLE_RETRY=3
|
10
|
+
|
11
|
+
RUN gem update --system "${RUBYGEMS_VERSION}" \
|
12
|
+
&& rm /usr/local/lib/ruby/gems/*/specifications/default/bundler*.gemspec \
|
13
|
+
&& gem install --default bundler:${BUNDLER_VERSION} \
|
14
|
+
&& gem install bundler -v ${BUNDLER_VERSION}
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Kuper Tech
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
# Sbmt Pact
|
2
|
+
|
3
|
+
**`sbmt-pact`** is a powerful Ruby gem designed to simplify and streamline [Pact](https://docs.pact.io/) testing between microservices. This gem provides a robust set of RSpec utilities to help developers implement consumer-driven contract testing in microservice architectures.
|
4
|
+
|
5
|
+
In the world of microservices, ensuring seamless communication between services is crucial. This gem leverages the Pact to enable effective contract testing, allowing you to catch integration issues early in the development cycle. Contract testing is a way to check if different parts of a system work well together. It's like making sure two puzzle pieces fit perfectly before assembling the whole puzzle. Each part is tested on its own to see if it follows a set of rules (the "contract") that everyone agreed on. This helps catch problems early and makes sure all parts of the system speak the same language.
|
6
|
+
|
7
|
+
## Motivation
|
8
|
+
|
9
|
+
Currently, the existing version of the [pact-ruby](https://github.com/pact-foundation/pact-ruby) gem only supports Pact Specification versions v1 and v2, which doesn't allow for:
|
10
|
+
- Writing contract tests with non-HTTP transports (for example, gRPC)
|
11
|
+
- Writing contract tests for async messages (Kafka, etc.)
|
12
|
+
|
13
|
+
The `pact-ruby` gem is in maintenance mode, as there has been a transition to rust-core, which is intended to be used through FFI in non-Rust stacks.
|
14
|
+
|
15
|
+
This gem eliminates the above-mentioned limitations and implements support for the latest versions of Pact specifications:
|
16
|
+
- It's based on pact-ffi and pact-ruby-ffi
|
17
|
+
- It provides a convenient DSL, simplifying the writing of contract tests in Ruby/RSpec
|
18
|
+
|
19
|
+
## Architecture
|
20
|
+
|
21
|
+
![Pact tests architecture](docs/sbmt-pact-arch.png)
|
22
|
+
|
23
|
+
- DSL - implementation of RSpec-DSL for convenient writing of Pact tests
|
24
|
+
- Matchers - implementation of Pact matchers, which are convenient helpers used in consumer-DSL, encapsulating all the logic for serialization into Pact format
|
25
|
+
- Mock servers - mock servers that allow for correct execution of provider tests
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
For each type of interaction (due to their specific features), a separate version of DSL has been implemented. However, the general principles remain the same for each type of interaction.
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
|
33
|
+
# Declaration of a consumer test, always include the :pact tag
|
34
|
+
# This is used in CI/CD pipelines to separate Pact tests from other RSpec tests
|
35
|
+
# Pact tests are not run as part of the general RSpec pipeline
|
36
|
+
RSpec.describe "SomePactConsumerTestForAnyTransport", :pact do
|
37
|
+
# declaration of the type of interaction - here we determine which consumer and provider interact on which transport
|
38
|
+
has_http_pact_between "CONSUMER-NAME", "PROVIDER-NAME"
|
39
|
+
# or
|
40
|
+
has_grpc_pact_between "CONSUMER-NAME", "PROVIDER-NAME"
|
41
|
+
# or
|
42
|
+
has_message_pact_between "CONSUMER-NAME", "PROVIDER-NAME"
|
43
|
+
|
44
|
+
# the context for one of the interactions, for example GET /api/v2/stores
|
45
|
+
context "with GET /api/v2/stores" do
|
46
|
+
let(:interaction) do
|
47
|
+
# creating a new interaction - within which we describe the contract
|
48
|
+
new_interaction
|
49
|
+
# if you need to save any metadata for subsequent use by the test provider,
|
50
|
+
# for example, specify the entity ID that will need to be moved to the database in the test provider
|
51
|
+
# we use the provider states, see more at https://docs.pact.io/getting_started/provider_states
|
52
|
+
.given("UNIQUE PROVIDER STATE", key1: value1, key2: value2)
|
53
|
+
# the description of the interaction, used for identification inside the package binding,
|
54
|
+
# is optional in some cases, but it is recommended to always specify
|
55
|
+
.upon_receiving("UNIQUE INTERACTION DESCRIPTION")
|
56
|
+
# the description of the request using the matchers
|
57
|
+
# the name and parameters of the method differ for different transports
|
58
|
+
.with_request(...)
|
59
|
+
# the description of the response using the matchers
|
60
|
+
# the name and parameters of the method differ for different transports
|
61
|
+
.with_response(...)
|
62
|
+
# further, there are differences for different types of transports,
|
63
|
+
# for more information, see the relevant sections of the documentation
|
64
|
+
end
|
65
|
+
|
66
|
+
it "executes the pact test without errors" do
|
67
|
+
interaction.execute do
|
68
|
+
# here our client is called for the API being tested
|
69
|
+
# in this context, the client can be: http client, grpc client, kafka consumer
|
70
|
+
expect(make_request).to be_success
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
```
|
77
|
+
|
78
|
+
Common DSL Methods:
|
79
|
+
- `new_interaction` - initializes a new interaction
|
80
|
+
- `given` - allows specifying a provider state with or without parameters, for more details see https://docs.pact.io/getting_started/provider_states
|
81
|
+
- `upon_receiving` - allows specifying the name of the interaction
|
82
|
+
|
83
|
+
### HTTP consumers
|
84
|
+
|
85
|
+
Specific DSL methods:
|
86
|
+
- `with_request(HTTP_METHOD, QUERY_PATH, {headers: kv_hash, body: kv_hash})` - request definition
|
87
|
+
- `with_response(HTTP_STATUS, {headers: kv_hash, body: kv_hash})` - response definition
|
88
|
+
|
89
|
+
More at [http_client_spec.rb](spec/pact/providers/sbmt-pact-test-app/http_client_spec.rb)
|
90
|
+
|
91
|
+
### gRPC consumers
|
92
|
+
|
93
|
+
Specific DSL methods:
|
94
|
+
- `with_service(PROTO_PATH, RPC_SERVICE_AND_ACTION)` - specifies the contract used, PROTO_PATH is relative from the app root
|
95
|
+
- `with_request(request_kv_hash)` - request definition
|
96
|
+
- `with_response(response_kv_hash)` - response definition
|
97
|
+
|
98
|
+
More at [grpc_client_spec.rb](spec/pact/providers/sbmt-pact-test-app/grpc_client_spec.rb)
|
99
|
+
|
100
|
+
### Kafka consumers
|
101
|
+
|
102
|
+
Specific DSL methods:
|
103
|
+
- `with_headers(kv_hash)` - message-headers definition; you can use matchers
|
104
|
+
- `with_metadata(kv_hash)` - message-metadata definition (special keys are `key` and `topic`, where, respectively, you can specify the matchers for the partitioning key and the topic
|
105
|
+
|
106
|
+
Next, the specifics are one of two options for describing the format:
|
107
|
+
|
108
|
+
**JSON** (to describe a message in a JSON representation):
|
109
|
+
- `with_json_contents(kv_hash)` - message format definition
|
110
|
+
|
111
|
+
**PROTO** (to describe the message in the protobuf view):
|
112
|
+
- `with_proto_class(PROTO_PATH, PROTO_MESSAGE_NAME)` - specifies the contract used, PROTO_PATH is relative to the root, PROTO_MESSAGE_NAME is the name of the message used from the proto file
|
113
|
+
- `with_proto_contents(kv_hash)` - message format definition
|
114
|
+
|
115
|
+
More at [kafka_spec.rb](spec/pact/providers/sbmt-pact-test-app/kafka_spec.rb)
|
116
|
+
|
117
|
+
### Matchers
|
118
|
+
|
119
|
+
Matchers are special helper methods that allow you to define rules for matching request/response parameters at the level of the pact manifest.
|
120
|
+
The matchers are described in the [Pact specifications](https://github.com/pact-foundation/pact-specification). In this gem, the matchers are implemented as RSpec helpers.
|
121
|
+
|
122
|
+
For details of the implementation, see [matchers.rb](lib/sbmt/pact/matchers.rb)
|
123
|
+
|
124
|
+
- `match_exactly(sample)` - match the exact value specified in the sample
|
125
|
+
- `match_type_of(sample)` - match the data type (integer, string, boolean) specified in the sample
|
126
|
+
- `match_include(sample)` - match a substring
|
127
|
+
- `match_any_string(sample)` - match any string, because of the peculiarities, null and empty strings will also be matched here
|
128
|
+
- `match_any_integer(sample)` - match any integer
|
129
|
+
- `match_any_decimal(sample)` - match any float/double
|
130
|
+
- `match_any_number(sample)` - match any integer/float/double
|
131
|
+
- `match_any_boolean(sample)` - match any true/false
|
132
|
+
- `match_uuid(sample)` - match any UUID (`match_regex` is used under the hood)
|
133
|
+
- `match_regex(regex, sample)` - match by regexp
|
134
|
+
- `match_datetime(format, sample)` - match any datetime
|
135
|
+
- `match_iso8601(sample)` - match datetime in ISO8601 (the matcher does not fully comply with ISO8601, matches only the most common variants, `match_regex` is used under the hood)
|
136
|
+
- `match_date(format, sample)` - match any date (rust datetime)
|
137
|
+
- `match_time(format, sample)` - match any time (rust datetime)
|
138
|
+
- `match_each(template)` - match all the elements of the array according to the specified template, you can use it for nested elements
|
139
|
+
- `match_each_regex(regex, sample)` - match all array elements by regex, used for arrays with string elements
|
140
|
+
- `match_each_key(template, key_matchers)` - match each hash key according to the specified template
|
141
|
+
- `match_each_value(template)` - match each hash value according to the specified template, can be used for nested elements
|
142
|
+
- `match_each_kv(template, key_matchers)` - match all the keys/values of Hash according to the specified template and key_matchers, can be used for nested elements
|
143
|
+
|
144
|
+
See the different uses of the matchers in [matchers_spec.rb](spec/sbmt/pact/matchers_spec.rb)
|
145
|
+
|
146
|
+
## Development & Test
|
147
|
+
|
148
|
+
Install [Dip](https://github.com/bibendi/dip)
|
149
|
+
|
150
|
+
### Setup
|
151
|
+
|
152
|
+
```shell
|
153
|
+
dip provision
|
154
|
+
```
|
155
|
+
|
156
|
+
### Run unit tests
|
157
|
+
|
158
|
+
```shell
|
159
|
+
dip rspec
|
160
|
+
```
|
161
|
+
|
162
|
+
### Run pact tests
|
163
|
+
|
164
|
+
The Pact tests are not run within the general rspec pipeline, they need to be run separately, see below
|
165
|
+
|
166
|
+
#### Consumer tests
|
167
|
+
|
168
|
+
```shell
|
169
|
+
dip pact consumer
|
170
|
+
# or
|
171
|
+
bundle exec rspec -t pact spec/pact/providers/**/*_spec.rb
|
172
|
+
```
|
173
|
+
|
174
|
+
**NOTE** If you have never run it, you need to run it at least once to generate json-pact manifests that will be used in provider tests (below)
|
175
|
+
|
176
|
+
#### Provider tests
|
177
|
+
|
178
|
+
```shell
|
179
|
+
dip pact provider
|
180
|
+
# or
|
181
|
+
bundle exec rspec -t pact spec/pact/consumers/*_spec.rb
|
182
|
+
```
|
183
|
+
|
184
|
+
#### Using Pact Broker locally
|
185
|
+
|
186
|
+
If you need to check the ability to work with a package broker locally, you need to do the following:
|
187
|
+
|
188
|
+
- Run the broker
|
189
|
+
|
190
|
+
```shell
|
191
|
+
$ dip up pact-broker
|
192
|
+
```
|
193
|
+
|
194
|
+
- Run consumer tests to generate a pact manifest (it will be created in `spec/internal/pacts` based on the results of successful completion of consumer tests)
|
195
|
+
|
196
|
+
```shell
|
197
|
+
$ dip pact consumer
|
198
|
+
```
|
199
|
+
|
200
|
+
- Publish the generated pact manifest in the pact broker
|
201
|
+
|
202
|
+
```shell
|
203
|
+
$ dip pact-cli publish
|
204
|
+
```
|
205
|
+
|
206
|
+
- Make sure that the manifest is published by opening it in a browser http://localhost:9292 (don't forget to forward port 9292 to localhost, see `docker-compose.yml`)
|
207
|
+
|
208
|
+
- run provider tests using a pact broker
|
209
|
+
|
210
|
+
```shell
|
211
|
+
$ dip pact provider-with-local-broker
|
212
|
+
```
|
data/Rakefile
ADDED
data/dip.yml
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
version: '7'
|
2
|
+
|
3
|
+
environment:
|
4
|
+
RUBY_VERSION: '3.3'
|
5
|
+
|
6
|
+
compose:
|
7
|
+
files:
|
8
|
+
- docker-compose.yml
|
9
|
+
|
10
|
+
interaction:
|
11
|
+
bash:
|
12
|
+
description: Open the Bash shell in app's container
|
13
|
+
service: ruby
|
14
|
+
command: /bin/bash
|
15
|
+
|
16
|
+
bundle:
|
17
|
+
description: Run Bundler commands
|
18
|
+
service: ruby
|
19
|
+
command: bundle
|
20
|
+
|
21
|
+
rails:
|
22
|
+
description: Run RoR commands
|
23
|
+
service: ruby
|
24
|
+
command: bundle exec rails
|
25
|
+
|
26
|
+
appraisal:
|
27
|
+
description: Run Appraisal commands
|
28
|
+
service: ruby
|
29
|
+
command: bundle exec appraisal
|
30
|
+
|
31
|
+
rspec:
|
32
|
+
description: Run Rspec commands
|
33
|
+
service: ruby
|
34
|
+
command: bundle exec rspec
|
35
|
+
subcommands:
|
36
|
+
all:
|
37
|
+
command: bundle exec appraisal rspec
|
38
|
+
rails-6.0:
|
39
|
+
command: bundle exec appraisal rails-6.0 rspec
|
40
|
+
rails-6.1:
|
41
|
+
command: bundle exec appraisal rails-6.1 rspec
|
42
|
+
rails-7.0:
|
43
|
+
command: bundle exec appraisal rails-7.0 rspec
|
44
|
+
|
45
|
+
pact:
|
46
|
+
description: Run pact tests
|
47
|
+
service: ruby
|
48
|
+
environment:
|
49
|
+
RAILS_ENV: test
|
50
|
+
PACT_DO_NOT_TRACK: true
|
51
|
+
subcommands:
|
52
|
+
consumer:
|
53
|
+
command: bundle exec rspec -t pact spec/pact/providers/**/*_spec.rb
|
54
|
+
provider:
|
55
|
+
command: bundle exec rspec -t pact spec/pact/consumers/*_spec.rb
|
56
|
+
provider-with-local-broker:
|
57
|
+
command: /bin/sh -c 'PACT_CONSUMER_BRANCH=master PACT_CONSUMER_FULL_NAME=sbmt-pact-test-app PACT_BROKER_URL=http://pact-broker:9292 bundle exec rspec -t pact spec/pact/consumers/*_spec.rb'
|
58
|
+
|
59
|
+
pact-cli:
|
60
|
+
description: Run pact-broker commands
|
61
|
+
service: pact-cli
|
62
|
+
subcommands:
|
63
|
+
publish:
|
64
|
+
command: pact-broker publish --consumer-app-version 1.0.0 --branch master --broker-base-url http://pact-broker:9292 sbmt-pact-test-app-sbmt-pact-test-app.json
|
65
|
+
|
66
|
+
rubocop:
|
67
|
+
description: Run Ruby linter
|
68
|
+
service: ruby
|
69
|
+
command: bundle exec rubocop
|
70
|
+
|
71
|
+
setup:
|
72
|
+
description: Install deps
|
73
|
+
service: ruby
|
74
|
+
command: bin/setup
|
75
|
+
|
76
|
+
test:
|
77
|
+
description: Run linters, run all tests
|
78
|
+
service: ruby
|
79
|
+
command: bin/test
|
80
|
+
|
81
|
+
provision:
|
82
|
+
- dip compose down --volumes
|
83
|
+
- cp -f lefthook-local.dip_example.yml lefthook-local.yml
|
84
|
+
- rm -f Gemfile.lock
|
85
|
+
- rm -f gemfiles/*gemfile*
|
86
|
+
- dip setup
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
services:
|
2
|
+
ruby:
|
3
|
+
build:
|
4
|
+
context: .
|
5
|
+
dockerfile: Dockerfile
|
6
|
+
args:
|
7
|
+
RUBY_VERSION: ${RUBY_VERSION:-3.3}
|
8
|
+
BUNDLER_VERSION: 2.4.22
|
9
|
+
RUBYGEMS_VERSION: 3.4.22
|
10
|
+
image: sbmt-pact-dev:0.1.0-ruby_${RUBY_VERSION:-3.3}
|
11
|
+
environment:
|
12
|
+
HISTFILE: /app/tmp/.bash_history
|
13
|
+
BUNDLE_PATH: /usr/local/bundle
|
14
|
+
BUNDLE_CONFIG: /app/.bundle/config
|
15
|
+
command: bash
|
16
|
+
working_dir: /app
|
17
|
+
volumes:
|
18
|
+
- .:/app:cached
|
19
|
+
- ${SBMT_RUBYGEMS_PATH:-..}:/app/vendor/gems:cached
|
20
|
+
- bundler_data:/usr/local/bundle
|
21
|
+
|
22
|
+
pact-broker:
|
23
|
+
image: pactfoundation/pact-broker
|
24
|
+
ports:
|
25
|
+
- 9292
|
26
|
+
environment:
|
27
|
+
PACT_BROKER_DATABASE_ADAPTER: sqlite
|
28
|
+
PACT_BROKER_DATABASE_NAME: pact_broker.sqlite
|
29
|
+
PACT_BROKER_LOG_LEVEL: DEBUG
|
30
|
+
|
31
|
+
pact-cli:
|
32
|
+
image: pactfoundation/pact-cli
|
33
|
+
working_dir: /app
|
34
|
+
depends_on:
|
35
|
+
- pact-broker
|
36
|
+
volumes:
|
37
|
+
- ./spec/internal/pacts:/app:cached
|
38
|
+
|
39
|
+
volumes:
|
40
|
+
bundler_data:
|
Binary file
|
data/lefthook.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sbmt
|
4
|
+
module Pact
|
5
|
+
class Configuration
|
6
|
+
attr_reader :before_provider_state_proc, :after_provider_state_proc
|
7
|
+
|
8
|
+
class GlobalProviderConfigurationError < ::Sbmt::Pact::Error; end
|
9
|
+
|
10
|
+
def before_provider_state_setup(&block)
|
11
|
+
raise GlobalProviderConfigurationError, "no block given" unless block
|
12
|
+
|
13
|
+
@before_provider_state_proc = block
|
14
|
+
end
|
15
|
+
|
16
|
+
def after_provider_state_teardown(&block)
|
17
|
+
raise GlobalProviderConfigurationError, "no block given" unless block
|
18
|
+
|
19
|
+
@after_provider_state_proc = block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|