pact-foundation / pact-php

PHP version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project
Apache License 2.0
273 stars 92 forks source link

Pact Version 3 support #29

Closed DerManoMann closed 1 year ago

DerManoMann commented 6 years ago

Just a question if this is planned or already happening?

mattermack commented 6 years ago

I'll more or less paste my answer I posted on issue #27.

There are lots of plans. Keeping in mind, I original ported the Pact.Net 1.1 solution, which did not call Ruby. I'd say I based my entire knowledge of Pact from that implementation. My expertise tends to follow PHP, .Net, JS, then R in that order. The day I finished Pact.Php 1.0, the .Net solution released Pact 2.0 support. I really needed Matcher support for my organization. Thus, I wrote the base of PHP Pact 2.0 support on two long airplane rides (I got some odd looks as we all do). My main concern at the time is that PHP's external calls are finicky. Sometimes, you need to make exec, sometimes new COM("WScript.Shell"); on different versions of Windows. Let's say I have a history.

Looking back, I should have started PHP Pact 2.0 using Ruby. I also do not want to waste that effort if the Rust implementation is around the corner. Should have happened and will happen. The question is when. Next up, I desperately need AMPQ and/or ZMQ support in both the .Net and PHP versions. I was thinking about making two different libraries that could ideally be merged into Pact-PHP and Pact.Net when they support Pact 3.0 specifications. I'd like to do both of these by the end of the year. This is probably the wrong format for my response but through it all out there.

mattermack commented 6 years ago

@DerManoMann ,

Out of curiosity, is there a feature or feature set you are looking for in 3.0? I'm particularly interested in the Message Bus specification. I could certainly use some help there.

bethesque commented 6 years ago

I'm looking at exposing the v2 pact matching via a CLI - that could be used to give you a leg up on the message queue stuff.

DerManoMann commented 6 years ago

@mattermack Not really a feature - I am having problems with the providerState which is required by the library. The broker we are using fails on those pact files (empty or null value is fine!!). We use both Java and PHP and the Java projects generate v3 pact files. I was kinda hoping that might perhaps fix the problem....

bethesque commented 6 years ago

@DerManoMann can you clarify what you mean by "The broker we are using fails on those pact files"? Do you mean the broker fails to render it in HTML? Can you raise an issue in the pact_broker repository then.

DerManoMann commented 6 years ago

Yeah, I thought about that - I do not know enough about the specs to judge this, but having a behaviour where all values other than non-empty string work does not seem right :)

mattermack commented 6 years ago

Reopening as this should be the issue when it is supported (comment earlier on has reference on the state)

arkonchik commented 6 years ago

Can you answer, please, when pactV3 will approximately supported?

bethesque commented 6 years ago

Unfortunately it is dependent on pact v3 being done in the ruby implementation. I've added the pact message support, but I haven't added any of the new matchers. @arkonchik which feature of v3 are you after?

bethesque commented 6 years ago

Oh, I've just seen your other post @arkonchik . @mattermack, @mefellows and I can help you out with adding the message support.

mattermack commented 6 years ago

Thanks. I'll be traveling for a bit. I was originally thinking of implementing something outside of the implementation like https://github.com/Mattersight/pact-net-messages. If the ruby conversion is further along when this starts, the better. @arkonchik , we do not have implementation timeline, other than soon. I personally have a need to get PHP up to V3 with messages like the related .Net implementation but would like to be more inline with the rest of the community. So ... soon :)

bethesque commented 6 years ago

We've already got a pact message beta out for javascript and go using the ruby standalone. There's really quite a small amount of work that needs doing to integrate it into another language.

arkonchik commented 6 years ago

@bethesque you guessed. I need message queue support. I can try to help with this too.

arkonchik commented 6 years ago

@bethesque How can I help with message queue support?

bethesque commented 6 years ago

@arkonchik I've done a bit of a brain dump here: https://github.com/pact-foundation/pact-message-demo

But there is so much to explain, that writing it down would take me ages. Perhaps we could have an online catch up where we could discuss it "in person" with @mattermack and @mefellows?

mefellows commented 6 years ago

Would love to discuss this in "person" too :)

FWIW I've added some more notes to the original POC gist: https://gist.github.com/bethesque/c858e5c15649ae525ef0cc5264b8477c#gistcomment-2596746

It's far from a guide, but hopefully will be handy.

On Tue, May 22, 2018 at 11:02 AM, Beth Skurrie notifications@github.com wrote:

