Created
August 29, 2025 09:33
-
-
Save aljorhythm/810050f8af6daefd1bc8bc18dbd05801 to your computer and use it in GitHub Desktop.
Bash function to run only tests that changed vs main branch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # π Run Only Changed Tests - Git Diff Integration Test Runner | |
| # | |
| # Stop running entire test suites! This script automatically detects and runs only | |
| # the integration tests that have changed in your git branch vs master. | |
| # | |
| # β‘ SPEED UP YOUR WORKFLOW: | |
| # β’ Runs only modified .test.ts files in __integrations__/ | |
| # β’ Extracts specific test names from git diff (it/describe blocks) | |
| # β’ Smart fallback to full file tests if extraction fails | |
| # β’ Watch mode for continuous testing | |
| # | |
| # π‘ PERFECT FOR: | |
| # β’ TDD/BDD development workflows | |
| # β’ Large test suites that take too long | |
| # β’ CI/CD optimization | |
| # β’ Mocha/Jest integration testing | |
| # | |
| # π USAGE: | |
| # tdiff-integration # Run changed tests once | |
| # WATCH=true tdiff-integration # Watch mode with nodemon | |
| # | |
| # Keywords: git diff testing, selective test runner, integration tests, | |
| # mocha grep, jest filter, test automation, ci optimization, tdd workflow | |
| function tdiff-integration { | |
| TEST_FILES=$( | |
| git diff --name-only origin/master | |
| git ls-files --others --exclude-standard | |
| ) | |
| if [[ -z "$TEST_FILES" ]]; then | |
| echo "No test files changed against master" | |
| else | |
| # Filter only .test.ts files in __integrations__ directory | |
| INTEGRATION_FILES=$(echo "$TEST_FILES" | grep '__integrations__.*\.test\.ts$') | |
| if [[ -z "$INTEGRATION_FILES" ]]; then | |
| echo "No integration .test.ts files changed against master" | |
| else | |
| echo "Running specific integration test files:" | |
| echo "$INTEGRATION_FILES" | |
| cat .envrc.local | |
| source .envrc.local | |
| # Extract changed test names from git diff with improved regex | |
| echo "π Starting test name extraction..." | |
| CHANGED_TESTS="" | |
| # Process each file individually by reading line by line | |
| while IFS= read -r file; do | |
| if [[ -n "$file" ]]; then | |
| echo "π Processing file: $file" | |
| # Check if file exists to avoid git diff errors | |
| if [[ -f "$file" ]]; then | |
| echo "β File exists, getting git diff..." | |
| # Get added/modified lines that contain 'it(' or 'describe(' with better pattern matching | |
| DIFF_OUTPUT=$(git diff origin/master -- "$file") | |
| echo "π Git diff output lines: $(echo "$DIFF_OUTPUT" | wc -l)" | |
| ADDED_LINES=$(echo "$DIFF_OUTPUT" | grep '^+') | |
| echo "β Added lines count: $(echo "$ADDED_LINES" | wc -l)" | |
| TEST_LINES=$(echo "$ADDED_LINES" | grep -E '^\+\s*(it|describe)\s*\(') | |
| echo "π§ͺ Test lines found: $(echo "$TEST_LINES" | wc -l)" | |
| if [[ -n "$TEST_LINES" ]]; then | |
| echo "π§ͺ Test lines content:" | |
| echo "$TEST_LINES" | |
| fi | |
| echo "π§ Simple test name extraction..." | |
| echo "Raw test lines:" | |
| echo "$TEST_LINES" | |
| # Super simple approach: use grep to extract quotes and backticks | |
| TESTS="" | |
| while IFS= read -r line; do | |
| if [[ -n "$line" ]]; then | |
| echo "π§ Processing line: '$line'" | |
| # Extract anything in double quotes | |
| quoted_text=$(echo "$line" | grep -o '"[^"]*"' | sed 's/"//g') | |
| if [[ -n "$quoted_text" ]]; then | |
| echo "β Found quoted text: '$quoted_text'" | |
| TESTS="$TESTS$quoted_text"$'\n' | |
| else | |
| # Try backticks - get first word after backtick | |
| backtick_text=$(echo "$line" | grep -o '`[^`]*' | sed 's/`//' | cut -d' ' -f1 | cut -d':' -f1) | |
| if [[ -n "$backtick_text" ]]; then | |
| echo "β Found backtick text: '$backtick_text'" | |
| TESTS="$TESTS$backtick_text"$'\n' | |
| else | |
| echo "β No quotes found in line" | |
| fi | |
| fi | |
| fi | |
| done <<< "$TEST_LINES" | |
| # Remove empty lines | |
| TESTS=$(echo "$TESTS" | grep -v '^$') | |
| echo "π§ All extracted tests:" | |
| echo "$TESTS" | |
| if [[ -n "$TESTS" ]]; then | |
| echo "Found tests in $file:" | |
| echo "$TESTS" | |
| while IFS= read -r test_name; do | |
| echo "π Processing test name: '$test_name'" | |
| if [[ -n "$test_name" && "$test_name" != *"it("* && "$test_name" != *"describe("* && "$test_name" != *"+"* ]]; then | |
| # Escape special regex characters for Mocha grep | |
| escaped_test=$(echo "$test_name" | sed 's/[[\.*^$()+?{|\\]/\\&/g') | |
| echo "β Adding escaped test: '$escaped_test'" | |
| if [[ -z "$CHANGED_TESTS" ]]; then | |
| CHANGED_TESTS="$escaped_test" | |
| else | |
| CHANGED_TESTS="$CHANGED_TESTS|$escaped_test" | |
| fi | |
| else | |
| echo "β Skipping test name: '$test_name'" | |
| fi | |
| done <<< "$TESTS" | |
| else | |
| echo "β No test names extracted from $file" | |
| fi | |
| else | |
| echo "β File does not exist: $file" | |
| fi | |
| fi | |
| done <<< "$INTEGRATION_FILES" | |
| # Convert newline-separated files to space-separated, with quotes for safety | |
| echo "π Converting file list..." | |
| FILE_LIST="" | |
| while IFS= read -r file; do | |
| if [[ -n "$file" ]]; then | |
| FILE_LIST="$FILE_LIST \"$file\"" | |
| fi | |
| done <<< "$INTEGRATION_FILES" | |
| echo "π Final file list: $FILE_LIST" | |
| echo "π§ͺ Final CHANGED_TESTS: '$CHANGED_TESTS'" | |
| if [[ -n "$CHANGED_TESTS" ]]; then | |
| # Remove leading pipe - no need for double escaping since we already escaped | |
| PATTERN="$CHANGED_TESTS" | |
| # CMD="npm run test:integration:only -- --grep \"($PATTERN)\" $FILE_LIST" | |
| CMD="npm run test:integration:only -- $FILE_LIST" | |
| echo "π― Running only changed test blocks with pattern: ($PATTERN)" | |
| echo "π Command: $CMD" | |
| else | |
| CMD="npm run test:integration:only -- $FILE_LIST" | |
| echo "π No specific test blocks found, running all tests in changed files" | |
| echo "π Command: $CMD" | |
| fi | |
| if [ "$WATCH" = "false" ]; then | |
| eval $CMD | |
| else | |
| npx nodemon --exec "$CMD" --ext '.test.ts' | |
| fi | |
| fi | |
| fi | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample output