How do you run TestGen from Snowflake Tasks?

A Snowflake Task can run DataOps TestGen only by calling a Python stored procedure that reaches the TestGen REST API through a Snowflake external access integration. DataKitchen doesn't document that route. The documented one is an outside runner, such as Airflow, Data Factory, or TestGen's own scheduler, calling the same API after the Task graph finishes.

Key points

  • DataKitchen documents no way to call DataOps TestGen from inside Snowflake as of October 2026; its API docs describe HTTP calls from CI/CD pipelines, orchestration tools, and custom workflows.
  • Snowflake documents external access integrations that let a Python stored procedure call an external HTTPS endpoint, and a Task can call a stored procedure, so a Task can reach the TestGen API if Snowflake can reach the TestGen host.
  • Private connectivity from Snowflake to an external endpoint requires Snowflake Business Critical Edition or later, per Snowflake's external network access docs checked October 2026.
  • Snowflake Data Metric Functions require Enterprise Edition and run on a DMF schedule attached to the table, hourly by default, with no Task needed; TestGen generates its 34 test types from a profile instead of measuring metrics you attach.
  • DataKitchen documents no DataOps Observability agent for Snowflake Tasks as of October 2026.

Snowflake Tasks don’t make HTTP calls. They run SQL or call a stored procedure. DataOps TestGen runs from whatever calls its REST API, so “run TestGen from a Task” means one of two things, and only one of them is in DataKitchen’s docs. Neither needs a connector.

This page covers the trigger. Connecting DataOps TestGen to Snowflake, with the role and grants, is in the Snowflake how-to and DataKitchen’s Snowflake quickstart.

Route 1: an outside runner (documented)

The TestGen API is built for CI/CD pipelines, orchestration tools, and custom workflows. If Airflow, Data Factory, or a CI job already starts your Snowflake work, it calls TestGen after the Task graph finishes. The calls are in Run Profiling and Tests:

StepCall
Start a test runPOST /api/v1/test-suites/{test_suite_id}/test-runs
PollGET /api/v1/jobs/{job_id} until completed, error, or canceled
Read the resultGET /api/v1/test-runs/{job_id} for result_counts and score

The Airflow answer and the CI/CD answer show those calls as tasks. With no outside runner at all, TestGen’s own scheduler runs the suite on a cron set after the graph usually finishes. That catches problems. It doesn’t stop the next task.

Route 2: a stored procedure (built from Snowflake’s docs, untested by DataKitchen)

Snowflake documents external network access: a network rule, a secret, and an external access integration let a Python procedure call an outside HTTPS endpoint. A Task can call that procedure. The sketch below is built from Snowflake’s docs and TestGen’s API docs. DataKitchen has not tested it end to end:

CREATE NETWORK RULE testgen_api MODE = EGRESS TYPE = HOST_PORT
  VALUE_LIST = ('testgen.example.com:443');
CREATE SECRET testgen_token TYPE = GENERIC_STRING SECRET_STRING = '<access token>';
CREATE EXTERNAL ACCESS INTEGRATION testgen_access
  ALLOWED_NETWORK_RULES = (testgen_api) ALLOWED_AUTHENTICATION_SECRETS = (testgen_token) ENABLED = TRUE;

CREATE PROCEDURE run_testgen(suite_id STRING) RETURNS STRING LANGUAGE PYTHON
  RUNTIME_VERSION = 3.12 PACKAGES = ('snowflake-snowpark-python','requests') HANDLER = 'run'
  EXTERNAL_ACCESS_INTEGRATIONS = (testgen_access) SECRETS = ('tok' = testgen_token)
AS $$
import _snowflake, requests, time
API = "https://testgen.example.com"
def run(session, suite_id):
    h = {"Authorization": "Bearer " + _snowflake.get_generic_secret_string("tok")}
    job_id = requests.post(f"{API}/api/v1/test-suites/{suite_id}/test-runs", headers=h, timeout=30).json()["id"]
    for _ in range(120):
        job = requests.get(f"{API}/api/v1/jobs/{job_id}", headers=h, timeout=30).json()
        if job["status"] in ("completed", "error", "canceled"):
            break
        time.sleep(15)
    if job["status"] != "completed":
        raise Exception(f"TestGen job {job_id}: {job['status']}")
    c = requests.get(f"{API}/api/v1/test-runs/{job_id}", headers=h, timeout=30).json()["result"]["result_counts"]
    if c["failed"] or c["error"]:
        raise Exception(f"{c['failed']} failed, {c['error']} errors")
    return "passed"
$$;

Put the Task that calls it in the middle of the graph. Snowflake’s task graph docs say a child task waits for its predecessors to complete successfully (checked October 2026), so a raised exception keeps the downstream task from running.

Three catches. Snowflake has to reach the TestGen API, which listens on http://<host>:8530 by default; serve it over HTTPS on a host Snowflake can reach. Private connectivity needs Business Critical Edition. And the secret holds a token. Personal access tokens are an Enterprise feature and stay valid for their full lifetime, often months. Open source uses an OAuth 2.1 client: each access token expires after one hour, so the procedure would have to store the refresh token and trade it at /oauth/token on every run, and the refresh token expires after 30 days, when someone re-authorizes the client in a browser. On open source, Route 1 is the practical one.

Either way, this is DataKitchen’s tripwire pattern, with a test step between layers as the medallion post lays out.

Data Metric Functions, for comparison

Snowflake’s native option needs no Task. Data Metric Functions require Enterprise Edition and run on a DMF schedule attached to the table, hourly by default. System DMFs cover common metrics, and you write custom ones for the rest. That’s the strength: no extra server. The limit is that you pick every metric. TestGen profiles the table and generates tests from 34 test types, and its SQL runs in the same account. The Snowflake tool comparison covers the trade in full.

Documentation: TestGen API, Run Profiling and Tests, API Authentication, Scheduling, Snowflake quickstart, Access Requirements

Frequently asked questions

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

Can a Snowflake Task call the TestGen API directly?

Not directly. A Snowflake Task runs SQL or calls a stored procedure, and the Task itself makes no HTTP calls. A Python stored procedure with an external access integration can make an outbound HTTPS call. That procedure can call the DataOps TestGen REST API, but DataKitchen doesn't document or test the route as of October 2026, and the TestGen host must be reachable from Snowflake.

Should I use Snowflake Data Metric Functions or TestGen?

Use DMFs for a few metrics you know you want on specific tables, and DataOps TestGen for coverage you didn't write. DMFs need Snowflake Enterprise Edition and run on a schedule attached to each table, hourly by default. TestGen profiles 55 column characteristics and generates tests from 34 test types, running its SQL inside your Snowflake account.

What is the simplest way to run TestGen after a Snowflake Task graph?

Use TestGen's own scheduler. Schedule the test suite with a cron expression set after the Task graph's usual finish time. It gates nothing, but it needs no code. To block downstream tasks, the check has to run inside the graph, which means a stored procedure with external network access calling the DataOps TestGen API.

Does any data leave my environment when TestGen tests Snowflake?

No. DataOps TestGen runs its profiling and tests as read-only SQL inside your Snowflake account 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. An API call from a Task returns IDs, counts, and a score, never rows.

Try it on your own data

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