如何将我的 App 模块导入 MyAppUITests 文件?

How to import my App module into MyAppUITests file?

这是我的简单测试用例:

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

因为这个:

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?
    }
}

点击 UITabBarItem 后,我更改了 DBAppSettings.mode 的值,所以在这里我想访问我的 DBAppSettings.mode 属性 以检查它是否真的变了

我注意到有一件奇怪的事情,当我构建我的应用程序并检查构建的内容时,没有为我的 UITest 目标构建。重要吗?

这是 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.

由于 Apple 阻止您从 UI 测试访问您的主应用程序,您可能会考虑重新组织您的应用程序结构以存储需要检查到 UI 可以访问的位置的相关数据测试。

您可以考虑将定义和数据从您的主应用程序 class 移动到一个单独的 class,它可以由测试框架加载。

您需要在 UI 测试中访问的每个对象都必须是 UI 测试目标的一部分。这包括对象依赖性。这是一个湿滑的斜坡,而且是一团糟。

与其让你的测试知道你的应用程序,不如试着扭转它,让你的应用程序知道它正在接受测试。一种方法是使用 launchArguments 属性:

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

然后在您的应用中:

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

在您的情况下,应用可以相应地设置 NSUserDefaults。

我通过将一些东西从我的应用程序目标中提取到两个框架(模型和视图模型)中来解决无法访问的符号问题,然后我可以将它们导入到我的 UI 测试中。

至于访问 executable 的实际内存,你不能,但你可以测试应该在该模式下某处出现在屏幕上的东西。我用这个断言来例如检查是否存在 table 视图单元格:

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

由于您可以使用辅助功能,因此您可以通过这种方式访问​​相当多的内容。我想你可以添加一个不可见的标签,其中包含你的应用程序内存的转储 - 仅在测试模式下!

我也使用启动参数为 UI 测试配置我的应用程序,正如 Michael 所建议的:.