Last active
January 1, 2016 04:29
-
-
Save bethesque/5a35a3c1cb9fdab6dce7 to your computer and use it in GitHub Desktop.
An idea of what a flexible matching fluent API might look like, and how it could be serialised.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Notes: | |
# Headers and status would still be value based matching | |
# Default to type based matching??? | |
# like(xxx) means xxx and all children would be matched using type based matching | |
# literal(xxx) means xxx and all children would be matched using exact value matching | |
# eg(generate, matcher) would be a regular expression match | |
# each_like([]) would indicate the each element in the array should be like the example given | |
# A like() could be nested inside a literal() which could be nested inside a like() - at each stage, | |
# it changes the matching type for all children until it gets switched back. | |
# Outstanding questions: | |
# Should array order matter? | |
# How to specify something like "an array of strings, length unknown" (eg. the backtrace of an exception) | |
# Ruby code | |
will_respond_with( | |
{ | |
status: 200, | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
body: { | |
age: 30, | |
address: literal({ | |
street: '123 Fred St', | |
suburb: like('Melbourne'), | |
postcode: '3000', | |
state: eg('VIC',/[A-Z]{3}/) | |
}), | |
phoneNumber: eg("0415 134 234", /\d{4} \d{3} \d{3}/), | |
favouriteColors: each_like(['red']), | |
an_empty_array: [], | |
url: eg('http://localhost:1234/blah', %r{http://.*/blah}) | |
} | |
}) | |
# Generated JSON | |
{ | |
"responseMatchingRules": { | |
"body" : { | |
"$..*": {"match": "type"}, | |
"$.address": {"match":"value", "allowExtraKeys": false}, | |
"$.address.suburb": {"match":"type"}, | |
"$.phoneNumber": {"regex" : "\d{4} \d{3} \d{3}"}, | |
"$.favouriteColors": {"eachLike": true }, | |
"$.url": {"regex" : "http://.*/blah"} | |
} | |
}, | |
"response": { | |
"body": { | |
"age": 30, | |
"address": { | |
"street": "123 Fred St", | |
"suburb": "Melbourne", | |
"postcode": "3000", | |
"state": "VIC" | |
}, | |
"phoneNumber": "0415 134 234", | |
"favouriteColors": [ | |
"red" | |
], | |
"an_empty_array": [], | |
"parents": [ | |
"mum", | |
"dad" | |
], | |
"url": "http: //localhost:1234/blah" | |
} | |
} | |
} | |
end |
Super late to the party on this one.
The good thing about pact 1.0 is that you have a clear document indicating what's being tested structurally.
With the jsonpath matching rules, you've still got your structure, but then you've got a list of rules which are exceptions to the structure. Building a mental model of where those rules apply is challenging, it harms readability, it's less a document and more of a serialised program.
Unfortunately I don't have a good solution, documents are naturally less flexible than programs, and programs are naturally less readable than documents.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There are a couple of reasons I've stuck with the "here's an example" technique rather than the "define the types" technique. One is that pact would have to randomly generate values for the response in the consumer project, and the request when verifying a pact, and randomly generated values are not great for the auto generated documentation. The second is that, as you say, you'd have to start specifying the lengths as well, or you'd get random errors if the generated string was too long. This would add complexity to both the definition and the code. I'm not discounting the idea entirely, but it's not the direction I've been heading in, after giving both concepts a good deal of thought.