| name | add-integration-test |
| description | Create a new integration test for dbt-autofix with proper folder structure and golden files |
| disable-model-invocation | true |
| argument-hint | ["project-name"] |
| allowed-tools | Read, Write, Bash, Glob, Grep, Edit |
Add Integration Test
Create a new integration test for dbt-autofix. Integration tests verify that the refactor tool correctly transforms dbt projects.
Philosophy: Test-Driven Development
Integration tests document DESIRED behavior, not current behavior.
- For bug fixes: Create a test that reproduces the bug, with expected output showing the correct behavior
- For feature requests: Create a test that specifies what the feature should do
- Tests should FAIL initially, then PASS once the fix/feature is implemented
This approach:
- Serves as a specification for the work
- Prevents regressions
- Automatically validates when the implementation is complete
Using GOLDIE_UPDATE: Run with GOLDIE_UPDATE=1 to understand current behavior, but don't blindly accept it as the expected output. Manually craft the _expected files to reflect what the behavior should be.
Arguments
$ARGUMENTS - The test project name (e.g., config_quoted_strings)
Running a single test:
uv run pytest "tests/integration_tests/test_full_dbt_projects.py::test_project_refactor[project_<name>]" -v
Example for a project named config_quoted_strings:
uv run pytest "tests/integration_tests/test_full_dbt_projects.py::test_project_refactor[project_config_quoted_strings]" -v
Naming guidance: Use descriptive names that explain what the test covers, not issue numbers. For example:
config_quoted_strings (not issue_221)
python_model_meta_config (not issue_220)
jinja_unmatched_endif
The name becomes project_<name> in the test projects directory.
Test Structure
Each integration test requires 3 artifacts in tests/integration_tests/dbt_projects/:
-
project_<name>/ - Input dbt project (before refactor)
- Minimum:
dbt_project.yml + model files in models/
-
project_<name>_expected/ - Expected output (after refactor)
- Mirror of input with the DESIRED transformations applied
-
project_<name>_expected.stdout - Expected JSON log output
- One JSON object per line documenting refactors that SHOULD be applied
Steps to Follow
Step 1: Gather Information
Reference the README for the authoritative list of deprecations: README.md
Discover existing test projects to see patterns and avoid duplication:
ls tests/integration_tests/dbt_projects/ | grep -v _expected
Ask the user:
- What deprecation, bug, or behavior is being tested?
- Is there a GitHub issue number to reference?
- Does this test need special flags?
--behavior-change mode
--semantic-layer mode
Step 2: Understand Current Behavior (Optional)
Run with GOLDIE_UPDATE=1 to see what the tool currently does:
GOLDIE_UPDATE=1 uv run pytest "tests/integration_tests/test_full_dbt_projects.py::test_project_refactor[project_<name>]" -v
Note: Do NOT commit the auto-generated _expected files from GOLDIE_UPDATE without review. They reflect current behavior, not necessarily desired behavior. Manually craft the expected output to reflect what the behavior should be.
Step 3: Create Project Structure
tests/integration_tests/dbt_projects/
├── project_<name>/
│ ├── dbt_project.yml
│ └── models/
│ └── <model>.sql (or .py for Python models)
├── project_<name>_expected/
│ ├── dbt_project.yml
│ └── models/
│ └── <model>.sql
└── project_<name>_expected.stdout
Minimal dbt_project.yml:
name: '<test name>'
version: '1.0.0'
config-version: 2
profile: 'default'
model-paths: ["models"]
Step 4: Create Test Models (Input)
Create model files that demonstrate the behavior being tested. The input should contain the pattern that triggers the deprecation/refactor.
Step 5: Create Expected Output (Desired Behavior)
Manually create the _expected files showing what the output SHOULD be after the fix/feature is implemented. Do NOT just copy current behavior.
Step 6: Create Expected stdout
Write the JSON log output that SHOULD be produced. Each line is a JSON object:
{"mode": "applied", "file_path": "...", "refactors": [{"deprecation": "...", "log": "..."}]}
{"mode": "complete"}
Step 7: Handle Special Modes (if needed)
If the test requires --behavior-change or --semantic-layer, add an entry to the dicts in tests/integration_tests/test_full_dbt_projects.py:
project_dir_to_behavior_change_mode["project_<name>"] = True
project_dir_to_semantic_layer_mode["project_<name>"] = True
Step 8: Verify Test Behavior
uv run pytest "tests/integration_tests/test_full_dbt_projects.py::test_project_refactor[project_<name>]" -v
Golden File Tips
GOLDIE_UPDATE=1 shows current behavior - use for understanding, not as source of truth
- The
file_path key is ignored during comparison (paths don't need to match)
- Blank lines are ignored in file comparisons
- The
_expected suffix must match exactly
- Include trailing newlines in files
Example Workflows
Bug Fix (quoted strings causing errors)
- Create
project_config_quoted_strings/ with a model containing the problematic quoted string
- Create
project_config_quoted_strings_expected/ showing correct handling (no error, proper transformation)
- Test fails initially (bug exists)
- Fix the bug
- Test passes (bug fixed)
Feature Request (Python model custom config access)
- Create
project_python_model_meta_config/ with a Python model using dbt.config.get("custom_key")
- Create
project_python_model_meta_config_expected/ showing the Python code updated to dbt.config.get("meta").get("custom_key")
- Test fails initially (feature not implemented)
- Implement feature
- Test passes (feature complete)