@arkonchik https://github.com/arkonchik I've done a bit of a brain dump here: https://github.com/pact-foundation/pact-message-demo

But there is so much to explain, that writing it down would take me ages. Perhaps we could have an online catch up where we could discuss it "in person" with @mattermack https://github.com/mattermack and @mefellows https://github.com/mefellows?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pact-foundation/pact-php/issues/29#issuecomment-390830114, or mute the thread https://github.com/notifications/unsubscribe-auth/AADSjKcycJ5XzSvsX3qRARS1-DjStMsBks5t02OSgaJpZM4Qv6GA .

-- Matt Fellows

mefellows commented 6 years ago

Here is the pact message consumer diagram:

  1. Test case sets up the interaction, and accepts a message consumer that should be able to handle the message
  2. Test case invokes Verify on the wrapper language
  3. Wrapper may optionally reach out to pact-message to reify the data structure back into its generated form (i.e. strip out all of the matchers etc.)
  4. Wrapper then invokes the message consumer
  5. If the consumer errors, it fails the test
  6. If the consumer passes, it calls pact-message update to save the pact.

I can add this to your repo if you like Beth?

On Tue, May 22, 2018 at 5:51 PM, Matt Fellows matt.fellows@onegeek.com.au wrote:

Would love to discuss this in "person" too :)

FWIW I've added some more notes to the original POC gist: https://gist.github.com/bethesque/c858e5c15649ae525ef0cc5264b847 7c#gistcomment-2596746

It's far from a guide, but hopefully will be handy.

On Tue, May 22, 2018 at 11:02 AM, Beth Skurrie notifications@github.com wrote:

@arkonchik https://github.com/arkonchik I've done a bit of a brain dump here: https://github.com/pact-foundation/pact-message-demo

But there is so much to explain, that writing it down would take me ages. Perhaps we could have an online catch up where we could discuss it "in person" with @mattermack https://github.com/mattermack and @mefellows https://github.com/mefellows?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pact-foundation/pact-php/issues/29#issuecomment-390830114, or mute the thread https://github.com/notifications/unsubscribe-auth/AADSjKcycJ5XzSvsX3qRARS1-DjStMsBks5t02OSgaJpZM4Qv6GA .

-- Matt Fellows

-- Matt Fellows

mefellows commented 6 years ago

Added :)

On Tue, May 22, 2018 at 6:41 PM, Matt Fellows matt.fellows@onegeek.com.au wrote:

Here is the pact message consumer diagram:

  1. Test case sets up the interaction, and accepts a message consumer that should be able to handle the message
  2. Test case invokes Verify on the wrapper language
  3. Wrapper may optionally reach out to pact-message to reify the data structure back into its generated form (i.e. strip out all of the matchers etc.)
  4. Wrapper then invokes the message consumer
  5. If the consumer errors, it fails the test
  6. If the consumer passes, it calls pact-message update to save the pact.

I can add this to your repo if you like Beth?

On Tue, May 22, 2018 at 5:51 PM, Matt Fellows <matt.fellows@onegeek.com.au

wrote:

Would love to discuss this in "person" too :)

FWIW I've added some more notes to the original POC gist: https://gist.github.com/bethesque/c858e5c15649ae525ef0 cc5264b8477c#gistcomment-2596746

It's far from a guide, but hopefully will be handy.

On Tue, May 22, 2018 at 11:02 AM, Beth Skurrie notifications@github.com wrote:

@arkonchik https://github.com/arkonchik I've done a bit of a brain dump here: https://github.com/pact-foundation/pact-message-demo

But there is so much to explain, that writing it down would take me ages. Perhaps we could have an online catch up where we could discuss it "in person" with @mattermack https://github.com/mattermack and @mefellows https://github.com/mefellows?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pact-foundation/pact-php/issues/29#issuecomment-390830114, or mute the thread https://github.com/notifications/unsubscribe-auth/AADSjKcycJ5XzSvsX3qRARS1-DjStMsBks5t02OSgaJpZM4Qv6GA .

-- Matt Fellows

-- Matt Fellows

-- Matt Fellows

arkonchik commented 6 years ago

Yes, we can try to discuss online if my english level will enough.

mattermack commented 6 years ago

FYI, I started flushing out message support. Definitely WIP

https://github.com/pact-foundation/pact-php/tree/feat/message-pact

mefellows commented 6 years ago

nice! 👍

On Sat, Jun 30, 2018 at 2:00 AM, mattermack notifications@github.com wrote:

FYI, I started flushing out message support. Definitely WIP

https://github.com/pact-foundation/pact-php/tree/feat/message-pact

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pact-foundation/pact-php/issues/29#issuecomment-401398643, or mute the thread https://github.com/notifications/unsubscribe-auth/AADSjGqZriEbFEbeTMyaPXQam3ZV9yEdks5uBk8JgaJpZM4Qv6GA .

-- Matt Fellows

mattermack commented 6 years ago

I have a first draft of the consumer pact creation leveraging pact-message ruby classes: https://github.com/pact-foundation/pact-php/tree/feat/message-pact

To follow up on:

  1. Currently only allows one message per pact - perhaps craft a listener to this somehow
  2. Research why pact-message is returning contents: null
  3. Implement provider side
  4. Update readme and create better examples from rabbit

@nbrink91, want to take a peek at the implementation? I need another set of eyes.

mefellows commented 6 years ago

Nice one @mattermack!

  1. Do you mean per pact file, or per "test case"? I haven't been able to think of a good use case where you would want to allow multiple messages in a test case.
  2. When is pact-message returning contents null - in reification?

On Sat, Jul 7, 2018 at 7:15 AM, mattermack notifications@github.com wrote:

I have a first draft of the consumer pact creation leveraging pact-message ruby classes: https://github.com/pact-foundation/pact-php/tree/feat/ message-pact

To follow up on:

  1. Currently only allows one message per pact - perhaps craft a listener to this somehow
  2. Research why pact-message is returning contents: null
  3. Implement provider side
  4. Update readme and create better examples from rabbit

@nbrink91 https://github.com/nbrink91, want to take a peek at the implementation? I need another set of eyes.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pact-foundation/pact-php/issues/29#issuecomment-403148695, or mute the thread https://github.com/notifications/unsubscribe-auth/AADSjMX8iYOaJAuc9ML06mmonYquLe7Rks5uD9NVgaJpZM4Qv6GA .

-- Matt Fellows

mefellows commented 6 years ago

Ah, I see https://github.com/pact-foundation/pact-ruby-standalone/issues/20#issuecomment-403162767. Ignore #2. I do seem to remember getting this myself, but it was the content vs contents field problem, which seems to be correct glancing at your code.

cfmack commented 6 years ago

For #1, the way I have it written, if a consumer and provider pair shared more than one message, the entire pact would need to be written by a single phpunit class. I could see this being a hindrance.

On Fri, Jul 6, 2018, 10:25 PM Matt Fellows notifications@github.com wrote:

Ah, I see pact-foundation/pact-ruby-standalone#20 (comment) https://github.com/pact-foundation/pact-ruby-standalone/issues/20#issuecomment-403162767. Ignore #2 https://github.com/pact-foundation/pact-php/pull/2. I do seem to remember getting this myself, but it was the content vs contents field problem, which seems to be correct glancing at your code.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/pact-foundation/pact-php/issues/29#issuecomment-403184979, or mute the thread https://github.com/notifications/unsubscribe-auth/AAZX6Ia5BUf-nh82v37eMeQ9_G_7Nft2ks5uECoegaJpZM4Qv6GA .

mattermack commented 6 years ago

Updated list of to-dos (because lists are fun to cross off)

  1. Currently only allows one message per pact - perhaps craft a listener to this somehow
  2. Research why pact-message is returning contents: null
  3. Implement provider side 3.1. Implement provider proxy service 3.2. Attempt to move from Amp\Monolog in Provider implementation to Symphony's PSR log 3.3. Move much of the hard coded values to a config
  4. Create better examples from rabbit 4.0. Better example on metadata when publishing directly to a queue or an exchange 4.1. Multiple unit test functions in a single test case writing to the same consumer-provider pair 4.2. Multiple files with single unit test per test case writing to the same consumer-provider pair
  5. Update readme with better examples 5.1 Is there a better way of getting metadata about the queue/routing_key into the pact? The current examples stinks.
mattermack commented 6 years ago

After attempting React and spatie/async for days, I finally got Amp Async to work as all others appear to have limited Windows support for async processes.

cfmack commented 6 years ago

Update: at the Ruby version is at the appropriate mock level, where we do not fully support the entire Pact Specification 3 but do support Message implementations.

johnsnowderomania commented 5 years ago

!up

