Quality · Testing
Unit Tests Pay for Themselves — and UI Tests Belong on Real Devices
Testing is routinely the first thing cut from a mobile budget, because its value is invisible until the day it isn't. Here's how we think about the testing pyramid in practice — from unit tests on business logic to Appium-automated UI tests running on a device farm.
The argument clients actually care about
The honest sales pitch for testing is not "quality" in the abstract — it's speed, later. An app with no tests is fast to change in month one and terrifying to change in month twelve: every modification risks breaking something invisible, so every release needs a full manual click-through, so releases become rare and large and riskier still. Tests invert that curve. They are the reason a mature codebase can still ship confidently every week.
We saw this concretely on Invoice Guru: a partial rewrite of a live invoicing app is only a responsible thing to attempt when tests pin down the behaviour that must not change — clients, items, and VAT-correct totals. The tests weren't overhead on that project; they were the safety harness that made the project possible.
Unit tests: cheap, fast, and aimed at the logic that matters
We don't chase coverage percentages. We aim unit tests at the code where a silent mistake costs real money or trust: pricing and VAT calculations, date and currency handling, data transformations, state transitions. This is also where unit tests are cheapest — pure logic with no UI attached, running in milliseconds on every change.
This is one reason architecture and testing are the same conversation: logic that lives in providers, repositories, and services (rather than inside widgets) is logic a test can reach. A codebase that is hard to unit test is almost always announcing an architecture problem, not a testing problem.
UI tests on a device farm: because emulators lie
Above the unit layer, the question changes from "is the logic right?" to "does the app actually work on the phone in the user's hand?" — and no emulator answers that honestly. Android fragmentation is real: manufacturers ship their own Android skins, aggressive battery managers kill background work, screen sizes and densities vary wildly, and OS versions stay in circulation for years. iOS is gentler but not exempt — notches, dynamic type, and OS updates all break layouts that looked fine in the simulator.
That's why our end-to-end UI tests are automated with Appium and run on a device farm — real physical devices across manufacturers, screen sizes, and OS versions. Appium drives the app the way a user does: taps, swipes, text entry, assertions on what's actually on screen. The critical flows — sign-in, the core value path, payment — get exercised on the device matrix before a release, not by a human with a checklist on whatever phone was on the desk.
What we automate — and what we deliberately don't
Automation has a maintenance cost, so the e2e suite stays small and high-value: the flows where a regression would be an incident, not an inconvenience. Below that, widget tests cover screens with meaningful logic, and unit tests carry the bulk of the pyramid. Exploratory testing — the weird, creative, human kind — stays human; automation frees testers for it rather than replacing them.
The release rule that falls out of all this is simple: the pipeline runs the suite, the device farm runs the critical flows, and a red result blocks the release. No exceptions on a deadline — the deadline is exactly when the discipline earns its keep.
Takeaways
- ✓Tests are a speed feature: they're what keeps releases fast and calm in month twelve, not a tax paid in month one.
- ✓Aim unit tests at money-and-trust logic — pricing, VAT, dates, data transformations — not at a coverage percentage.
- ✓Hard-to-test code is an architecture smell; testable logic lives outside widgets, in providers and services.
- ✓Emulators don't represent reality — run critical-flow UI tests with Appium on real devices across the fragmentation matrix.
- ✓Keep the e2e suite small and ruthless: automate the flows where a regression is an incident, and let red block the release.
Building something where this matters?
This is how we work on every project — mobile, web, and AI. If you want a team that reasons this way about your product, let's talk.
Get a free estimate