Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/theteleporter/scripts/llms.txt

Use this file to discover all available pages before exploring further.

Proper testing ensures your scripts work correctly and catch errors before they cause problems. Learn the testing approaches used in TheTeleporter Scripts.

Testing Workflow

1

Syntax validation

Check for syntax errors without executing the script:
bash -n script.sh
This performs a dry-run that only parses the script without executing it.
2

Static analysis

Use ShellCheck to find common issues and anti-patterns:
shellcheck script.sh
ShellCheck catches issues like:
  • Unquoted variables
  • Useless cats and pipes
  • Missing error handling
  • Deprecated syntax
3

Debug mode testing

Run the script in debug mode to see what it would do:
./script.sh --debug
Debug mode should:
  • Show what would be executed
  • Print debug messages
  • Not make actual changes
4

Manual testing

Test the actual functionality:
# Test with valid inputs
./script.sh --source /path/to/source

# Test error handling
./script.sh --source /nonexistent

# Test help flag
./script.sh --help

Syntax Validation

The bash -n command checks syntax without execution:
bash -n my-script.sh

What it catches:

  • Missing quotes or brackets
  • Unclosed strings or heredocs
  • Invalid command syntax
  • Incorrect function definitions

Example:

# Bad syntax - missing closing quote
echo "Hello world