Thomblin commented 5 years ago

@mattermack Is the todo list up to date? What is the top priority?

cfmack commented 5 years ago

New todo list:

  1. If the Ruby version support this, we need to update [query strings as maps/arrays](https://github.com/pact-foundation/pact-specification/tree/version-3#query-strings-are-stored-as-map-instead-of-strings}
  2. Allow multiple provider states with parameters. This will be extremely difficult to do with the message broker implementation but the HTTP version should be pretty straight forward
  3. Allow arrays of matchers to be defined against a matcher path
  4. Drop the Jsonpath notation for matchers
  5. Add an equality matcher
  6. Add an include matcher
  7. Add an minmax matcher
  8. Add more specific type matchers
  9. Introduce example generators (not sure if this is needed for the spec or not)
  10. Content-Type header matching should include parameters in the matching

Basically, the full implementation includes a bunch of fixes for the HTTP implementation. The current v3 functionality that I implmeneted has been solely focused on message brokers. On the message broker side, I believe all we need are more examples.

You've been great and I appreciate your PRs! The last time I looked at the Ruby implementation, we did not seem to have the full v3 spec down. I believe that implementation is ready to go and full steam ahead.

Update: it looks like Ruby supports validating v3 specs but not creating the yet. https://github.com/pact-foundation/pact-ruby#current-pact-specification-version

Thomblin commented 5 years ago

I would like to begin with introducing the new matchers. Where can I find the syntax that shall be used to push the expected response to the mock service with POST /interactions?

frastel commented 5 years ago

About the messaging: I checked the source for v3 and of course the v3 specification itself. I totally do not understand why a server has to be executed during the message verification. I might got something totally wrong but I try to explain my understanding of the process.

The v3 specification of a message is only about the contents of a message NOT how a message is send over the net nor which message broker or queue is used. Thus defining metadata is totally not needed. I think we only need to test the behaviour of the provider class itself without any running server.

The workflow would be:

Lets take the example from the README (metadata has already be removed here).

{
  "consumer": {
    "name": "test_consumer"
  },
  "provider": {
    "name": "test_provider"
  },
  "messages": [
    {
      "description": "footprints dressed in red",
      "providerStates": [
        {
          "name": "You can hear happiness staggering on down the street"
        }
      ],
      "contents": {
        "song": "And the wind whispers Mary"
      },
      "matchingRules": {
        "body": {
        }
      }
    }
  ],
  "metadata": {
    "pactSpecification": {
      "version": "2.0.0"
    }
  }
}
class SomeProvider {
    public function __construct(Song $song) {}

    public function run(){
        return \json_encode(['song' => $song->getName(), 'untestedProperty' => 'bar']);
    }
}

That's it.

In the verification process you just execute the according callback for the provider state. The return value of the callback is the output of the provider instance.

Again let's take the example from the README

        $callbacks = array();

        // a hello message is a provider state / given() on the consumer side
        $callbacks["You can hear happiness staggering on down the street"] = function() {

            $provider = (new SomeProvider(new Song('foo')))
            return $provider->run();
        };

        $verifier = (new MessageVerifier($config))
            ->setCallbacks($callbacks)
            ->verifyFiles([__DIR__ . '/../../output/test_consumer-test_provider.json']);

The only thing you have to do now is to check if the response of $provider->run() returns expected rules.

You only speak with classes not with servers for generating and verify the pact.

What do you think?

mefellows commented 5 years ago

The only thing you have to do now is to check if the response of $provider->run() returns expected rules. You only speak with classes not with servers for generating and verify the pact.

This is exactly how Pact JS and Pact Go does it (and probably Pact JVM). See https://github.com/pact-foundation/pact-js#asynchronous-api-testing for an example, we just need to pass the function to the runtime that needs to be executed.

I won't speak for the PHP implementation, but wanted to let you know that your proposal was consistent with at least other approaches.

frastel commented 5 years ago

Ok, thank you @mefellows for your feedback. I'll check other implementations and consider to refactor the implementation in pact-php.

agrosner commented 1 year ago

Has Specification 3 been implemented as of 8.X?

mefellows commented 1 year ago

Not yet, see https://github.com/pact-foundation/pact-php/pull/270.

YOU54F commented 1 year ago

For any readers you can find a alpha release with this functionality available to test

https://github.com/pact-foundation/pact-php/releases/tag/10.0.0-alpha1

along with links to instructions for migrating, using and contributing in the release notes.