Loading...
Automatically run relevant tests when code changes are detected, with intelligent test selection and parallel execution
{
"hookConfig": {
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/code-test-runner-hook.sh",
"matchers": [
"write",
"edit",
"multiedit"
]
}
}
},
"scriptContent": "#!/usr/bin/env bash\n\n# Read the tool input from stdin\nINPUT=$(cat)\nTOOL_NAME=$(echo \"$INPUT\" | jq -r '.tool_name')\nFILE_PATH=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path // \"\"')\n\nif [ -z \"$FILE_PATH\" ]; then\n exit 0\nfi\n\necho \"🧪 Running tests for $FILE_PATH...\"\n\n# Get file extension and directory\nEXT=\"${FILE_PATH##*.}\"\nDIR=$(dirname \"$FILE_PATH\")\n\n# Find and run relevant tests based on file type\ncase \"$EXT\" in\n js|jsx|ts|tsx)\n # JavaScript/TypeScript files\n if [ -f \"package.json\" ]; then\n if command -v npm &> /dev/null && npm list jest &> /dev/null; then\n echo \"Running Jest tests...\"\n npm test -- --testPathPattern=\"$FILE_PATH\" --passWithNoTests 2>/dev/null\n elif command -v npm &> /dev/null && npm list vitest &> /dev/null; then\n echo \"Running Vitest tests...\"\n npx vitest run \"$FILE_PATH\" 2>/dev/null\n fi\n fi\n ;;\n py)\n # Python files\n if command -v pytest &> /dev/null; then\n echo \"Running pytest...\"\n pytest \"${FILE_PATH%.*}_test.py\" \"${DIR}/test_*.py\" 2>/dev/null || echo \"No Python tests found\"\n elif command -v python &> /dev/null; then\n echo \"Running Python unittest...\"\n python -m unittest discover -s \"$DIR\" -p \"*test*.py\" 2>/dev/null || echo \"No Python tests found\"\n fi\n ;;\n go)\n # Go files\n if command -v go &> /dev/null; then\n echo \"Running Go tests...\"\n go test \"${DIR}/...\" 2>/dev/null || echo \"No Go tests found\"\n fi\n ;;\n java)\n # Java files\n if command -v mvn &> /dev/null && [ -f \"pom.xml\" ]; then\n echo \"Running Maven tests...\"\n mvn test 2>/dev/null\n elif command -v gradle &> /dev/null && [ -f \"build.gradle\" ]; then\n echo \"Running Gradle tests...\"\n gradle test 2>/dev/null\n fi\n ;;\nesac\n\necho \"✅ Test execution completed for $FILE_PATH\" >&2\nexit 0"
}.claude/settings.local.json~/.claude/settings.json.claude/settings.json{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/code-test-runner-hook.sh",
"matchers": [
"write",
"edit",
"multiedit"
]
}
}
}#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
echo "🧪 Running tests for $FILE_PATH..."
# Get file extension and directory
EXT="${FILE_PATH##*.}"
DIR=$(dirname "$FILE_PATH")
# Find and run relevant tests based on file type
case "$EXT" in
js|jsx|ts|tsx)
# JavaScript/TypeScript files
if [ -f "package.json" ]; then
if command -v npm &> /dev/null && npm list jest &> /dev/null; then
echo "Running Jest tests..."
npm test -- --testPathPattern="$FILE_PATH" --passWithNoTests 2>/dev/null
elif command -v npm &> /dev/null && npm list vitest &> /dev/null; then
echo "Running Vitest tests..."
npx vitest run "$FILE_PATH" 2>/dev/null
fi
fi
;;
py)
# Python files
if command -v pytest &> /dev/null; then
echo "Running pytest..."
pytest "${FILE_PATH%.*}_test.py" "${DIR}/test_*.py" 2>/dev/null || echo "No Python tests found"
elif command -v python &> /dev/null; then
echo "Running Python unittest..."
python -m unittest discover -s "$DIR" -p "*test*.py" 2>/dev/null || echo "No Python tests found"
fi
;;
go)
# Go files
if command -v go &> /dev/null; then
echo "Running Go tests..."
go test "${DIR}/..." 2>/dev/null || echo "No Go tests found"
fi
;;
java)
# Java files
if command -v mvn &> /dev/null && [ -f "pom.xml" ]; then
echo "Running Maven tests..."
mvn test 2>/dev/null
elif command -v gradle &> /dev/null && [ -f "build.gradle" ]; then
echo "Running Gradle tests..."
gradle test 2>/dev/null
fi
;;
esac
echo "✅ Test execution completed for $FILE_PATH" >&2
exit 0Tests run on every file save slowing down
Add file extension filter or test file detection: `if [[ "$FILE_PATH" == *test* ]] || [[ "$FILE_PATH" == *spec* ]]; then exit 0; fi` to skip running tests when editing test files themselves.
Jest testPathPattern not finding related tests
Pattern matches test file paths not source. Use `--findRelatedTests` instead: `npm test -- --findRelatedTests="$FILE_PATH"` which finds tests importing the changed file through dependency graph.
Hook runs tests twice with both Jest and Vitest
Detection uses `npm list jest` which may find both. Add explicit priority: `if npm list jest &> /dev/null; then run_jest; exit 0; elif npm list vitest ...` to prevent fallthrough.
Python tests fail to locate test directory
Hook looks for `${FILE_PATH%.*}_test.py` and `test_*.py`. For pytest, use explicit discovery: `pytest --collect-only "$DIR" 2>/dev/null | grep "test session starts"` to verify test detection.
Go tests timeout on large module changes
Add timeout flag and scope: `go test -timeout 30s "${DIR}" 2>/dev/null` instead of `${DIR}/...` which tests all subpackages. Or use `go test -short` for quick tests only during development.
Loading reviews...