How to capture device logs, video, and screenshots from failed mobile tests

Reading Time : 6 min read
capture device logs from failed mobile tests

A bug report that says “login failed on the Pixel” is an invitation to a Slack thread. The developer asks for logs. QA reruns the test. The failure doesn’t reproduce. Someone asks, “Is it my app, or your rig?” and a day disappears.

The fix is a failure evidence pipeline: every failed run automatically produces device logs, a screenshot, and a video, and those artifacts land in the ticket without anyone hunting for them. Here’s how to build one for Android, iOS, and hosted device clouds.

Set a failure evidence standard before you write any code

Decide what every failed test must produce. I use three items:

  • Device logs: what the app and the OS were doing (logcat on Android, system and app logs on iOS).
  • A screenshot: the exact UI state at the moment of failure.
  • A video: the full journey, which shows timing, animations, and the step before things went wrong.

Logs explain why, the screenshot shows what, and the video shows when. A developer who gets all three rarely needs to ask a follow-up question. That is the whole point of the standard: fewer “can you rerun it?” messages and fewer arguments about whether the failure came from the app or the test environment.

Android: hook screenshots and logcat into the failure path

For Espresso, you have two solid options. A custom FailureHandler runs when a view assertion or interaction fails, so it’s the right place to grab a screenshot and dump logcat. A JUnit TestWatcher with an overridden failed() method works for any failure in the test, including ones outside Espresso’s view matchers.

For UI Automator, call UiDevice.takeScreenshot() in your failure path and use executeShellCommand(“logcat -d”) to dump the log buffer. If you drive tests from a host with adb, adb logcat -d, adb exec-out screencap -p, and adb shell screenrecord cover the same ground.

Video needs a reality check. You can’t pull a recording from nowhere after a test fails. Start screenrecord when the test starts, then keep the file if the test fails and delete it if it passes. Note that screenrecord has a built-in time limit per file, so long tests need chunked recordings.

Use Tradefed collectors if you run tests through it

Don’t rebuild this plumbing if your CI uses Tradefed. The Android Open Source Project documents “log on failure” behavior, stating that debugging a test always needs a baseline set of logs, including Logcat and the Tradefed host log. It also ships a ScreenRecordOnFailureCollector that runs screenrecord while a test case executes and logs the recording when that case fails. Built-in collectors give you consistent output across every job, which beats a pile of one-off scripts.

iOS: let Xcode Test Plans do most of the work

For XCUITest, open your Test Plan and set screenshots and screen recordings to keep “On Failure.” Xcode then attaches them to failed tests and surfaces them in the test report. Check that the plan is applied to the right target and scheme. A misapplied plan is the most common reason nothing shows up.

For finer control, attach artifacts yourself with XCTAttachment, and set its lifetime to keep it. You can do this inside a test’s failure path to add a screenshot, a log excerpt, or a custom file. Both approaches give you artifacts in the result bundle that CI can export.

If you drive either platform with Appium, the same logic applies. Call the screenshot and log retrieval commands from your test framework’s failure hook (a pytest fixture, a TestNG listener, a JUnit extension), and use the driver’s screen recording commands, started at test start, for video.

Device clouds: flip the debugging options, then download fast

Hosted platforms usually generate artifacts through capabilities. BrowserStack App Automate is a clear example for Espresso. Instrumentation logs are always on. Device logs are off by default and need deviceLogs. Network logs need networkLogs. Video is on by default and disabled with video: false. Screenshots require Spoon framework integration through enableSpoonFramework.

Retention is the catch. BrowserStack’s Espresso docs state that videos are kept for 30 days and other data for 60 days. Its XCUITest docs also say video is deleted after 30 days. If your bug triage takes longer than that, the evidence is gone, so download artifacts as part of the pipeline.

One more planning note: Firebase Test Lab’s documentation now carries a notice that the service shuts down on September 30, 2027. If your evidence pipeline depends on it, plan the migration now.

A simple rule for what to enable:

Run typeLogsScreenshotsVideo
Per-commit CIDevice logsOn failureRecord, keep on failure
Nightly regressionDevice and network logsOn failureRecord, keep on failure
Deep debuggingEverythingEverythingEverything

Kobiton approaches this differently because the evidence lives with the real-device session. Session Explorer captures and surfaces issues from a test session, and its one-click Jira bug filing pre-populates logs, device details, and session context. It works with Appium, XCUITest, and Espresso, so the developer opens one ticket instead of five attachments.

Package the evidence so nobody attaches files by hand

Collection is half the job. Three habits finish it:

  • Name files with context. Include test name, device model, OS version, and build ID, for example checkout_pixel8_android15_build4821.mp4.
  • Upload to one place. Use your CI artifact store or a reporting tool such as Allure or ReportPortal, and link from the result.
  • Template the ticket. Reproduction steps, expected versus actual, links to logs and video, and the timestamp where the failure begins.

That timestamp matters more than it sounds. Nobody wants to watch four minutes of video to find the broken step.

Troubleshooting empty or missing artifacts

Check these first:

  • Blank Android screenshots: screens using FLAG_SECURE block capture by design.
  • Missing files: storage permissions or the wrong pull path often block retrieval.
  • Thin logs: logcat may be cleared or limited. Dump the right buffers and capture before the test clears them.
  • iOS nothing attached: confirm the Test Plan is active for the scheme you’re running.
  • Cloud runs with no logs: confirm the debugging capabilities were set, and that retention hasn’t expired.

Make every failure explain itself

Artifact automation isn’t a nice-to-have. It’s what stops triage from turning into detective work, and it moves your team’s time from proving innocence to fixing bugs.

Pull your last three bug reports and check each for logs, a screenshot, and a video. If any are missing, pick one suite, wire in the hooks above, and run a pilot for a week. Then count how many follow-up questions you didn’t get asked.

Interested in Learning More?

Subscribe today to stay informed and get regular updates from Kobiton

Ready to accelerate delivery of
your mobile apps?

Request a Demo