datadog/run-tests
> Validate code changes by intelligently selecting and running the appropriate test suites. Use this when editing code to verify changes work correctly, run tests, validate functionality, or check for regressions. Automatically discovers affected test suites, selects the minimal set of venvs needed for validation, and handles test execution with Docker services as needed.
npx skills add https://github.com/DataDog/dd-trace-py --skill run-tests
This skill helps you efficiently validate code changes by running the appropriate subset of the test suite. It uses scripts/run-tests to intelligently discover affected tests and run only what's necessary for validation.
Use this skill when you have:
scripts/run-tests or riot via scripts/ddtest)--dry-run first - see what would run before executingdocs/contributing-testing.rst is the source of truth for testing proceduresFirst, determine which files were modified:
I'll use the scripts/run-tests script to discover what test suites match your changes:
scripts/run-tests --list <edited-files>
This outputs JSON showing:
Rather than running ALL available venvs (which could take hours), I'll select the minimal set needed to validate your changes:
When you modify files like:
ddtrace/internal/core/*, ddtrace/_trace/*, ddtrace/trace/*ddtrace/_monkey.py, ddtrace/settings/*ddtrace/constants.pyStrategy: Run core tracer + internal tests with 1 venv each
tracer suite with latest Python + internal suite with latest PythonWhen you modify files like:
ddtrace/contrib/flask/*, ddtrace/contrib/django/*, etc.ddtrace/contrib/*/patch.py or integration-specific codeStrategy: Run ONLY the affected integration suite with 1-2 venvs
contrib::flask suite with latest PythonWhen you modify tests/ files (but not test infrastructure):
-- -- -k test_name (first -- ends scripts/run-tests parsing and starts riot args; second -- tells riot to forward remaining args to pytest), or direct pytest test paths (e.g., -- -- tests/contrib/flask/test_views.py)When you modify:
tests/conftest.py, tests/suitespec.yml, scripts/run-tests, riotfile.pyStrategy: Run a quick smoke test suite
internal suite with 1 venv as a sanity checkI'll run the selected venvs. On the first invocation in a session, always run without -s to ensure the venv has dd-trace-py properly installed:
scripts/run-tests --venv <hash1> --venv <hash2>
On subsequent runs, use -s (riot's --skip-base-install flag, not to be confused with pytest's -s) to skip rebuilding dd-trace-py and save significant time:
scripts/run-tests --venv <hash1> --venv <hash2> -- -s
When to use -s (skip base install) on subsequent runs:
When to omit -s even on subsequent runs (force rebuild):
.pyx, .pxd), or CMake files were modified (e.g., under ddtrace/internal/, ddtrace/appsec/_iast/_taint_tracking/, src/native/)setup.py, pyproject.toml, or setup.cfg were modifiedriotfile.py or .riot/requirements/ files were modifiedThis will:
If tests pass: ✅ Your changes are validated!
If tests fail: 🔴 I'll:
For re-running specific tests (use -s since the venv is already built):
scripts/run-tests --venv <hash> -- -s -- -vv -k test_name
When you encounter test failures, follow this systematic approach:
-vv or -vvv for detailed outputFrom scripts/run-tests --list, you'll see output like:
{
"suites": [
{
"name": "tracer",
"venvs": [
{
"hash": "abc123",
"python_version": "3.8",
"packages": "..."
},
{
"hash": "def456",
"python_version": "3.11",
"packages": "..."
}
]
}
]
}
--venv DirectlyWhen you have a specific venv hash you want to run, you can use it directly without specifying file paths:
scripts/run-tests --venv e06abee
The --venv flag automatically searches all available venvs across all suites, so it works regardless of what files you have locally changed. This is useful when:
Changed file: ddtrace/contrib/internal/flask/patch.py
scripts/run-tests --list ddtrace/contrib/internal/flask/patch.py
# Output shows: contrib::flask suite available
# Select output (latest Python):
# Suite: contrib::flask
# Venv: hash=e06abee, Python 3.13, flask
# First run: no -s to ensure venv is properly set up
scripts/run-tests --venv e06abee
# Subsequent runs: use -s since only Python files changed
scripts/run-tests --venv e06abee -- -s
Changed file: ddtrace/_trace/tracer.py
scripts/run-tests --list ddtrace/_trace/tracer.py
# Output shows: tracer suite, internal suite available
# Select strategy:
# - tracer: latest Python (e.g., abc123)
# - internal: latest Python (e.g., def456)
# First run: no -s
scripts/run-tests --venv abc123 --venv def456
# Subsequent runs: use -s since only Python files changed
scripts/run-tests --venv abc123 --venv def456 -- -s
Changed file: tests/contrib/flask/test_views.py
scripts/run-tests --list tests/contrib/flask/test_views.py
# Output shows: contrib::flask suite
# First run: no -s
scripts/run-tests --venv flask_py311 -- -- -vv tests/contrib/flask/test_views.py
# Subsequent runs: use -s to skip rebuild
scripts/run-tests --venv flask_py311 -- -s -- -vv tests/contrib/flask/test_views.py
After the first run shows a test failing, use -s to iterate quickly:
scripts/run-tests --venv flask_py311 -- -s -- -vv -k test_view_called_twice
# Focused on the specific failing test with verbose output
-s on subsequent runs: After the first run builds the venv, pass -- -s to skip rebuild when only Python files changed-k filter when re-running failuresgit status-s after merging from main: Native code or dependencies may have changed, requiring a rebuild-s when C/Cython/CMake files changed: Native extensions must be recompiledFor comprehensive testing guidance, refer to the contributing documentation:
scripts/run-tests usage examplesWhen to reference these docs:
contributing-testing.rstcontributing.rstcontributing-design.rst# Manually check/stop services:
docker compose ps
docker compose down
tests/suitespec.yml to understand suite patterns-k to run subset of testsThe scripts/run-tests system:
tests/suitespec.ymlriot to manage multiple Python/package combinations as venvs-- <riot args> -- <pytest args> for mixed passthrough. The first -- is consumed by scripts/run-tests, and the second -- is consumed by riot before forwarding remaining args to pytest. If you only need pytest args, use -- -- <pytest args>.Primary suites for validation:
tracer: Core tracing functionality testsinternal: Internal component testscontrib::*: Integration with specific libraries (flask, django, etc.)integration_*: Cross-library integration scenariostelemetry, profiling, appsec, llmobs, etc.Some suites require environment setup:
DD_TRACE_AGENT_URL: For snapshot-based testsYou can limit CPU and memory resources to simulate resource-constrained CI environments where multiple jobs run in parallel. This helps reproduce flaky tests that fail due to timing issues, race conditions, or resource exhaustion.
Environment Variables:
DD_TEST_CPUS: CPU limit (e.g., 0.25, 0.5, 1.0, 2.0)DD_TEST_MEMORY: Memory limit with unit (e.g., 512m, 1g, 2g)Usage:
# Run tests with resource constraints
DD_TEST_CPUS=0.5 DD_TEST_MEMORY=1g scripts/run-tests --venv <hash>
# Run specific test file with heavy constraints
DD_TEST_CPUS=0.25 DD_TEST_MEMORY=1g scripts/run-tests tests/path/to/test.py
# Multiple runs to catch intermittent failures
for i in {1..10}; do
DD_TEST_CPUS=0.5 DD_TEST_MEMORY=1g scripts/run-tests --venv <hash> -- --randomly-seed=$RANDOM
done
Recommended Resource Limits:
DD_TEST_CPUS=2.0 DD_TEST_MEMORY=4g
Simulates a CI runner with some other jobs running. Good for initial testing.
DD_TEST_CPUS=1.0 DD_TEST_MEMORY=2g
Simulates a heavily loaded CI server with many concurrent jobs. Recommended starting point for reproducing flaky tests.
DD_TEST_CPUS=0.5 DD_TEST_MEMORY=1g
Simulates extreme resource contention. Good for surfacing timing issues and race conditions.
DD_TEST_CPUS=0.25 DD_TEST_MEMORY=512m
Forces maximum resource pressure. Use this to find the breaking point or reproduce worst-case scenarios.
When to Use Resource Limits:
Verifying Limits Are Applied:
# Check configuration before running
DD_TEST_CPUS=0.5 DD_TEST_MEMORY=1g docker compose config | grep -A 5 testrunner
# Monitor actual resource usage during test run (in another terminal)
docker stats
Example: Testing a Flaky Test
# Run a known flaky test 20 times with resource constraints
DD_TEST_CPUS=0.5 DD_TEST_MEMORY=1g scripts/run-tests \
tests/appsec/integrations/flask_tests/test_iast_flask_testagent.py::test_iast_unvalidated_redirect \
-- --count=20
Take datadog/run-tests from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.