dbt-bigquery against bqemulator¶
Runs a dbt build cycle (seed → run → test) against bqemulator
instead of real BigQuery, using dbt-bigquery's native endpoint
override path.
Pairs with the dbt integration guide.
What it demonstrates¶
- Pointing
dbt-bigqueryat the emulator usingBIGQUERY_EMULATOR_HOST(full URL including thehttp://scheme — dbt-bigquery forwards this verbatim intoclient_options.api_endpointandrequestsneeds the scheme to pick a connection adapter) + theoauth-secretsmethod with a placeholder bearer token (bqemulator accepts any token;oauth-secretsis the one auth path that does not contact Google's/tokenendpoint at startup). - One seed (
customers.csv), one staging model (models/staging/stg_customers.sql), one mart model (models/marts/dim_customers.sql), and dbt schema tests (not_null,unique). dbt buildruns end to end with no real-GCP credentials.
Version compatibility¶
The example tracks dbt-bigquery >=1.9,<1.11. Both 1.9 and 1.10
emit CREATE SCHEMA \proj`.`ds`two-part identifiers; the
bqemulator table-rewriter collapses those into a single"proj__ds"schema (matching what every other rewriter path
emits) so the SQL reaches DuckDB cleanly. Earlier passes mistakenly
pinned to<1.10chasing what looked like a dbt regression — the
actual cause was bqemulator's rewriter producing"proj__ds".""`
with an empty trailing identifier.
Layout¶
dbt_project.yml — project + model config
profiles.yml — emulator profile (endpoint, anonymous auth)
seeds/customers.csv — three rows of test data
models/staging/ — stg_customers.sql + schema.yml
models/marts/ — dim_customers.sql + schema.yml
macros/ — (none yet — placeholder for project macros)
run.sh — start emulator, run `dbt build`, tear down
Run¶
make test invokes run.sh, which:
- Spins up an ephemeral emulator on a random port via the
bqemulatorCLI (bqemulator start --ephemeral). - Exports
BIGQUERY_EMULATOR_HOSTsodbt-bigquery's endpoint resolution picks it up. - Runs
dbt deps && dbt build --profiles-dir . --target emulator. - Asserts a non-zero number of rows landed in
dim_customers. - Tears down the emulator.
What to look for¶
profiles.ymlusesmethod: oauth-secretswith a literal placeholder token (bqemu-fake-token). dbt builds a staticgoogle.oauth2.credentials.Credentialsfrom it and never calls Google's token endpoint — the bearer reaches bqemulator, which doesn't validate auth, and the call goes through.- The endpoint override is set via the
BIGQUERY_EMULATOR_HOSTenv var (the Google Cloud Python client libraries recognise it natively), prefixed withhttp://. dbt-bigquery forwards the value verbatim intoclient_options.api_endpoint, so the scheme must be present (the baregoogle-cloud-bigquerylibrary auto-injectshttp://but dbt's wrapper bypasses that branch). - No real GCP project, dataset, or billing is required.