# Check syntax
$ bash -n bad-script.sh
bad-script.sh: line 2: unexpected EOF while looking for matching `"'
bad-script.sh: line 3: syntax error: unexpected end of file
Run bash -n after any changes to catch syntax errors immediately.

Static Analysis with ShellCheck

ShellCheck is a static analysis tool that finds bugs and style issues:

Installation

# Ubuntu/Debian
sudo apt install shellcheck

# macOS
brew install shellcheck

# Arch
sudo pacman -S shellcheck

Basic usage:

shellcheck script.sh

Example output:

$ shellcheck backup.sh

In backup.sh line 15:
rm -rf $TEMP_DIR
       ^-------^ SC2086: Double quote to prevent globbing and word splitting.

In backup.sh line 23:
if [ $STATUS = "success" ]; then
     ^-----^ SC2086: Double quote to prevent globbing and word splitting.
   ^ SC2039: In POSIX sh, == in place of = is undefined.

Common issues ShellCheck finds:

Unquoted variables:
# Bad
rm -rf $DIR

# Good
rm -rf "$DIR"
Useless use of cat:
# Bad
cat file.txt | grep "pattern"

# Good
grep "pattern" file.txt
Missing error handling:
# Bad
cd /some/directory
rm -rf *

# Good
cd /some/directory || exit 1
rm -rf *

Ignoring specific warnings:

If you need to ignore a warning:
# shellcheck disable=SC2086
for file in $FILES; do
  echo "$file"
done
Only disable warnings when you understand why they’re triggered and know it’s safe to ignore them.

Debug Mode Testing

All scripts should support debug mode via the --debug flag:

Implementation:

DEBUG=0

while [[ $# -gt 0 ]]; do
  case $1 in
    -d|--debug)
      DEBUG=1
      shift
      ;;
  esac
done

main() {
  if [[ $DEBUG -eq 1 ]]; then
    debug "Would delete: $FILE"
    warning "This is a dry-run, no changes will be made"
  else
    rm "$FILE"
    success "Deleted: $FILE"
  fi
}

Testing with debug mode:

# See what would happen without making changes
./script.sh --debug

# Example output:
# [DEBUG] Would delete: /tmp/cache
# ⚠ This is a dry-run, no changes will be made

Debug function:

The template includes a debug function that only prints in debug mode:
debug() {
  if [[ $DEBUG -eq 1 ]]; then
    echo -e "${DIM}[DEBUG]${NC} $*"
  fi
}

# Usage
debug "Variable value: $VAR"
debug "Would execute: rm -rf $DIR"

Manual Testing

Test Cases

Create a checklist of scenarios to test:
  1. Happy path - Script works with valid inputs
  2. Missing arguments - Script handles missing required arguments
  3. Invalid arguments - Script rejects invalid options
  4. File not found - Script handles missing files gracefully
  5. Permission denied - Script handles permission errors
  6. Edge cases - Empty inputs, large files, special characters

Example test script:

#!/bin/bash
# test-backup.sh - Test backup script

SCRIPT="./backup.sh"

echo "Testing backup script..."

# Test 1: Help flag
echo "Test 1: Help flag"
$SCRIPT --help

# Test 2: Missing arguments
echo "Test 2: Missing arguments"
$SCRIPT && echo "FAIL: Should require arguments" || echo "PASS: Rejected missing args"

# Test 3: Valid backup
echo "Test 3: Valid backup"
TEMP_DIR=$(mktemp -d)
echo "test" > "$TEMP_DIR/test.txt"
$SCRIPT --source "$TEMP_DIR" --dest /tmp
if [[ -f /tmp/backup_*.tar.gz ]]; then
  echo "PASS: Backup created"
else
  echo "FAIL: Backup not created"
fi
rm -rf "$TEMP_DIR"

# Test 4: Debug mode
echo "Test 4: Debug mode"
$SCRIPT --source /tmp --debug

echo "Tests complete"

Interactive Testing

For interactive scripts (like gdrive_ingest.sh), test:

UI elements:

  • Arrow key navigation works
  • Enter/selection works
  • Quit/cancel works
  • Cursor visibility (hidden during UI, shown after)

Progress indicators:

  • Progress bars update correctly
  • Percentages are accurate
  • Cleanup happens on interruption

Error recovery:

  • Ctrl+C handling
  • Cleanup on exit
  • Cursor restoration

Testing Traps and Cleanup

Test that cleanup happens correctly:
#!/bin/bash

TEMP_DIR=$(mktemp -d)

cleanup() {
  echo "Cleaning up..."
  rm -rf "$TEMP_DIR"
}
trap cleanup EXIT INT TERM

# Do work
echo "Working in $TEMP_DIR"
sleep 5

# Try interrupting with Ctrl+C - cleanup should still run
Test scenarios:
  1. Normal exit - cleanup runs
  2. Ctrl+C (SIGINT) - cleanup runs
  3. Script error - cleanup runs
  4. Kill signal (SIGTERM) - cleanup runs

Testing Error Handling

Verify error handling works correctly:

Test with invalid inputs:

# Missing required file
./script.sh --file /nonexistent
# Expected: Error message + exit 1

# Invalid option
./script.sh --invalid-flag
# Expected: Error message + exit 1

# Missing dependency
# (temporarily rename a required command)
mv /usr/bin/jq /usr/bin/jq.bak
./script.sh
mv /usr/bin/jq.bak /usr/bin/jq
# Expected: Error message about missing jq + exit 1

Test error propagation:

# Script should exit on command failure
set -eo pipefail

# This should exit the script
false
echo "This should not print"

Testing Output

Verify color codes:

./script.sh | cat -A
# Should show ANSI escape codes like ^[[0;32m

Test stderr vs stdout:

# Errors should go to stderr
./script.sh --invalid 2>&1 | grep "Unknown option"

# Success messages should go to stdout
./script.sh > output.txt
cat output.txt

Test with no color support:

# Some environments don't support colors
TERM=dumb ./script.sh

Continuous Testing

Integrate testing into your workflow:

Pre-commit hook:

Create .git/hooks/pre-commit:
#!/bin/bash
# Pre-commit hook to validate scripts

echo "Running tests..."

for script in $(git diff --cached --name-only | grep '\.sh$'); do
  echo "Testing $script..."
  
  # Syntax check
  bash -n "$script" || exit 1
  
  # ShellCheck
  if command -v shellcheck &>/dev/null; then
    shellcheck "$script" || exit 1
  fi
done

echo "All tests passed"
Make it executable:
chmod +x .git/hooks/pre-commit

Testing Checklist

Before considering a script complete:
  • Syntax validated with bash -n
  • Static analysis with shellcheck
  • Help flag displays correctly
  • Debug mode works without making changes
  • Error messages are clear and actionable
  • Missing arguments handled gracefully
  • Invalid arguments rejected with error
  • File operations handle missing files
  • Cleanup runs on exit/interruption
  • Colors display correctly
  • No hardcoded paths (use variables)
  • Dependencies validated on startup

Common Issues and Solutions

Issue: Script works in terminal but fails in cron

Solution: Source the full environment or use absolute paths
# Bad - relies on PATH
jq .data file.json

# Good - absolute path
/usr/bin/jq .data file.json

Issue: Variables with spaces break commands

Solution: Always quote variables
# Bad
rm -rf $DIR

# Good
rm -rf "$DIR"

Issue: Pipeline failures not caught

Solution: Use set -o pipefail
set -o pipefail

# This will now exit on curl failure
curl http://example.com | jq .data

Tools and Resources

Essential tools:

  • bash -n - Syntax validation (built-in)
  • ShellCheck - Static analysis (shellcheck.net)
  • bashdb - Bash debugger for complex scripts
  • shellspec - Testing framework for bash

Online resources:

Next Steps