Your app works. You've been using it for weeks.
You've also been using it in one browser, on one machine, with fast internet, with your own account and your own data, doing the things you built it to do in the order you expect. That's one path through the software, and real people will find dozens you never considered.
Your laptop is a liar
The environment you build in is unusually gentle.
Your internet is quick and doesn't drop. Your phone is new. Your data is well-formed because you typed it. Your account has been through every migration you've ever run. You know which button to press.
None of that holds for the person downloading your app on a train with two bars of signal, on a three-year-old phone, with an empty account, unsure what any of it does.
The gap between those two situations is where most launch-day problems live.
Testing on a real device
For a mobile app this is the one that catches people, because a simulator on your laptop is a very convincing lie.
Things that behave differently on actual hardware: performance, obviously, but also touch targets that turned out to be too small for a thumb, keyboards covering the input you're typing into, notches and rounded corners eating your layout, permission dialogs appearing at unexpected moments, and everything to do with being offline.
Install it on your own phone. Then, if you possibly can, on someone else's, ideally an older one. An afternoon of that will find more real problems than a week of clicking around the simulator.
What's worth writing tests for
Automated tests are code that checks your code, and you don't need many.
For a first app, write them for the parts where being wrong is expensive and silent. The core thing your app does. Anything involving money. Anything calculating a number people will trust. Anything to do with who's allowed to see what.
Everything else can be checked by using the app, because you'll notice if a button looks wrong. You won't notice if a total is quietly two percent off.
One warning that's easy to fall into: a test that couldn't have failed isn't testing anything. It's very possible to write something that always passes and feels reassuring. If you write a test, make sure you've watched it fail at least once, by breaking the thing on purpose. Otherwise you've built an alarm that isn't connected.
Try to break it on purpose
Ten minutes of deliberate misuse before launch is worth a lot.
Submit an empty form. Paste a novel into a name field. Put emoji everywhere. Enter a date in the past, or the year 3000. Click submit twice quickly. Turn off wifi halfway through something. Open two tabs and do conflicting things. Log out in one, carry on in the other.
Every one of those is something a real user will do, some by accident, some because they're curious.
The double-click one deserves special mention. It's remarkably common, and if your submit button doesn't guard against it you'll get duplicate orders, duplicate records, duplicate charges.
Watching someone else use it
The highest-value testing available, and it costs nothing.
Give your app to somebody who's never seen it. Don't explain anything, don't guide, and specifically don't rescue them when they get stuck. Just watch.
It's uncomfortable. They'll hesitate at things you thought were obvious, tap things that aren't buttons, and miss the feature you're most proud of.
Ten minutes of that reveals more about your app than any amount of your own testing, because you physically cannot see your own interface with fresh eyes any more. You know too much.
A quick story. My first job dropped me straight onto a website serving about two million users. Not a gentle onboarding.
What that teaches you very quickly is a different relationship with the word "works." At that scale, something that fails for one user in a thousand is failing for two thousand people. An edge case stops being a curiosity and becomes a queue of angry support tickets.
You don't have two million users, and you don't need that level of paranoia. But the habit worth borrowing is asking "what happens when this goes wrong" as a normal part of building, rather than as a separate phase you do at the end and often skip.
If you want help finding what's broken
Point four is the one that catches genuinely invisible bugs. Your account isn't representative, and neither is your timezone.
Next: The security stuff you can't skip →
Go deeper: Chapter 28, Testing and Verification and Chapter 29, Debugging