ITV/scala-pact

Support for Pact Version 3

Opened this issue · 10 comments

The specification for v3 can be found here. The most notable inclusion is the support for message queues.

Pact v4 is WIP, so I’d suggest not bothering with it yet. From first glance (and I have only been reading the source code for a couple of hours) there is a lot of work required to support v3.

There are a few breaking changes between Pact v2 and v3. These stop the v3 examples in the pact-specs subproject from being parsed.

I believe there are two possible paths here. Add interfaces/implementations to be able to say “this is the behaviour for v3, rather than v2” OR convert v2 and v3 into/out-of an internal model when needed. I’m not currently sure which path would be better, but would probably opt to try for the latter as an internal model already exists and it seems like less work.

Either way, we need to define a pattern for what's allowable in v2 versus v3.

All other changes for v3 seem to be additive, including the message queue support. There are a lot of other changes though, so this work needs splitting up into manageable chunks.

A prerequisite:

Scala-pact doesn’t currently look at the metadata block, which is where the pact-version would be described. We should add this first.

For example:

"metadata": {
    "pact-specification": {
        "version": "2.0.0"
    },
    "pact-jvm": {
        "version": "3.2.11"
    }
}

It seems as though there is already an issue to add the metadata: #84

Morning,

Thanks for doing all that, I've reviewed it and most of the rest of the V3 page - there are a couple of other gotchas too like the changes of the Jsonpath support.

Everything you've listed above does need to be done to support V3, but most of it is a fairly boring (and hard) reworking of the core functionality. I hate to say it but you'll probably have to leave me to it.

There is however some entirely separate work which is more interesting and is not particularly blocked by any of the above (if you can be a bit creative): Adding the ability to write and run consumer tests. I think the flow is:

  1. Write your test using a slightly different DSL
  2. Run your client code in a test which sends a message to a running queue
  3. The framework then pulls down the message from the queue (there should only be one), Acks it and checks it (right now, you could ignore the matching logic entirely and just do a straight string match only sending trivial messages)

The DSL needs to do the same job of defining the scenario (try and keep to the current style if possible - feel free to improve both though!), and organise the stub queue's config.

The Stub queue should ideally be an in-memory thing we can add as an SBT dependancy - I'm not a fan of requiring people to know how to setup a running local RabbitMQ. We might have to, but lets try not to, I'd rather everything just magically worked when you checked out the project and ran sbt test so that Junior devs don't face a wall of red through no fault of their own.

As I say, you can cunningly side step the matching logic for now. Or even don't, as long as you avoid matchers and do straight comparisons you should fine you can just use the body matching logic to compare two json structures. I'd start with strings and work up though!

The only burning question for me is whether we organise the SBT 1.x thing before you go too far down this rabbit hole. But then, it shouldn't be too hard to move over, just try and do the minimum, think PoC not production ready.

Thoughts?

Dave

I was hoping you’d say “leave it to me” as I was a starting to become concerned about the amount of work required! :)

To clarify what you meant by the separate work, is this for the scalapact-scalatest project, and is essentially a message-based version of runConsumerTest? If that is correct, using one of the answers from this Stack Overflow question could be used to provide an embedded message queue.

Although it’s probably worth noting that Pact doesn’t say AMQP only - it is for any message queue… so perhaps this is overkill? Or maybe just one way of doing it? The DSL could provide a hook to get the message defined in a contract, for the user to place on a queue themselves, before the runConsumerTest happens?

@cjwebb @davesmith00000 has any progress been made here?

I'd like to start helping out with this effort. Going to try to understand what exactly is involved here as I know a lot has changed recently. @jbwheatley @davesmith00000 are these still the only applicable tickets? Or do you foresee the need for more? https://github.com/ITV/scala-pact/issues?q=is%3Aissue+is%3Aopen+label%3A%22Pact+V3+Roadmap%22

I'd also like to help out for supporting Pact V3. I don't know much about the codebase nor the actual Pact specifications for now but happy to learn more about it. How may I help?

hey @gaeljw. From my perspective, I think the long and the short of it is that V3 support is not going to happen for ScalaPact. I would direct people to https://github.com/jbwheatley/pact4s instead which already has V3 support due to it wrapping pact-jvm.

Thanks for the quick answer @jbwheatley, does this mean that somehow ScalaPact derived from Pact specifications and it cannot fit into newer Pact specifications versions?

I'm just starting to use Pact and before using it on a large Scala codebase I'm wondering if ScalaPact is a good move then?

(I'll have a deeper look to pact4s anyway)

Too much has changed between v2 and v3 for it to be easy to migrate ScalaPact, and imo it is a fruitless task when the work has already been done by pact-jvm, which is why I would push newcomers towards using pact4s instead.

Agreed. IMO the documentation of this repository should be updated to reflect that this project will likely not be updated past the V2 specification, and this issue can then be closed in favor of pact4s (our company has also moved to using pact4s over scala-pact).