How do you run TestGen from Databricks Workflows?

You run DataOps TestGen from Databricks Workflows, now called Lakeflow Jobs, with a Python script task placed after the notebook task: it calls the TestGen REST API to start a test run, polls the job, and exits non-zero when tests fail. Under the default All succeeded rule, the next task never runs. No connector is needed.

Key points

  • DataOps TestGen runs from a Databricks job through its REST API: POST /api/v1/test-suites/{test_suite_id}/test-runs starts a run, GET /api/v1/jobs/{job_id} polls it, and GET /api/v1/test-runs/{job_id} returns result counts and a score.
  • Databricks' default Run if condition, All succeeded, marks a downstream task Upstream failed when a dependency fails, per Databricks docs checked October 2026, so a failing TestGen task stops the next transform.
  • DataKitchen's April 2026 tripwires post wired TestGen into a Databricks job over SSH and docker exec because the HTTP API had not shipped; the TestGen API now replaces that with three HTTPS calls.
  • TestGen tests the tables the job wrote through a Databricks SQL warehouse connection, running its SQL in the warehouse.
  • DataOps Observability has a documented Databricks agent for Azure Databricks, Databricks on AWS, and Databricks on Google Cloud; the docs mark access to its private Docker repository as Enterprise.

In April 2026, DataKitchen published a Databricks tripwire that reached TestGen by opening an SSH session to its VM and running docker compose exec inside the container. The post was blunt about the cost: key rotation, port whitelisting, a security review. It said an HTTP API was coming and would turn the whole thing into a REST call.

It shipped. DataOps TestGen now runs from Databricks Workflows, which Databricks calls Lakeflow Jobs, through its REST API. No connector, no SSH. The Airflow answer and the CI/CD answer cover the same calls elsewhere. Setting up the Databricks SQL connection TestGen tests through is in the Databricks how-to.

The job

bronze_to_silver (notebook) -> testgen_silver (Python script) -> silver_to_gold (notebook)

The middle task, from Run Profiling and Tests:

import sys, time, requests
from databricks.sdk.runtime import dbutils  # dbutils outside a notebook

suite_id = sys.argv[1]
API = dbutils.secrets.get("testgen", "api-url")  # http://<host>:8530 by default
HDR = {"Authorization": f"Bearer {dbutils.secrets.get('testgen', 'token')}"}

job_id = requests.post(f"{API}/api/v1/test-suites/{suite_id}/test-runs",
                       headers=HDR, timeout=30).json()["id"]
deadline = time.time() + 1800
while time.time() < deadline:
    job = requests.get(f"{API}/api/v1/jobs/{job_id}", headers=HDR, timeout=30).json()
    if job["status"] in ("completed", "error", "canceled"):
        break
    time.sleep(15)
else:
    sys.exit(f"TestGen job {job_id} did not finish")
if job["status"] != "completed":
    sys.exit(f"TestGen job {job_id}: {job['status']} {job['error_message']}")

result = requests.get(f"{API}/api/v1/test-runs/{job_id}", headers=HDR, timeout=30).json()["result"]
counts = result["result_counts"]
print(f"score {result['score']}, counts {counts}")
if counts["failed"] or counts["error"]:
    sys.exit(f"FAIL: {counts['failed']} failed, {counts['error']} errors in suite {suite_id}")

sys.exit with a message is the enforcement, same as the April version. Only the transport changed. The token and URL sit in a Databricks secret scope, not in the script.

Block the next task

Leave silver_to_gold on the default Run if condition, All succeeded. When testgen_silver fails, Databricks marks silver_to_gold Upstream failed and skips it (docs checked October 2026). Gold stays on the last good data. Add a task with At least one failed if you want a cleanup or notification step on the failure path.

Warnings pass through. A TestGen test set to warn returns warning, not failed, per the testing docs, so the data steward decides what blocks without a redeploy. DataKitchen’s medallion post puts one of these tasks between each layer.

Where results land

In TestGen’s Test Results page, with the job’s printed score and counts in the task log. The run accepts an optional body with external_url and metadata, shown under Link and Run details; send the Databricks run URL so a failed test links back to the job.

Profile on a schedule, not in every run. POST /api/v1/table-groups/{table_group_id}/profiling-runs works from a weekly job, or use TestGen’s own scheduler.

Tokens and Observability

The script reads one bearer token from the secret scope. Personal access tokens are an Enterprise feature, and they are the simple fit. Open source authenticates with an OAuth 2.1 client instead. Its access token expires after one hour, so store the client ID, client secret, and refresh token in the scope and trade the refresh token at /oauth/token at the top of the script. The refresh token lasts 30 days, after which someone re-authorizes the client in a browser.

DataOps Observability has a documented Databricks agent that watches the workflow runs themselves. The docs mark access to its private Docker repository as Enterprise. TestGen results join that view through Connect to Observability. For how TestGen compares with Lakehouse Monitoring and the managed vendors, see the Databricks tool comparison.

Documentation: TestGen API, Run Profiling and Tests, API Authentication, OAuth 2.1 Clients, Databricks quickstart, Connect to Observability, Observability Databricks agent

Frequently asked questions

Short answers to the follow-up questions people ask next.

Is there a Databricks connector for running TestGen?

Not for orchestration, and none is needed. DataOps TestGen connects to Databricks SQL to profile and test your tables, and a Databricks job task drives it through the TestGen REST API: POST /api/v1/test-suites/{test_suite_id}/test-runs to start, GET /api/v1/jobs/{job_id} to poll, and GET /api/v1/test-runs/{job_id} for the counts.

Should the TestGen task be a notebook or a Python script task?

Either works, because both can make HTTPS calls and fail the task. A Python script task keeps the TestGen call in one versioned file that every job reuses, with the test suite ID passed as a parameter. DataKitchen's April 2026 tripwires example used Python script tasks deployed through Databricks Asset Bundles.

Does DataOps Observability monitor Databricks jobs?

Yes. DataKitchen documents a DataOps Observability agent for Databricks workflows on Azure Databricks, Databricks on AWS, and Databricks on Google Cloud. It authenticates with a Databricks personal access token, an Azure service principal, or basic authentication. The docs mark access to the agent's private Docker repository as Enterprise.

Does any data leave my environment when a Databricks job runs TestGen?

No. DataOps TestGen runs its profiling and tests as read-only SQL inside your Databricks SQL warehouse and stores only computed results, such as aggregates, statistics, and test outcomes, in its own application database on your infrastructure. Profiling also keeps each column's most frequent values, and minimum and maximum text values, for display. The job task receives IDs, counts, and a score, never table rows.

Try it on your own data

DataOps TestGen is free and open source. Profile a table and generate its tests this afternoon.