Mapping
- Source-to-target mapping per table
- Transformation rules with examples
- Grain of each fact table
- Key and surrogate key rules
A dashboard nobody trusts is worse than no dashboard. Agnotic Technologies tests data warehouses and their reports so every figure can be traced back to source rows, and turns each check into a regression test that runs on every release.
Trusted by global innovators
























DW and BI testing
Data warehouse testing checks that the numbers in a warehouse and its reports match the source systems: every row arrived, every transformation rule did what the mapping says, history was kept correctly and each dashboard figure can be traced back to source rows. Agnotic Technologies runs it as a QA engagement for ETL, ELT and BI releases.
We test warehouses other teams built as well as our own. Building pipelines is our data engineering work, and validation rules inside live healthcare feeds are in our data validation checklist; this page is the testing around a release.
The test basis is the source-to-target mapping. If it is missing or out of date, writing it down is the first deliverable, because a test without an expected result is only a query.
Checklist
The test types we plan for every release, what each one catches and an example of the check behind it.
| Test type | What it catches | Example check |
|---|---|---|
| Completeness | Rows dropped by filters, failed loads or late files | Source rows for the load batch equal target rows plus rows logged as rejected |
| Aggregate reconciliation | Amounts that drift in joins or in currency and unit conversion | Sum of order value by day and store matches between the source and the fact table |
| Transformation rules | Mapping logic coded differently from the specification | Each source status code lands as its mapped value, and no unmapped values exist |
| SCD Type 2 history | Overwritten history, overlapping or missing validity dates | Each business key has exactly one current row and no two versions overlap in time |
| SCD Type 1 | Old values kept where they should be replaced | After a correction load the dimension holds only the corrected value |
| Referential integrity | Facts that point to missing dimension rows | Every foreign key in the fact table finds a dimension key or the agreed unknown member |
| Report filter and security | Dashboards that hide, double count or expose rows | A region's dashboard total equals the warehouse query for that region, viewed as that region's role |
Each check is written as a query with an expected result, so it runs again in every release.
Report-to-source tracing
The steps we follow when a number on a report is questioned. For key figures we automate the same steps.
The report, the measure, the filters and the user role, exactly as the person saw them.
The formula in the semantic model, the tables it reads and any row-level security on that role.
Query the fact and dimension tables directly with the same filters and compare the result.
Compare the curated, staging and raw layers for the rows behind the figure, using the mapping document.
Pull the same records from the source and explain every difference: timing, rejects or a rule.
Keep the queries and expected results so the figure is checked automatically on every release.
Big data testing
Big data testing for Spark and streaming pipelines adds checks that a small fixture cannot show: quality thresholds with a quarantine table, late, duplicate and out-of-order events, replay from a checkpoint, a stream reconciled against its source and a sustained run at production rate. Agnotic Technologies runs these alongside the job's own unit tests.
| Test | What it catches | When it runs |
|---|---|---|
| Data quality expectations with thresholds | Null rates, duplicate keys or values outside agreed ranges; failing rows go to a quarantine table for review instead of the target | Inside every pipeline run, with the run stopped when a threshold is crossed |
| Late events | Windows that close before late events arrive, or that drop events inside the agreed lateness | On a test stream with scripted event times, before each release |
| Duplicate events | Double counts when a producer retries or a source resends a batch | On the same test stream, with known duplicates injected |
| Out-of-order events | Results that change with arrival order, such as a status that ends on an older value | On the same test stream, with events shuffled |
| Replay from a checkpoint | A restarted job that skips or repeats data, or a query change the old checkpoint does not accept | After any change to state, windows, keys or sinks |
| Stream reconciliation | Counts and totals per window that drift from the source table over hours or days | Continuously in staging, and as a scheduled check in production |
| Sustained run at production rate | Consumer lag that grows, state that keeps expanding and checkpoints that slow down | Before major releases, on masked data |
Results are reported per row, because each one points to a different fix. Streaming architecture itself is covered on our real-time data warehouse page.
Test basis
The documents and access we collect before writing the first test.
Failure points
Defects we find most often, and the test that catches each one.
Challenge
A late file loads after the nightly reconciliation has already passed.
Agnotic approach
Reconciliation runs per load batch with the batch ID recorded, not once per night.
Challenge
A Type 2 dimension adds a version on every load because a timestamp column changes.
Agnotic approach
Tests check that new versions appear only when tracked attributes change.
Challenge
A source schema change silently turns a column into nulls.
Agnotic approach
Not-null and accepted-value tests on critical columns fail the release before reports refresh.
Challenge
A many-to-many join doubles revenue in one report.
Agnotic approach
Grain tests check one row per key, and aggregate reconciliation against the source catches the doubling.
Challenge
Row-level security hides rows from the people testing the report.
Agnotic approach
Reports are tested as each role, using a role matrix agreed with the data owner.
Challenge
Test data is a copy of production with real customer details.
Agnotic approach
Masked or synthetic test sets that keep keys and edge cases but not identities.
Test data
Good warehouse tests need realistic data. These are the rules we follow.
When to test
The moments when an independent look at the numbers pays off.
Parallel runs of the old and new warehouse, reconciled by table and by key figure.
Report-by-report comparison when dashboards move to a new tool or semantic model.
A trace of the disputed figures, then regression tests so the dispute does not come back.
Evidence that reported figures match source records, kept with each release.
Tests your team runs in CI, written in the tools you already use, such as SQL or dbt tests.
A short list of checks on the figures investors and the board see most.
Methods
We write tests in the tools your team already runs wherever we can.
Tool behavior our tests rely on, each linked to the vendor's own documentation.
dbt ships with four generic data tests: unique, not_null, accepted_values and relationships, the last of which checks referential integrity between tables.
Source: dbt documentation: Add data tests to your DAGdbt snapshots implement Type 2 slowly changing dimensions over mutable source tables, recording each version of a row with dbt_valid_from and dbt_valid_to columns.
Source: dbt documentation: Add snapshots to your DAGIn Power BI, a row-level security role filters rows with a DAX expression, and Microsoft advises using the View as role feature to check a filter returns the expected rows before publishing.
Source: Microsoft Learn: Row-level security with Power BIA Spark Structured Streaming query restarted after a failure or shutdown recovers from its checkpoint location, which saves the offsets processed and the running aggregates, and some query changes are not allowed between restarts from the same checkpoint.
Source: Apache Spark, Structured Streaming Programming GuideIn Spark Structured Streaming, a watermark is set from an event time column and a lateness threshold: late data within the threshold is still aggregated, and data later than the threshold starts to be dropped.
Source: Apache Spark, Structured Streaming Programming GuideScope and cost
We do not publish prices. These drive the size of an engagement.
How many source systems feed the warehouse and how many tables are in scope.
Whether a current source-to-target mapping exists or has to be written first.
How many Type 2 dimensions and late-arriving data cases need tests.
How many key figures, dashboards and security roles we test.
One-off testing for a release, or a regression suite wired into your pipeline.
Whether masked or synthetic data sets exist, or need building.