uuid: - value: cbfe0f07-d0fc-46d0-950f-167a091e020d langcode: - value: en type: - target_id: daily_email target_type: node_type target_uuid: 8bde1f2f-eef9-4f2d-ae9c-96921f8193d7 revision_timestamp: - value: '2025-05-11T09:00:34+00:00' revision_uid: - target_type: user target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849 revision_log: { } status: - value: true uid: - target_type: user target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849 title: - value: | Testing multiple implementations with contract tests created: - value: '2023-08-24T00:00:00+00:00' changed: - value: '2025-05-11T09:00:34+00:00' promote: - value: false sticky: - value: false default_langcode: - value: true revision_translation_affected: - value: true path: - alias: /daily/2023/08/24/testing-multiple-implementations-with-contract-tests langcode: en body: - value: |

If you have multiple implementations of a service, as I mentioned in yesterday's email, you need to ensure they all provide the same functionality.

You need to be able to run the same tests against each implementation and have them pass.

How do you do this?

In PHP, I use a trait that contains the test methods and then have a test class for each implementation that uses the trait and sets up any test data.

Then, each test class will run the methods from the contract test trait and ensure they all provide the same behaviour, regardless of how it does so - whether it communicates with an API, uses an SDK, or returns fake values.

If one implementation doesn't return the same result as the others, its test will fail.

If you add a new implementation, you create a new test class, use the trait and get the tests to pass.

format: full_html processed: |

If you have multiple implementations of a service, as I mentioned in yesterday's email, you need to ensure they all provide the same functionality.

You need to be able to run the same tests against each implementation and have them pass.

How do you do this?

In PHP, I use a trait that contains the test methods and then have a test class for each implementation that uses the trait and sets up any test data.

Then, each test class will run the methods from the contract test trait and ensure they all provide the same behaviour, regardless of how it does so - whether it communicates with an API, uses an SDK, or returns fake values.

If one implementation doesn't return the same result as the others, its test will fail.

If you add a new implementation, you create a new test class, use the trait and get the tests to pass.

summary: null field_daily_email_cta: { }