I'm working on a tool that includes PACT support a...
# general
r
I'm working on a tool that includes PACT support and I'm trying to make it fit as good as possible. I understand testing for an optional attribute does not make sense as another consumer might want it to be there. However, if I describe a scenario (by giving provider states) where the returned array should be empty, can we not verify that? After reading documentation and doing some testing, I come to these conclusions: 1. A scenario where the array contains at least one item is verifiable. 2. A scenario where the array contains max=1 item is verifiable. 3. A scenario where the array contains max=0 is not verifiable (I can specify an empty array, but PACT would still allow a non-empty array). A real world example of scenario 3 would be: Given a provider state of items with only state 'declined' searching for items with state 'accepted' would result in an empty array I could theoretically have 3 interactions: - Interaction 1: tests items in the array - Interaction 2: tests for array length == 1 under specific circumstances - Interaction 3: tests for array length == 0 under specific circumstances It therefore seems arbitrary to allow
max=1
but not
max=0
.
🎉 1
t
3. A scenario where the array contains max=0 is not verifiable (I can specify an empty array, but PACT would still allow a non-empty array).
No, it won’t. If you’re experiencing this, it’s a bug.
Sometimes, people get confused by the
eachLike
matcher in the empty array case. When the array is empty, you don’t need a matcher, you just specify an empty array.
✅ 1
A key point is that the matcher isn’t for “here are the possible responses that the server might make” it’s for “everything that passes this matcher is covered by this particular test”
✅ 1
So, yes, you’re right that you usually need at least: • Some items in the array of a particular shape • No items in the array Depending on the meaning in the response, you might also need things like: • Exactly one item • Exactly these items in this order (you don’t need
eachLike
for this) • Array that includes these specific items in any order etc
What’s your tool? I’m also working on something that will be pact-compatible, we could compare notes
I’m guessing a bit, but another key point that might be relevant is: In normal pact usage, a pact file can only be written if we know that the consumer works with what the pact file describes. This is important, as it’s what gives you deployment confidence when the verification of a pact file passes. Sometimes we find people who want to write pact files manually (or automatically from a spec), and this is usually a reduction in deployment confidence.
I’m also working on something that will be pact-compatible, we could compare notes
One of the things I’d like to do is to review the pact-jvm source code (where the pact matchers are all described clearly) and write up how each one behaves. I want to do this so that I can read pact files correctly - it’s not at the top of my todo list yet, but if this is the kind of thing your tool will also need, it definitely would be worth comparing notes.
It therefore seems arbitrary to allow max=1 but not max=0.
I believe the reason for this choice is that it’s normally something people want to be able to specify when there’s a misuse or misunderstanding - so preventing it brings them to the help pages or FAQ instead of writing a broken test by mistake. The framework could treat
max=0
as
[]
, but think about how it would work if Pact didn’t exist, and instead a coworker was describing the response to you: “Ok, I need exactly zero items, each of which matches this template” ….you’d be like “wait, what? What do you mean?“. It would be better to have your coworker say: “Ok, I need an empty array” “Got it” And that’s why instead of
eachLike(item, {max: 0})
, you should say
[]
Also, very small point, but it’s Pact not PACT ❤️
(for your documentation)
r
Thanks for explaining all of this! Let's say I want to match on type at the root:
Copy code
{
id: 1,
text: 'hello world',
items: [],
}
So id would be a number, text would be a string and items would be an array. Now if I want items to be zero-length in some scenario, I cannot have the
{ match:'type' }
on root, because it will then force items to be an any-length array. So in this scenario, I would have to be specific about matching
id
to be a
number
and
text
to be a
string
because I can't use
{ max:0 }
as a matcher on
$.todos
Is this correct?
Documenting the various matchers would be very helpful I think! I see you referring to the jvm as the source of truth. At some point I thought the pact_verifier_cli would be the reference implementation to look at?
I do see quite some interesting documentation on https://docs.pact.io/implementation_guides/rust/pact_matching too bad it is a bit hidden (Rust is not my main language)
t
Is this correct?
No. You can cancel the match and go back to exact for
items
(I forget what it’s called in the pact file format, but there’s a “match this exactly”), or you could do match of
"type"
on both the
id
and the
text
instead of on the root.
At some point I thought the pact_verifier_cli would be the reference implementation to look at?
My understanding is that they’re the same behaviour. When I was asking Ron if the matchers were documented anywhere, he said they weren’t documented in the spec, but pointed me at this: https://github.com/pact-foundation/pact-jvm/blob/master/core/matchers/src/main/kotlin/au/com/dius/pact/core/matchers/MatcherExecutor.kt#L142
Out of interest, what are you building?
r
Hi Timothy, I'm working on a TypeScript HTTP client with a focus on integration testing, what about you?
👀 1
t
I’m working on another contract testing tool which will solve some of the pain points I have with Pact - but ideally I want to be as Pact compatible as possible
m
Thanks for answering in detail - as always - Tim! I did very much take time afk during the “break” over xmas (I say break because I’m moving homes, so I’d much rather have “wasted” my 2 weeks on the computer here 😛 ) Sounds like a fun project Rinke. Let us know how we can support you!
❤️ 1