BLOG / January 2, 2026

How I learned to break my own app

Testing apps like your least technical family member would

@jamditis
8 min read

So you've built something. It works on your machine. Tests pass. CI is green. Ship it, right?

Not so fast.

I just finished stress-testing AudioBash, an Electron app for voice-controlled terminal sessions. Everything looked solid until I started pretending to be my least tech-savvy family member.

Think like someone who doesn't think like you

Developers use software correctly. We click buttons once. We wait for things to load. We read error messages.

Regular users? They double-click everything, paste 50KB of text into a single field, resize your window to 100x100 pixels, then force-quit when it doesn't respond instantly.

The goal isn't to blame users. It's to build software that doesn't break when someone uses it wrong.

What I tested

For AudioBash, I ran through scenarios that seem absurd until you realize someone will do them:

The impatient double-click

# User opens app, nothing happens (they think), clicks again... and again
open "App.app"
open "App.app"
open "App.app"

Does your app handle this? AudioBash uses Electron's app.requestSingleInstanceLock() to ensure only one instance runs. The second/third launches just focus the existing window.

The giant paste

# User copies their entire server log and pastes it
python3 -c "print('X' * 50000)" | pbcopy
# Then Cmd+V

50,000 characters. Does your input field survive? Does the UI freeze? Does the app crash? AudioBash handled this fine, but I've seen apps completely lock up.

The window torturer

# Resize to something ridiculous
osascript -e 'tell application "System Events" to tell process "MyApp" to set size of window 1 to {100, 100}'
# Then blow it up
osascript -e 'tell application "System Events" to tell process "MyApp" to set size of window 1 to {2500, 1600}'

Responsive design doesn't mean "pretty at 1920x1080". It means "doesn't explode at any size."

The force quit recovery

This one caught me. After force-quitting AudioBash (pkill -9), the app wouldn't relaunch. Silent failure. No error. Just... nothing.

Turns out Electron's singleton lock files were left behind in ~/Library/Application Support/audiobash/. The app saw the lock, assumed another instance was running, and exited quietly.

The fix? Electron actually handles this automatically by detecting stale locks. But knowing why it happens is crucial for debugging.

The checklist

After this experience, I formalized my approach. Here's the framework:

1. Installation and first run

  • Can it run from a DMG without installing?
  • What happens with Gatekeeper/quarantine?
  • Does it need special permissions? Does it ask nicely?

2. Concurrency

  • Multi-instance prevention
  • Tab spam (Cmd+T x 20)
  • Rapid open/close cycles

3. Input abuse

  • Huge pastes (10KB, 50KB, 200KB)
  • Special characters (emoji, unicode, RTL text)
  • Rapid keypress spam

4. Window manipulation

  • Extreme resize (tiny and huge)
  • Minimize/restore cycles
  • Multi-monitor edge cases

5. Recovery

  • Force quit and relaunch
  • Stale lock file recovery
  • Crash log detection

6. Resource exhaustion

  • Memory usage over time
  • File descriptor leaks (for apps with sockets/streams)
  • CPU when idle

Automating it

I wrote a test script that runs through the basics automatically:

#!/bin/bash
# Quick sanity check

APP_PATH="${1:-dist/mac-arm64/MyApp.app}"
PASSED=0
FAILED=0

test_result() {
    if [ $1 -eq 0 ]; then
        echo "OK $2"
        ((PASSED++))
    else
        echo "FAIL $2"
        ((FAILED++))
    fi
}

# Test 1: Does it launch?
open "$APP_PATH"
sleep 4
pgrep MyApp > /dev/null
test_result $? "Basic launch"

# Test 2: Single instance?
open "$APP_PATH"
open "$APP_PATH"
sleep 2
COUNT=$(pgrep MyApp | wc -l | tr -d ' ')
[ "$COUNT" -le 5 ]  # Adjust for your process count
test_result $? "Single instance enforced"

# Test 3: Survives large paste?
python3 -c "print('X' * 50000)" | pbcopy
osascript -e 'tell application "System Events" to keystroke "v" using command down'
sleep 2
pgrep MyApp > /dev/null
test_result $? "Survives large paste"

# Cleanup
pkill MyApp 2>/dev/null

echo ""
echo "Passed: $PASSED"
echo "Failed: $FAILED"

It's not everything, but it catches the obvious stuff.

Claude Code skills

I made skill files for this. Grab them if you want:

See the AudioBash testing skill for an example.

We build for makers, but also for beginners who want to become makers. Test for both.

Resources