Comprehensive testing workflow that should be used proactively after ANY code changes...
Ensure comprehensive test coverage and prevent downstream breakage by following a systematic testing workflow after any code changes. This skill provides step-by-step procedures for validating changes at multiple levels: immediate targets, entire packages recursively, affected targets via target determination, and reverse dependencies.
ALWAYS test comprehensively after making changes. A passing single test is not sufficient. Changes can break:
Follow the complete workflow below to catch issues before they reach production or break other developers' work.
Use this skill proactively and automatically after:
Use pattern: After completing any change → immediately invoke this testing workflow.
Follow these steps in order. Do NOT skip steps.
First, verify the specific target being modified works correctly.
buck2 test <target>
Examples:
# Test a specific binary
buck2 test //src/buildflow:buildflow
# Test a specific library
buck2 test //src/tools/brainiac:brainiac
# Test a specific test target
buck2 test //src/lib/mylib:test-parser
Success criteria: All tests pass with no failures.
If tests fail: Fix the issues before proceeding. Do not continue to the next step with failing tests.
After the immediate target passes, test ALL targets in the package recursively using the ... pattern. This catches:
buck2 test <package-path>/...
Examples:
# Test all targets in buildflow package
buck2 test //src/buildflow/...
# Test all targets in brainiac package
buck2 test //src/tools/brainiac/...
# Test entire depot (use cautiously - very slow)
buck2 test //...
Why this matters: Individual targets may pass, but package-level tests or sibling targets may fail. The ... pattern ensures complete package validation.
Success criteria: All tests in the package pass.
If tests fail: Fix the issues. The recursive test found problems the immediate test missed.
Use target determination to find which other packages are affected by the changes. This identifies:
Using the MCP tool (preferred):
# Use the target determination MCP tool
mcp__brainiac__target_determination(
from: "trunk()",
to: "@",
universe: ["root//...", "third-party//..."]
)
Using buck2-target-determination skill (alternative):
Invoke the buck2-target-determination skill to run target determination analysis. This will identify affected targets based on the current changes.
Manual approach (if needed):
# Find reverse dependencies manually
buck2 uquery "rdeps(//..., <your-target>)"
# Example: find everything that depends on brainiac
buck2 uquery "rdeps(//..., //src/tools/brainiac:brainiac)"
Output: List of affected target patterns.
Build and test all targets identified by target determination to ensure changes don't break downstream consumers.
Build affected targets first:
buck2 build <affected-targets...>
Example:
# Build multiple affected targets
buck2 build //src/tools/omnifix:omnifix //src/lib/parser:parser //tests/integration:all
Then test affected targets:
buck2 test <affected-targets...>
Example:
# Test all affected targets
buck2 test //src/tools/omnifix:omnifix //src/lib/parser:parser //tests/integration:all
Why this matters: Changes to libraries, APIs, or shared code can break packages that depend on them. Testing only the changed package misses these downstream failures.
Success criteria: All affected targets build and test successfully.
If tests fail: The changes broke a downstream consumer. Either:
For critical changes to widely-used libraries, explicitly test reverse dependencies.
Find direct reverse dependencies:
buck2 uquery "rdeps(//..., <target>, 1)"
Find transitive reverse dependencies:
buck2 uquery "rdeps(//..., <target>)"
Test reverse dependencies:
# Extract targets from uquery output and test them
buck2 test <rdep-targets...>
When to use:
Skip when:
Minimal workflow (use after every change):
buck2 test <target> # Step 1: immediate
buck2 test <package>/... # Step 2: recursive
Complete workflow (use before commits/PRs):
buck2 test <target> # Step 1: immediate
buck2 test <package>/... # Step 2: recursive
# Run target determination # Step 3: affected
buck2 build <affected> # Step 4: build affected
buck2 test <affected> # Step 4: test affected
Advanced workflow (use for library changes):
buck2 test <target> # Step 1: immediate
buck2 test <package>/... # Step 2: recursive
# Run target determination # Step 3: affected
buck2 build <affected> # Step 4: build affected
buck2 test <affected> # Step 4: test affected
buck2 uquery "rdeps(//..., <target>)" # Step 5: find rdeps
buck2 test <rdeps> # Step 5: test rdeps
After creating a BUILD file:
buck2 test //path/to:targetbuck2 test //path/to/...buck2 targets //path/to/...After changing source code:
buck2 test //path/to:targetbuck2 test //path/to/...After fixing tests:
buck2 test <fixed-target>buck2 test <package>/... (ensure fix didn't break other tests)After adding/removing dependencies:
buck2 test <target>buck2 test <package>/...buck2 uquery "rdeps(//..., <target>)"After refactoring:
buck2 test <package>/...buck2 build <affected>buck2 test <affected>Symptom: buck2 test <target> passes, but buck2 test <package>/... fails.
Cause:
Solution: Investigate which specific test is failing in the package run and why it differs from individual execution.
Symptom: Target determination returns empty or minimal results despite significant changes.
Cause:
Solution:
jj status["root//...", "third-party//..."]from: "trunk()", to: "@"Symptom: Downstream packages fail after changes.
Cause: Breaking changes to APIs, behavior, or contracts.
Solution:
Symptom: buck2 test //... takes too long.
Cause: Testing entire monorepo is expensive.
Solution:
buck2 build first to fail fast on compilation errors# ❌ Insufficient - only tests one target
buck2 test //src/buildflow:buildflow
# ✅ Comprehensive - tests entire package
buck2 test //src/buildflow/...
Building first catches compilation errors faster than waiting for test execution:
# Fast failure on build errors
buck2 build <targets>
buck2 test <targets>
Don't guess which packages might be affected:
# ❌ Guessing
buck2 test //src/tools/... //src/lib/...
# ✅ Systematic
# Run target determination
buck2 test <affected-targets>
Start narrow, expand scope:
Never commit with failing tests. The workflow is:
buck2 test <package>/...
# Run target determination
buck2 test <affected>
jj commit -m "..."
buck2 test <package>/...
# Run target determination
buck2 build <affected>
buck2 test <affected>
# Create PR
CI should run comprehensive tests:
buck2 test //...buck2-target-determination - Determine affected targets from changesbuck2-build-troubleshoot - Debug build failuresbuck2-query-helper - Query dependency graphs and targetsGolden rule: After any change, always:
...This workflow prevents downstream breakage and ensures high code quality across the monorepo.