XCTest/Swift Automation: How can I determine if an app is present before testing?

48 Views Asked by At

I'm doing UI automation using XCTest on an iOS app that has different bundle Id's depending on how it was provisioned and my tests need to support that. Before tests begin, trying to call a method that will check if they exist but can't find anything that works.

I've checked the springboard, but both icons are defined the same. Tried checking Bundle.allBundles but they don't show apps behind their sandbox. My last attempt has been to launch the test and try to catch it when it fails.

Resorting to ChatGPT; it claims that if I wrap in XCTContext the failure will not wipe the test but that seems spurious from my attempts, even when continueAfterFailure is true. It also suggested something like the code below but launch does not throw either, so this won't even compile...

    continueAfterFailure = true
    
    var ipaIsNotPresent = false
    let ipaBuild = XCTContext.runActivity(named: "Checking for IPA") { _ in
        do {
            setCurrentApp(.ipaVersionBundleId)
            try app.launch()
        } catch {
            ipaIsNotPresent = true
        }
    }
    
    if ipaIsNotPresent {
        var testFlightIsNotPresent = false
        let testflightBuild = XCTContext.runActivity(named: "Checking for TestFlight version") { _ in
            do {
                setCurrentApp(.testFlightBundleId)
                try app.launch()
            } catch {
                testFlightIsNotPresent = true
            }
        }
        
        if testFlightIsNotPresent {
            isAppInstalledAtAll = false
        } else {
            isAppTestFlightVersion = true
        }
    }

Also tried this, but I think bundle will always be nil if running from a test runner that is in its own project:

    if Bundle(identifier: BundleId.ipaVersionBundleId.rawValue) == nil {
        if Bundle(identifier: BundleId. testFlightBundleId.rawValue) == nil {
            isAppInstalledAtAll = false
        } else {
            isRunningAgainstTestFlightBuild = true
        }
    } else {
        isRunningAgainstTestFlightBuild = false
    }

If someone can suggest an easier / better way to detect the bundle under test, I'm quite happy to do so instead. Otherwise, is it possible to handle the launch failure so I can use that information?

If needs be I could move this into its own test rather than setup function, and then I think I can ignore that test's failing. I can also make changes in the app, but by then I assume it's too late.

To clarify again, my question is How can I detect if an app is present before running tests? Any alternatives to the code I'm trying is perfectly acceptable as an answer.

1

There are 1 best solutions below

0
Mercutio On

Ok, after trying several different approaches (including expected failures with isStrict option to false) it turned out to be trivial:

let firstId = "com.blah.blahBlah"
let secondId = "com.blah.internal.blahBlah"

var app = XCUIApplication(bundleIdentifier: firstId)
isAppTestFlightVersion = app.exists

app = XCUIApplication(bundleIdentifier: secondId)
isAppInstalledAtAll = isAppTestFlightVersion || app.exists

if !isAppInstalledAtAll {
    isAppTestFlightVersion = true
}