KeyMob
All articles

A real-device QA workflow that produces reproducible tickets

3 min readQADebugging

The gap between QA and engineering is usually not about effort. A tester sees the bug, but a developer receives only a sentence about it.

This article describes how to close that gap while the device is still in the tester’s hands.

The limits of a good bug report

Even a careful report with steps, expected and actual results, and a screenshot leaves out most of what was on the device at the time: the log around the failure, what the app was doing in the two seconds before, whether memory was climbing, the iOS build, how full the storage was, and whether the phone was hot.

A developer who cannot reproduce the bug has to guess all of this, one question at a time, over a week of comments.

Capture while it happens

The device is right there. Capture four things:

1. The log around the failure

Capture only the relevant part of the session: clear, reproduce, stop, save. A log that starts ten minutes early is almost as unhelpful as no log, because nobody will read it. Filter to the app under test, and note the filter in the ticket.

2. A performance capture, for performance bugs

Capture ten seconds on either side of the stutter, freeze or crash. This is the difference between “it was slow” and “CPU spiked to 90% for 400 ms during the transition”.

3. Screenshots on a timer

For visual, intermittent issues, a series at 500 ms intervals catches what a manual screenshot will miss. Start it, reproduce the issue, then stop.

4. Device state

Record the iOS build, model, free storage, battery health, installed profiles, locale and accessibility settings. Copy them into the ticket exactly. This section resolves “cannot reproduce” more often than any other.

The template

Keep it short enough that people actually fill it in.

Summary:
Steps:
Expected / Actual:
Device: iPhone 12, iOS 17.4.1
Storage: 4.2 GB free
Battery: 84%, 612 cycles
Build: 2.8.0 (412)
Profiles: none unexpected
Locale: en-GB, Dynamic Type default
Attached: filtered log (filter: [Feed])
performance capture (10s around the stutter)
screenshot burst (500 ms)

Six lines of device state and three attachments. It takes more work than a screenshot, and much less than a week of back-and-forth.

Two checks before filing

Try it on a second device. If it reproduces on both, say so. That rules out a whole line of investigation. If it does not, you have already found the most valuable fact in the ticket, and the device-state section is where the answer will be.

Check the crash list. If the app disappeared rather than misbehaved, there is a crash report on the device. Attach it. A report with a matching dSYM can turn a two-day investigation into a five-minute one.

Working with someone else’s device

When the phone belongs to a customer rather than the team, everything above still applies, with one extra rule: take only what you need.

  • Logs and performance captures are usually fine.
  • Screenshots may contain personal data. Review them before attaching.
  • An app container or device backup contains the owner’s personal data. Export one only with explicit permission, take only what answers the question, and delete it when the ticket is closed.

The usual problem is not bad intent. It is exporting a container to debug something, finishing the work, and forgetting the folder exists.

The result

A team that does this consistently files tickets that developers can act on the same day, and builds a collection of captures that makes the next occurrence of a bug much faster to identify. The cost is about four extra minutes per report, spent while the bug is in front of you and the information is easy to collect.