How can I change launchEnvironment dictionary after UI test launching?

168 views Asked by At

I use special server to substitute real url server responses (like Swifter). I send bunch of url path and new substitution url to launchEnvironment before app launching:

func launchNewApp(serverManager: ServerManagerProtocol) -> XCUIApplication {
    let app = XCUIApplication()
    app.launchArguments += ["UI-TESTING"]
    serverManager.routeInfo.forEach {
        app.launchEnvironment[$0.key] = $0.value
    }
    app.launch()
    return app
}

My test launch the app, into my app I substitute urls and my app get mocked server response:

extension URLRequest {
    private var isUITestingLaunching: Bool {
        ProcessInfo.processInfo.arguments.contains("UI-TESTING")
    }

    mutating func tryReplaceUITestRequest() {
#if DEBUG
        if isUITestingLaunching,
           let path = url?.path,
           let substitutionuUrlString = ProcessInfo.processInfo.environment[path],
           let substitutionuUrl = URL(string: substitutionuUrlString) {
            url = substitutionuUrl
        }
#endif
    }
}

Now I desire to substitute mocked url in test runtime:

  1. I set launchEnvironment and launch app

  2. I analyze UI recieved from the data from mock response

  3. I change may url in launchEnvironment

  4. I do pull to refresh in app

  5. I see new UI (because in new mock url response receive new data)

    func testExample() throws {
        // 1 launch app
        let app = XCUIApplication()
        app.launchArguments += ["UI-TESTING"]
        app.launchEnvironment["HomeSceneStructureUrlPath"] = "http://localhost:9000/SomeUrlPath"
        app.launch()

        // 2 test UI
        ...
        XCTAssertFalse(someElement.waitForExistence(timeout: 100))

        // 3 change launchEnvironment
        app.launchEnvironment["HomeSceneStructureUrlPath"] = "http://localhost:9000/OtherUrlPath"

        // 4 do PULL TO REFRESH
        let firstCell = app.tables["someTable"].cells.firstMatch
        let start = firstCell.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
        let finish = firstCell.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 10))
        start.press(forDuration: 0, thenDragTo: finish)

        // 5 test updating UI
        ...
        XCTAssertTrue(settingsButton.waitForExistence(timeout: 100))
    }

But my step 3 doesn't work, I can't change launchEnvironment in test runtime. Do you have any ideas how this can be done? Or maybe there is another way to send the mock url from the Test target to the Project target? I will be grateful you for an answers.

1

There are 1 answers

0
Mike R On

Per Apple docs, changing the environment variables will not take effect for the currently launched app:

Unlike Process, it is also legal to modify the environment variables after the application has been launched. Such changes will not affect the current launch session, but will take effect the next time the application is launched.

I'm not sure of a good way to update the UI besides hacking/mocking whatever class is performing the call to call the updated URL when the response from the first is received.