Skip to content

feat: pact contract for get job by id and post job - #106

Open
duvanmoionq wants to merge 8 commits into
mainfrom
pact/contract
Open

duvanmoionq wants to merge 8 commits into
mainfrom
pact/contract

Conversation

@duvanmoionq

@duvanmoionq duvanmoionq commented Sep 9, 2026

Copy link
Copy Markdown

QTPF-9072

install pact dependency
Adding pact contract for http POST /job
Adding pact contract for http GEt /job/{id}

@duvanmoionq
duvanmoionq requested a review from a team as a code owner September 9, 2026 16:47
@antalszava
antalszava self-requested a review September 10, 2026 12:04
@antalszava

Copy link
Copy Markdown
Collaborator

Thank you @duvanmoionq! before a full review, a question: should the new tests be added to the CI too? or does pact work in a different way?

@duvanmoionq

Copy link
Copy Markdown
Author

Thank you @duvanmoionq! before a full review, a question: should the new tests be added to the CI too? or does pact work in a different way?

Yes! we would do that later for now we are only adding test contracts examples that we can follow to add more contracts. we will add later the CI logic whenever we configure the Broker we need.

@antalszava antalszava left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much @duvanmoionq! 👏 Very interesting direction.

I've left a couple of comments, my main feedback is: could we somehow dynamically depend on the API spec that we have in the repo in the pact?

Also, could you further describe what we gain from using pact instead of "simply" writing pytest tests with expected responses?

Comment thread tests/pact/consumers/test_jobs_api.py Outdated
@@ -0,0 +1,165 @@
"""Pact HTTP contract: ionq-core-python (consumer) -> cloud-job-manager (provider).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a convention to have a consumers folder inside the pact folder?

First it seems a bit unnecessary to have two levels of folder nesting atm.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's the convention we decided to follow in all the repos.

Comment thread tests/pact/consumers/test_jobs_api.py Outdated
"""Pact HTTP contract: ionq-core-python (consumer) -> cloud-job-manager (provider).

Pins the two jobs-API interactions the SDK depends on, in ONE pact
(ionq-core-python-cloud-job-manager.json):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mention of ionq-core-python-cloud-job-manager.json seems a bit confusing here since it's not a file in the repo - where does it live?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed that comment but I will keep cloud-job-manager-http because that's the name of the provider.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Pins the two jobs-API interactions the SDK depends on, in ONE pact
(ionq-core-python-cloud-job-manager.json):

1. POST /v0.4/jobs create a circuit job -> 201 {id, status, session_id}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint can have different inputs: single-circuit,multi-circuit, quantum function and qaoa function. Should that matter here/does that matter for the contract?

@duvanmoionq duvanmoionq Sep 17, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's very true. and that's the idea! so we can add contracts to cover all cases. but for now the idea of this PR is just to add an example, structure to follow.

Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Comment on lines +6 to +7
1. POST /v0.4/jobs create a circuit job -> 201 {id, status, session_id}
2. GET /v0.4/jobs/{id} fetch a completed job -> 200 (every SingleCircuitJob

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho these should be coming dynamically from this repo's API spec version. Accordingly, I think it would be good to remove/keep the endpoint and payload descriptions minimal here because they need to be changed here each time their spec changes.

Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Comment thread tests/pact/consumers/test_jobs_api.py Outdated
Comment on lines +164 to +165
PACT_DIR.mkdir(exist_ok=True)
pact.write_file(PACT_DIR, overwrite=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do these instructions do?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They create the consumer contract file(pacts/ionq-core-python-cloud-job-manager.json) that is published to the pact broker.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you! what is in the consumer contract right now? is it empty?

@duvanmoionq

Copy link
Copy Markdown
Author

Thank you so much @duvanmoionq! 👏 Very interesting direction.

I've left a couple of comments, my main feedback is: could we somehow dynamically depend on the API spec that we have in the repo in the pact?

Also, could you further describe what we gain from using pact instead of "simply" writing pytest tests with expected responses?

About dynamically depending on the API spec, I am no sure I follow what you mean, what do you have in mind?
For the gain using pact, this is not a simple test. it looks like a test but the main work is actually on the broker side, as an example this Repo is the consumer and the source of truth, so we create the contract of what the sdk expects for some cases like creating a job or getting some results, but the producer is the one that actually verifies and make sure the contract is complaying the expectation so every time someone creates a new change on the API, contracts will be verified on the broker and make sure they don't break this consumer contract. for more details there is a cool video here that allow you to understand better https://docs.pact.io/.

Comment thread tests/pact/consumers/test_jobs_get.py
@antalszava

Copy link
Copy Markdown
Collaborator

The PR is now looking good, just posting more on our discussion (once settled, this is looking great 👍).

About dynamically depending on the API spec, I am no sure I follow what you mean, what do you have in mind?

Right now, everything is hardcoded: there's a CREATE_PAYLOAD, CREATE_RESPONSE_BODY and GET_RESPONSE_BODY objects. Each time there's a change in the API that influences these hardcoded objects, they have to be updated too. On the other hand, the API spec data served at https://api.ionq.co/v0.4/api-docs (or more conretely in this repo, the content of https://github.com/ionq/ionq-core-python/blob/main/openapi.json) is meant to be the source of truth to what each API endpoint looks like - meaning that any change to the API is reflected there too (theoretically). What I mean is, can't we use for example the "examples" section of the API spec to pull in examples from there instead of creating a job payload programmatically in the test? Same for the responses.

For the gain using pact, this is not a simple test. it looks like a test but the main work is actually on the broker side, as an example this Repo is the consumer and the source of truth, so we create the contract of what the sdk expects for some cases like creating a job or getting some results, but the producer is the one that actually verifies and make sure the contract is complaying the expectation so every time someone creates a new change on the API, contracts will be verified on the broker and make sure they don't break this consumer contract. for more details there is a cool video here that allow you to understand better https://docs.pact.io/.

Do I understand it correctly, that on the broker side the expectations are coded up and then any consumer (ionq-core being one) can be tested using those contracts? What is the expectation coming from ionq-core to the provider?

@duvanmoionq

Copy link
Copy Markdown
Author

CREATE_RESPONSE_BODY

I see what you mean, but that will go against what pact said we should do, pact contracts needs to use payload for what the SDK really uses, open spec have many things that the SDK don't event use. so for example GET_RESPONSE_BODY uses matchers for fields we really use, and if any one change it on the consumer or the provider the contract will fail. that's why we do it that way. what we can do is that we can be more strict with the matchers we use on these payloads. for the case of create a job there are so many contracts we could implement.

and about his question
Do I understand it correctly, that on the broker side the expectations are coded up and then any consumer (ionq-core being one) can be tested using those contracts? What is the expectation coming from ionq-core to the provider?
It is the other side, consumers are the ones who set the expectation and the provider is the one that verify we meet the expectations for each consumer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants