xcodebuild says TEST SUCCEEDED, the xcresult says "Issues recorded without an associated test or suite"

·4 mins

A branch passed locally. xcodebuild test exited 0 and printed:

** TEST SUCCEEDED **

The fastlane coverage lane on the same branch failed with Tests have failed and didn’t name a test. Scan’s xcpretty output doesn’t show Swift Testing results, so the log didn’t include any failing tests. The result bundle had the answer:

xcrun xcresulttool get test-results summary --path Test.xcresult
{'result': 'Failed', 'totalTestCount': 2320, 'passedTests': 2317, 'failedTests': 1, ...}
testName: Issues recorded without an associated test or suite
failureText: Issue recorded: failed - Unimplemented: Unimplemented AppVersionClient.currentVersion …
  This issue was emitted from tests running in a host application.
  This can lead to false positives, where failures could have emitted from live application code at launch time, and not from the current test.

If your console is green and fastlane, Xcode Cloud or anything else that reads the .xcresult is red, check the summary for that pseudo-test before you go looking for a flaky test.

Setup

  • Xcode 26, Swift Testing, an app-hosted unit test target (tests run inside the real app process).
  • swift-dependencies 1.14, with a client whose testValue calls IssueReporting.unimplemented(...). That’s the usual way to make sure a test sets every dependency it uses.
  • The app’s root view is a login screen. On appear, it asks a backend for the minimum supported version and compares it with currentVersion().

What happened

Because the app hosts the tests, it launches as it does for a user, and its login screen sends the version request. When the response arrives, the screen reads the version client inside a test process, which resolves to the unimplemented test value and records an issue. No test is running on that code path, so the issue gets attached to no test.

The console run only shows it as a warning:

⚠︎ Test «unknown» recorded a warning at VersionClient.swift:24:1: Issue recorded
↳ failed - Unimplemented: Unimplemented AppVersionClient.currentVersion …

The result bundle counts it as a failure, though, and fastlane reads it.

Main didn’t fail, and the new branch didn’t touch any of this code. Its only addition was a new app-hosted suite that took about seven seconds. That extra time let the response arrive while tests were still running. On main, the run was over before the response came back. This is timing-dependent, so a faster backend or a slower one can hide the failure or bring it back.

Reproduce one target and compare the result bundle summaries:

RunTotalFailed
Hosted target, as is211
Same, new suite skipped (-skip-testing)160
Same, with the fix200

The 21 in the first row is 20 real tests plus the pseudo-test.

Dead end: set the dependency at launch

The obvious fix is to give the app a live value in its entry point:

prepareDependencies {
    $0.appVersion = AppVersionClient { Bundle.main.shortVersion }
}

It built and changed nothing. The same failure showed up again. In a test process, swift-dependencies resets its cached values for each test: it registers an XCTest observer that clears the cache whenever a test case starts. The value you prepare at app launch is gone once the tests start, and the later response reads the test value again.

Fix: don’t show the app UI while hosting tests

isTesting from IssueReporting (re-exported by Dependencies) is true inside a test process. Gate the scene’s content on it:

import Dependencies
import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            // Unit tests run inside this app. Its login screen would start a
            // network request whose response reads an unimplemented test dependency.
            if !isTesting {
                RootView()
            }
        }
    }
}

This is the workaround in the library’s Testing gotchas docs. Before applying it, check that no hosted test needs the app’s window or a view in the scene. Here, none did, because the tests only needed a real UIApplication, which still exists with an empty WindowGroup. The shipping app is unchanged, since isTesting is false outside a test run.

With the fix, the hosted target passed 20 of 20, the whole coverage lane reported 0 failures on both schemes, and the test run stopped sending requests to the dev backend.

That last part is a nice bonus. A test host that shows its real UI talks to real servers from your CI, and anything it logs (request and response bodies, anti-forgery tokens) ends up in your test logs.

Takeaway

An app-hosted test run also runs your app. Anything the app starts on its own at launch can record a failure that belongs to no test and shows up only in the .xcresult. Keep the UI out of the test host with if !isTesting, and when the console and the lane disagree, read xcresulttool get test-results summary first.

Try it on your own app-hosted target: grep a recent test log for Test «unknown» recorded. Each hit is an issue recorded outside any test, and the result bundle may already count it as a failure.