How to Unit Test in BigQuery

Galaxy Glossary

How do I write and automate unit tests in BigQuery?

Unit testing in BigQuery isolates and validates SQL logic by comparing actual query results to expected outcomes directly inside the warehouse.

Sign up for the latest in SQL knowledge from the Galaxy Team!
Welcome to the Galaxy, Guardian!
Oops! Something went wrong while submitting the form.

Description

What is unit testing in BigQuery?

Unit testing in BigQuery runs small, deterministic SQL snippets that verify one transformation or calculation at a time. By checking actual results against expected rows inside the warehouse, you catch logic errors before dashboards break.

Why should I write tests?

Tests prevent regressions, document intent, and speed debugging when schemas or business rules change. They are essential for teams sharing queries or powering revenue-critical reports.

Which methods can I use?

Use native BigQuery scripting (DECLARE, CREATE TEMP TABLE, ASSERT) or wrappers like Dataform, dbt, and bqunit. Native scripts give full control; frameworks add orchestration and reporting.

How do I structure a test case?

1) Create a TEMP TABLE expected with hard-coded rows. 2) Build a TEMP TABLE actual using your production SQL. 3) Compare with EXCEPT DISTINCT or ASSERT. 4) Return zero rows or raise an error when mismatches exist.

Can I see a concrete example?

The example below ensures each Orders.total_amount equals the sum of its OrderItems. A non-zero mismatch count triggers an ASSERT failure.

How do I automate tests?

Store each test in a file, then run bq query --use_legacy_sql=false --script in CI (Cloud Build, GitHub Actions). Fail the pipeline when any script exits non-zero.

Best practices for BigQuery unit tests?

Keep fixtures tiny, cover edge cases, name tests after rules, clean up temp objects, and run tests locally before committing.

Why How to Unit Test in BigQuery is important

How to Unit Test in BigQuery Example Usage


-- Validate Orders.total_amount equals sum(OrderItems)
DECLARE test_name STRING DEFAULT 'order_total_accuracy';

CREATE TEMP TABLE expected AS
SELECT o.id AS order_id, o.total_amount
FROM `project.dataset.Orders` o
WHERE o.id IN (101,102);

CREATE TEMP TABLE actual AS
SELECT o.id AS order_id,
       SUM(oi.quantity*p.price) AS total_amount
FROM `project.dataset.Orders` o
JOIN `project.dataset.OrderItems` oi ON oi.order_id = o.id
JOIN `project.dataset.Products` p   ON p.id = oi.product_id
WHERE o.id IN (101,102)
GROUP BY o.id;

ASSERT (SELECT COUNT(1)
        FROM (SELECT * FROM expected EXCEPT DISTINCT SELECT * FROM actual)
       ) = 0
  DESCRIPTION 'Totals mismatch for sample orders';

How to Unit Test in BigQuery Syntax


-- BigQuery script template for a unit test
DECLARE test_name STRING DEFAULT 'order_total_matches_items';

-- 1. Expected rows
CREATE TEMP TABLE expected AS
SELECT 1 AS order_id, 220.00 AS total_amount
UNION ALL
SELECT 2, 150.00;

-- 2. Actual rows from production logic
CREATE TEMP TABLE actual AS
SELECT o.id AS order_id,
       SUM(oi.quantity * p.price) AS total_amount
FROM `project.dataset.Orders` o
JOIN `project.dataset.OrderItems` oi ON oi.order_id = o.id
JOIN `project.dataset.Products` p   ON p.id = oi.product_id
WHERE o.id IN (1,2)
GROUP BY o.id;

-- 3. Detect mismatches
CREATE TEMP TABLE mismatches AS
SELECT * FROM expected
EXCEPT DISTINCT
SELECT * FROM actual
UNION ALL
SELECT * FROM actual
EXCEPT DISTINCT
SELECT * FROM expected;

-- 4. Assert zero mismatches
ASSERT (SELECT COUNT(1) FROM mismatches) = 0
  DESCRIPTION CONCAT('Test failed: ', test_name);

-- 5. Optional success output
SELECT 'PASS' AS status, test_name AS test;

Common Mistakes

Frequently Asked Questions (FAQs)

Can I run tests against views?

Yes. Build the actual temp table with SELECT * FROM my_view. Views materialize during the test without affecting production.

How do I test time-partitioned tables?

Filter fixture queries to a small date range and set _PARTITIONTIME explicitly when inserting expected rows.

What happens when an ASSERT fails?

The script aborts, BigQuery returns a non-zero exit code, and CI marks the job as failed. The error message contains the description you supplied.

Want to learn about other SQL terms?

Trusted by top engineers on high-velocity teams
Aryeo Logo
Assort Health
Curri
Rubie Logo
Bauhealth Logo
Truvideo Logo
Welcome to the Galaxy, Guardian!
Oops! Something went wrong while submitting the form.