# Add Integration Test

> Create a new integration test for dbt-autofix with proper folder structure and golden files

- Skill: `dbt-labs/add-integration-test` (Agent Skill)
- Install (CLI): `npx skillmds@latest add dbt-labs/add-integration-test`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dbt-labs/add-integration-test/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: dbt-labs (https://skillmd.com/u/dbt-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/dbt-labs/add-integration-test

---


# 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:
1. Serves as a specification for the work
2. Prevents regressions
3. 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:**
```bash
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`:
```bash
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/`:

1. **`project_<name>/`** - Input dbt project (before refactor)
   - Minimum: `dbt_project.yml` + model files in `models/`

2. **`project_<name>_expected/`** - Expected output (after refactor)
   - Mirror of input with the DESIRED transformations applied

3. **`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](../../../README.md)

**Discover existing test projects** to see patterns and avoid duplication:
```bash
ls tests/integration_tests/dbt_projects/ | grep -v _expected
```

Ask the user:
1. What deprecation, bug, or behavior is being tested?
2. Is there a GitHub issue number to reference?
3. 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:

```bash
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`:**
```yaml
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:

```json
{"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`:

```python
project_dir_to_behavior_change_mode["project_<name>"] = True
# or
project_dir_to_semantic_layer_mode["project_<name>"] = True
```

### Step 8: Verify Test Behavior

```bash
# Should fail (or xfail) if feature not implemented
uv run pytest "tests/integration_tests/test_full_dbt_projects.py::test_project_refactor[project_<name>]" -v

# Should pass once feature is implemented
```

## 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)

1. Create `project_config_quoted_strings/` with a model containing the problematic quoted string
2. Create `project_config_quoted_strings_expected/` showing correct handling (no error, proper transformation)
3. Test fails initially (bug exists)
4. Fix the bug
5. Test passes (bug fixed)

### Feature Request (Python model custom config access)

1. Create `project_python_model_meta_config/` with a Python model using `dbt.config.get("custom_key")`
2. Create `project_python_model_meta_config_expected/` showing the Python code updated to `dbt.config.get("meta").get("custom_key")`
3. Test fails initially (feature not implemented)
4. Implement feature
5. Test passes (feature complete)

