Integration testing checks the behavior of two or more connected components rather than testing each component in isolation. The components might be application modules, an API and a database, or an ingestion job and its storage destination. The central question is whether their interaction produces the expected result under realistic conditions. Successful execution alone is insufficient: tests must assert the correctness of outputs, state changes, and failure handling.
For a cloud data pipeline, a practical integration test might upload a small, versioned input dataset to object storage, start a transformation job, wait for completion, and query the destination. Assertions could check the output schema, record counts, decimal precision, timestamp conversion, partition placement, and treatment of invalid records. A second execution with the same input can verify that the pipeline's intended deduplication or idempotency behavior prevents unintended duplicate records.
Integration tests also exercise operational boundaries that isolated tests often miss. A job may contain correct transformation logic but fail because its execution role cannot decrypt an input object, its network configuration cannot reach a database, or its catalog definition does not match the stored data. Use identities and configuration representative of the deployed workload. Tests run with administrator permissions can conceal authorization defects that appear after deployment.
In continuous integration and continuous delivery, commit the tests, fixtures, dependency definitions, and infrastructure templates alongside the pipeline code in version control. Run fast unit tests and static checks first, then deploy the candidate artifact to an isolated test environment and execute integration tests. Make test failures block promotion, and promote the same tested artifact rather than rebuilding it with potentially different dependencies. Continuous delivery can retain a production approval step; continuous deployment automatically releases changes after the required gates pass.
Keep test runs independent by using dedicated resources or unique database schemas, object prefixes, and execution identifiers. Provision environments reproducibly with infrastructure as code, use synthetic or appropriately de-identified data, and remove temporary resources even when tests fail. For asynchronous processing, poll for a defined completion condition with a bounded timeout rather than relying on fixed sleeps. Account for the consistency and delivery guarantees of each dependency, including duplicate or out-of-order events where applicable.
Integration tests usually cost more and take longer than unit tests because they involve additional dependencies and sometimes billable cloud resources. Emulators and test doubles provide fast feedback, but cannot establish that actual cloud permissions, networking, or managed-service behavior are correct. A practical strategy combines focused local tests with a smaller suite against real deployed dependencies. Capture logs, execution identifiers, test reports, and relevant metrics so failures can be diagnosed; avoid indiscriminate retries that hide genuine defects.
Integration testing is not synonymous with every other automated test. Unit tests isolate a small piece of logic, whereas integration tests examine interactions. End-to-end tests usually exercise a complete workflow, and acceptance tests evaluate business acceptance criteria. User interface tests exercise presentation-layer behavior, while security scans look for vulnerabilities or insecure configurations. These categories can overlap, but none replaces the others. Likewise, production monitoring detects operational problems after release; it complements rather than replaces predeployment testing.