BDD quickstart
Run your first Databricks-style Gherkin scenario locally, inspect its reports, and move the same feature to a real workspace.
This tutorial starts with no Databricks account, credentials, Python, or Fabric Experiments server. In about ten minutes you will run a real Gherkin scenario against local DuckDB and produce the same evidence formats used in CI. The last section moves that scenario to an isolated Databricks schema.
If you already maintain a Cucumber project, skip to Add Fabric to an existing suite. If you are evaluating Fabric against Behave, read the Behave migration guide after this tutorial.
What you will build
fx-bdd-evaluation/
├── cucumber.mjs
├── features/
│ ├── experiment-results.feature
│ └── support/
│ └── steps.ts
├── package.json
└── reports/ # created by the test runThe feature seeds a table, queries it, and checks its contents. Fabric creates and closes a scenario-isolated execution context automatically.
1. Check the prerequisites
Install Node.js 22 or newer and enable pnpm:
node --version
corepack enable
pnpm --versionYou do not need a JVM, Python, Docker, or a Databricks workspace for the local profile.
2. Create a project and install the published packages
The quickest supported path is the published fx scaffold:
npx @fabricorg/experiments@0.7.0 init databricks-tests fx-bdd-evaluation
cd fx-bdd-evaluation
pnpm install
pnpm testThat creates the package manifest, Cucumber configuration, support import, feature, fixture, and example environment file described below. To understand or add the pieces manually, continue with these commands:
mkdir fx-bdd-evaluation
cd fx-bdd-evaluation
pnpm init
pnpm add -D \
@cucumber/cucumber@13.0.0 \
@duckdb/node-api@1.5.4-r.1 \
@fabricorg/databricks-bdd@0.4.0 \
@fabricorg/databricks-testkit@0.2.4 \
tsx@4
mkdir -p features/support reportsAdd "type": "module" and these scripts to package.json:
{
"type": "module",
"scripts": {
"test:bdd": "cucumber-js",
"test:bdd:pretty": "cucumber-js --format pretty",
"test:bdd:wip": "cucumber-js --tags @wip --fail-fast --format summary"
}
}Pinning the versions makes an evaluation reproducible. After the first green run, adopt your normal dependency-update policy.
3. Configure Cucumber and reports
Create cucumber.mjs:
const common = {
paths: ['features/**/*.feature'],
import: ['features/support/steps.ts'],
parallel: process.env.DBX_TEST_PROFILE === 'live' ? 0 : 2,
}
export default {
...common,
format: [
'progress',
['junit', 'reports/bdd-junit.xml'],
['html', 'reports/bdd.html'],
['rerun', 'reports/rerun.txt'],
['@fabricorg/databricks-bdd/evidence-formatter', 'reports/evidence.json'],
],
}Local scenarios can run in parallel because each scenario owns its DuckDB context. Live scenarios stay serial by default because they can share governed workspace resources.
Create features/support/steps.ts:
import '@fabricorg/databricks-bdd/steps'That one import registers the Fabric World, lifecycle hooks, typed parameters, Databricks workload steps, cleanup, output capture, and failure evidence.
4. Write the first feature
Create features/experiment-results.feature:
Feature: Validate an experiment result table
Scenario: Treatment has the expected conversions
Given a table "experiment_results" with:
| variant_key | exposures | conversions |
| control | 100 | 12 |
| treatment | 100 | 18 |
When I query table "experiment_results"
Then the result has 2 rows
And the result contains rows matching:
| variant_key | conversions |
| treatment | 18 |The wording is standard Gherkin. Analysts can change examples and expected values without writing TypeScript. Platform engineers add TypeScript only when the team needs a new reusable action or assertion.
5. Run it locally
pnpm test:bddA successful run ends with one passed scenario and all listed Gherkin steps passing. It also creates:
| File | Use |
|---|---|
reports/bdd.html | Human-readable scenario and step report. |
reports/bdd-junit.xml | CI test annotation and test-history input. |
reports/evidence.json | Structured, schema-versioned audit evidence. |
reports/rerun.txt | Failed-scenario manifest for targeted reruns. |
Open reports/bdd.html in a browser. Then deliberately change 18 to 19
and rerun the feature. The failure report demonstrates the secret-redacted SQL,
statement identifier when live, and up to 32 KiB of captured step output. Put
the value back to 18 before continuing.
Add Fabric to an existing suite
Install the two Fabric packages and DuckDB peer, import
@fabricorg/databricks-bdd/steps from your existing support file, and add the
evidence formatter to your Cucumber configuration. Existing standard Gherkin,
Scenario Outlines, Examples, Rules, tags, hooks, and domain step files can stay
in place.
Use the Behave migration guide when the existing suite is Python Behave. Feature text normally moves unchanged; Python step and hook implementations are rewritten as TypeScript support modules.
6. Run the same scenario on Databricks
Use a dedicated scratch catalog and schema. The test identity needs workspace
access, CAN USE on the SQL warehouse, USE CATALOG, and ownership or
USE SCHEMA, CREATE TABLE, MODIFY, and SELECT on the scratch schema. Do
not point fixture-writing scenarios at a production schema.
Set one supported authentication method:
export DATABRICKS_HOST=https://<your-workspace-host>
# Recommended for secretless CI: Databricks workload identity federation
export DATABRICKS_AUTH_TYPE=env-oidc
export DATABRICKS_CLIENT_ID=<service-principal-application-id>
export DATABRICKS_OIDC_TOKEN_ENV=GITHUB_ID_TOKEN
export GITHUB_ID_TOKEN=<short-lived-idp-jwt>
# Also supported: OAuth machine-to-machine
export DATABRICKS_CLIENT_ID=<service-principal-application-id>
export DATABRICKS_CLIENT_SECRET=<service-principal-secret>
# Or, for a short local evaluation only:
# export DATABRICKS_TOKEN=<personal-access-token>Then configure the warehouse and isolated scope:
export DATABRICKS_HTTP_PATH=/sql/1.0/warehouses/<warehouse-id>
export DBX_TEST_CATALOG=fx_test
export DBX_TEST_SCHEMA=quickstart_<your_name>
export DBX_TEST_PROFILE=live
export DBX_TEST_LIVE=1
pnpm test:bddDBX_TEST_LIVE=1 is a deliberate safety gate: a live suite is a no-op without
it. Fixture tables are dropped during scenario cleanup unless
DBX_TEST_KEEP_FIXTURES=1 is set temporarily for debugging.
7. Publish the run to Studio
Create a write-scoped API key from Studio Settings, then send the generated evidence to the organization Quality Center:
fx login --api-key fx_key_...
fx doctor
npx @fabricorg/experiments@0.7.0 test publish reports/evidence.json \
--suite "Databricks evaluation"Open Quality in Studio to inspect scenarios, captured failures, CI metadata, and Databricks query-history links. JUnit-only suites can publish their XML the same way. On Databricks Apps, also configure the gateway service principal described in Quality Center.
Troubleshooting
| Symptom | Check |
|---|---|
Cannot use import statement | Confirm package.json contains "type": "module" and tsx is installed. |
| DuckDB module cannot be resolved | Install @duckdb/node-api; it is an optional peer because live-only consumers do not need it. |
| Live run exits without tests | Set both DBX_TEST_PROFILE=live and DBX_TEST_LIVE=1. |
| Warehouse cannot be resolved | Set DATABRICKS_HTTP_PATH or DATABRICKS_WAREHOUSE_ID, and grant the identity CAN USE. |
PERMISSION_DENIED creating fixtures | Use a scratch schema owned by the test identity or grant the schema permissions listed above. |
| A live-only scenario is skipped locally | Expected: @live, @jobs, @dlt, @pipeline, @autoloader, @lakebase, and @slow require the live profile. |
| Failure output contains less than expected | Capture is limited to 32 KiB per step; use DBX_TEST_CAPTURE_OUTPUT=passthrough to display while capturing. |
Choose the next path
- Browse the complete step catalog.
- Add Jobs, Lakeflow, Volume, Lakebase, notebook, or dbt scenarios in the BDD guide.
- Design a production suite with the advanced playbook.
- Compare exact behavior with Behave.
- See the working files in the public consumer example.
Testing on Databricks
A layered testing framework for Databricks artifacts — SQL, Delta tables, DLT pipelines, Jobs, Unity Catalog, Lakebase — with first-class BDD support.
Publish results to Quality Center
Send BDD, Databricks live-suite, or JUnit evidence from any CI system to Studio and investigate failures with Databricks deep links.