Code Change Validator
Validate code changes by analyzing diffs, running existing tests, performing exploratory testing, and writing regression tests for any issues discovered.
Workflow
- •Analyze the diff → Understand what changed
- •Determine intent → Use conversation context or ask the user
- •Find run instructions → Locate README, Makefile, package.json, etc.
- •Build the project → Compile/build before testing to catch build errors early
- •Run existing tests → Execute the project's test suite
- •Exploratory testing → Manually verify the changed behavior
- •Write regression tests → If issues found, add tests with descriptive comments
Step 1: Analyze the Git Diff
git diff HEAD~1 # or git diff main, git diff --staged, etc.
Identify:
- •Which files changed
- •What functions/classes/modules were modified
- •The nature of changes (new feature, bug fix, refactor, config change)
Step 2: Determine Intent
If prior conversation context exists: Extract the intended behavior from the conversation. Look for descriptions of what the changes should accomplish.
If no context: Ask the user:
"I see changes to [files/areas]. What behavior should these changes produce? What problem are they solving?"
Keep the question focused on the specific changes observed.
Step 3: Find Run Instructions
Search for setup and run documentation in this order:
- •
README.md,README.rst,README - •
Makefile,Taskfile.yml,justfile - •
package.json(scripts section) - •
pyproject.toml,setup.py,setup.cfg - •
Cargo.toml,go.mod,build.gradle,pom.xml - •
docker-compose.yml,Dockerfile - •
.github/workflows/(CI configs often reveal test commands)
Extract:
- •How to install dependencies
- •How to run the application
- •How to run tests (unit, integration, e2e)
- •Where and how to write e2e/integration tests (test directories, frameworks, config, conventions)
Step 4: Build the Project
Before running tests, build the project to catch compilation and build errors early.
Use the build command discovered in Step 3. Common patterns:
| Stack | Detection | Build Command |
|---|---|---|
| Node/JS | package.json with build script | npm run build |
| TypeScript | tsconfig.json | npx tsc --noEmit or npm run build |
| Python | pyproject.toml with build backend | pip install -e . or python -m build |
| Rust | Cargo.toml | cargo build |
| Go | go.mod | go build ./... |
| Java | pom.xml or build.gradle | mvn compile or gradle build |
If the build fails, fix build errors before proceeding to tests. Report any build failures that cannot be resolved.
Step 5: Run Existing Tests
Detect and run the project's test suite:
| Stack | Detection | Run Command |
|---|---|---|
| Node/JS | package.json with jest/vitest/mocha | npm test or npx jest |
| Python | pytest.ini, pyproject.toml, tests/ | pytest or python -m pytest |
| Rust | Cargo.toml | cargo test |
| Go | *_test.go files | go test ./... |
| Ruby | Gemfile with rspec/minitest | bundle exec rspec or rake test |
| Java | pom.xml or build.gradle | mvn test or gradle test |
If tests fail, note the failures for later regression test writing.
Step 6: Exploratory Testing
Prefer the project's own test infrastructure over ad-hoc bash scripts. If Step 3 revealed documentation or configuration for e2e/integration tests (e.g., Playwright, Cypress, Selenium, Testcontainers, or a custom harness), write new test cases there to exercise the changed behavior. This produces repeatable, CI-friendly validation instead of throwaway manual checks.
If e2e/integration test infrastructure exists:
- •Read the project's test docs to understand conventions (file location, naming, setup/teardown, fixtures)
- •Search for existing tests that already cover the changed behavior. Look in the project's test directories for tests that reference the modified functions, classes, endpoints, or components. If adequate coverage already exists, run those tests and skip to documenting results.
- •Write test cases only for uncovered behavior in the existing framework that cover:
- •The changed code paths with representative inputs
- •Edge cases relevant to the changes
- •Regressions in related functionality
- •Run the new tests using the project's test runner
- •Document any failures — expected vs. observed behavior
If no e2e/integration test infrastructure exists:
Fall back to manual exploratory testing:
- •Start the application using discovered run instructions
- •Exercise the changed code paths with real inputs
- •Verify expected behavior matches the stated intent
- •Test edge cases relevant to the changes
- •Check for regressions in related functionality
Document any issues discovered:
- •What behavior was expected
- •What behavior was observed
- •Steps to reproduce
Step 7: Write Regression Tests
Only if issues were found in steps 5 or 6.
Check for Existing Coverage First
Before writing a new test, search the test suite for existing tests that already assert the behavior you want to guard. Look for:
- •Tests referencing the affected functions, classes, or modules by name
- •Tests whose descriptions match the expected behavior
- •Tests that exercise the same code paths with similar inputs
If an existing test already covers the scenario but was not catching the issue (e.g., wrong assertion, missing edge case), update that test rather than adding a duplicate. Only write a new test when no existing test covers the behavior.
Test File Location
Follow the project's existing convention:
- •
tests/,test/,__tests__/,spec/ - •Co-located
*.test.js,*_test.py,*_test.go
Test Structure
Every regression test MUST include a comment explaining:
- •What bug or issue this test guards against
- •How the bug manifested
- •Reference to the validation session (date or context)
Examples by Framework
Jest/Vitest (JavaScript/TypeScript):
/**
* Regression test: Validates fix for [issue description]
*
* Bug: [Describe what went wrong]
* Expected: [What should happen]
* Found during: Code change validation [date/context]
*/
test('should [expected behavior]', () => {
// Arrange
// Act
// Assert
});
pytest (Python):
def test_regression_issue_description():
"""
Regression test: Validates fix for [issue description]
Bug: [Describe what went wrong]
Expected: [What should happen]
Found during: Code change validation [date/context]
"""
# Arrange
# Act
# Assert
Go:
// TestRegressionIssueDescription validates fix for [issue description]
//
// Bug: [Describe what went wrong]
// Expected: [What should happen]
// Found during: Code change validation [date/context]
func TestRegressionIssueDescription(t *testing.T) {
// Arrange
// Act
// Assert
}
After Writing Tests
- •Run the new tests to confirm they pass with the fix
- •Optionally verify they would have caught the original issue (if reproducible)
- •Ensure tests follow project conventions (naming, organization, assertions)
Reporting
Summarize findings:
## Validation Summary **Changes analyzed:** [files/areas] **Intended behavior:** [from context or user] ### Existing Tests - Status: [passed/failed] - [Details of any failures] ### Exploratory Testing - [What was tested] - [Issues found, if any] ### Regression Tests Added - [List of new tests with brief descriptions] - [Or "None required - all tests passed"]