Heya, I hope I have the right channel for this. I...
# general
k
Heya, I hope I have the right channel for this. I am trying to introduce (consumer driven) contract testing in our company, and picked a frontend and backend service as a pilot, but I seem to run into a chicken-egg problem, because they are already sharing an openapi spec file between them. And the frontend uses this file to generate the backend calling code. For the sake of example and to test my knowledge, lets forget the existance of the openapi file for a sec, and look at a scenario where the frontend is building a new feature that requires a new endpoint of the backend. If I understand the concept of consumer driven correctly, then it should look something like: 1: Frontend creates a new feature, and add some point during development reaches the point where they require the new backend call to get some data. 2: Frontend creates a new consumer test, in which they stub the backend in a way that they would like to receive the data. 3: When the test passes, a new contract is created containing the new endpoint, and data they expect to receive (the interaction) 4: Frontend pushes the contract to the broker 5: Backend pulls the contract from the broker, provider test fails, and implements the endpoint according to the expected result. 6: Once the provider test passes, both consumer and provider proceed to merging and deploying their changes. First of all, is my understanding so far correct? Now back to the usage of an openapi spec. Where I struggle in this specific case, is that the consumer uses the openapi spec to generate their backend calling code. If it is up to the consumer to write a consumer test first, how can they do that when they depend on the spec file to generate the calling code? The frontend cant write a test without the openapi file, but the backend cant provide the new openapi file without a new contract first. How do you transition from a 'provider first' to a 'consumer first' way of working when they were already sharing openapi file? The only thing I can think of is that the frontend first manually writes some temporary backend calling code, and uses that in the test. New contract is generated and pushed, backend pulls, implements, and sends the new openapi spec back to the frontend, where they then generate the new backend code, and replaces the temporary code with the generated one. But that seems very cumbersome and a very tough sell. When theyre already using openapi, perhaps the most logical answer would be to use bidirectional testing? But we are specifically looking into consumer driven, because we want to do value specific asserts. And bidirectional only does structural asserts right?
y
I would drive all changes via the OpenAPI then for spec first development. If consumer team needs something new in the openapi that doesn’t exist, they propose the change via an openapi. we’ve done this previously by verifying compliance of contracts with openapi spec prior to publishing, by checking out a feature branch version of the openapi if it exists or defaulting to main. we then used full fat CDCT testing on the verifier side. documented this a while back https://blog.you54f.com/2019/02/19/protecting-your-api-development-workflows-with-swagger-openapi-pact-io/
1: Frontend creates a new feature, and add some point during development reaches the point where they require the new backend call to get some data.
2: Frontend creates a new consumer test, in which they stub the backend in a way that they would like to receive the data.
3: When the test passes, a new contract is created containing the new endpoint, and data they expect to receive (the interaction)
4: Frontend pushes the contract to the broker
5: Backend pulls the contract from the broker, provider test fails, and implements the endpoint according to the expected result.
6: Once the provider test passes, both consumer and provider proceed to merging and deploying their changes.
First of all, is my understanding so far correct?
Yes that looks correct, although after step 4, if the contract has not been verified before (ie contents changed from last time it was verified), this will trigger a webhook to trigger providers ci build to verify a specific pact, against certain versions of the provider code (head of main branch, any deployed or released versions). for step6, provider would probably need to merge first depending on change (if they add something new). this may differ depending on scenario, and how you approach it, expand and contract to avoid a downtime scenario in case of a breaking change which you can do gracefully)
does your provider generate their openapi from code, or go spec first and create it prior to the implementation?
k
Working collaboratively on the spec file first seems like a good solution. But its new to me so I cant tell right away how or if it works for us. But I did some asking around, and I believe were already doing that (for the most part?). What they do is: • Create/edit their spec file first (in the backend repository) • With this spec file they generate the backend java interfaces • Implement the interface • Whenever the code (and spec file) is committed to source control, the spec file is also pushed to an npm repository • Frontend then can pull the spec file from the repository, and (re)generate their client code from there So I think that in this specific case, changes to the spec file is done in the backend repository. If we can find a solution where the frontend can also edit the spec file, then were nearly there right?