ETL testing verifies that data extracted from a source, transformed along the way, and loaded into a target ends up complete, accurate, and correctly transformed. It's easy to underrate because it doesn't look like traditional software testing. You're not testing whether a button works. You're testing whether a number that started in a source system still means the same thing by the time it lands in a report, after passing through joins, aggregations and business logic that can quietly change it.

The types of checks that make up ETL testing

  • Source-to-target count validation. Do the row counts reconcile, accounting for any intentional filtering? A silent drop in records between source and target is one of the most common and most missed failures.
  • Completeness testing. Are all the expected columns and records actually present in the target, not just some subset of them?
  • Transformation testing. Were the business rules applied correctly? If a transformation converts currency, buckets values into categories, or aggregates at a certain grain, the output needs to be checked against a known correct result, not just checked for existing.
  • Data quality testing within the pipeline. Nulls, duplicates, and format validity, checked specifically after transformation, since transformations themselves can introduce new quality issues that weren't in the source.
  • Referential integrity testing. Do the joins and foreign keys still resolve correctly after the load? A broken relationship here quietly orphans records or silently drops them from a join.
  • Regression testing. When the pipeline changes, does previously correct output stay correct? This is the check most manual processes skip entirely, and it's the one that catches a pipeline update that accidentally changes historical numbers.

Why manual ETL testing doesn't hold up

Manual testing is a reasonable way to first understand what needs checking. It's a bad long-term strategy, because every pipeline change means someone has to remember to re-run the same checks by hand, and eventually someone doesn't. The pipeline that broke silently and got noticed three weeks later almost always had a manual, not automated, test process behind it.

How to actually automate it

  • Write the checks as code, using whichever validation approach fits your team. See the comparison of Great Expectations, Soda, Informatica and custom Python for how to choose.
  • Run checks automatically as part of the pipeline, not as a separate manual step someone has to remember to trigger.
  • Compare source and target automatically, using row counts and, where it's feasible, checksums or hash comparisons, rather than spot-checking a sample by eye.
  • Build a small set of test datasets with known expected outputs specifically for transformation logic, the same way you'd unit test a function, so a transformation change gets caught the moment it produces a different result than expected.
  • Wire testing into CI/CD for the pipeline code, so a change to transformation logic gets tested before it ever reaches production, not after.

Done well, ETL testing is what turns "we moved the data" into "we moved the data and can prove it arrived correctly." That distinction is the entire point of the exercise.

Building this kind of test coverage into a pipeline is core to how I work.

See What I Do