How to import my App module into MyAppUITests file

2020-03-09 07:03发布

This is my simple test case:

import XCTest
@testable import MyApp //it doesn't work

because of this:

enter image description here

class TabBarControllerTests: XCTestCase {

    override func setUp() {
        super.setUp()

        let defaults = NSUserDefaults.standardUserDefaults()
        defaults.setObject([], forKey: DBTabBarOrderedIndexesKey) //key is undefined, because of lack of my app module
        defaults.synchronize()

        continueAfterFailure = false
        XCUIApplication().launch()
    }

    func testIsOrderOfTabsSaved() {

        XCUIApplication().tabBars.buttons["Catering"].tap()
        //what next?
    }
}

Once I tap UITabBarItem I change the value of DBAppSettings.mode, so here I would like to have an access to my DBAppSettings.mode property to check if it is really changed.

I noticed that there is one weird thing, when I build my app, and check what was built, there is no build for my UITest target. Is it important?

enter image description here

5条回答
Explosion°爆炸
2楼-- · 2020-03-09 07:40

Since Apple prevents you from accessing your main application from the UI tests, you might think about reorganizing your application structure to store the relevant data which needs checking into a spot accessible to the UI tests.

You might consider moving definitions and data from your main application class to a separate class which can be loaded by the test framework.

查看更多
小情绪 Triste *
3楼-- · 2020-03-09 07:41

Rather than having your tests know about your app, try turning it around and have your app know that it's being tested. One way is to use the launchArguments property:

    app = XCUIApplication()
    app.launchArguments.append("TestMode")
    app.launch()

Then in your app:

    if NSProcessInfo.processInfo().arguments.contains("TestMode") {
        // I am running in test mode
    }

In your case the app could then set the NSUserDefaults accordingly.

查看更多
太酷不给撩
4楼-- · 2020-03-09 07:41

I solved the inaccessible symbol problem by pulling some stuff from my app target into two frameworks (model and view-model) that I can then import into my UI tests.

As for accessing the actual memory of the executable, you can't, but you can test for things that should appear on screen somewhere in that mode. I use this assertion to e.g. check for the existence of a table view cell:

XCTAssertTrue(tables.cells.staticTexts["Cell title I expect to exist"].waitForExistence(timeout: 1))

Since you can use accessibility you can access a pretty decent amount of things this way. I suppose you could add an invisible label with a dump of your app's memory-in test mode only!

I too make use of the launch arguments to configure my app for UI tests, as Michael suggested: https://stackoverflow.com/a/34469136/4789448.

查看更多
欢心
5楼-- · 2020-03-09 07:42

Every object you need access to in UI Tests must be part of the UI Test target. This includes object dependencies. It's a slippery slope, and rather a mess.

查看更多
聊天终结者
6楼-- · 2020-03-09 08:06

This is a response from Apple:

UI tests execute differently from Unit tests - Unit tests run inside your application process so they can access your application code. UI tests execute in a separate process, outside your application, so they can simulate how the user interacts with the application. It’s not expected that you will be able to access your app class from a UI test.

查看更多
登录 后发表回答