如何在Xcode中加速UI测试用例?

问题描述 投票:16回答:7

从Xcode 7开始,我们有一个很好的用于UI测试的API。大多数情况下我对它很满意。唯一的问题与速度有关。

在一开始,普通的UI测试用例(大约15个动作)运行大约25秒。然后我完全嘲笑网络。现在需要20秒。考虑到时间只取决于动画和启动时间(1秒甚至更短),我想,必须有办法加快速度。

ios objective-c xcode7 xctest uitest
7个回答
26
投票

在UI测试运行时尝试设置此属性:

UIApplication.shared.keyWindow?.layer.speed = 100

这是我如何设置它:

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    if ProcessInfo.processInfo.arguments.contains("UITests") {
        UIApplication.shared.keyWindow?.layer.speed = 100
    }
}

在我的UI测试中:

class MyAppUITests: XCTestCase {

    // MARK: - SetUp / TearDown

    override func setUp() {
        super.setUp()

        let app = XCUIApplication()
        app.launchArguments = ["UITests"]
        app.launch()
    }
}

这个blog post还有一些方便的提示。


8
投票

另一种可能性是禁用动画:

[UIView setAnimationsEnabled:NO];

斯威夫特3:

UIView.setAnimationsEnabled(false)

4
投票

关注@Mark回答,Swift 3版本:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    if ProcessInfo.processInfo.arguments.contains("UITests") {
        UIApplication.shared.keyWindow?.layer.speed = 200
    }
}

在你ui测试文件:

override func setUp() {
    super.setUp()

    // Put setup code here. This method is called before the invocation of each test method in the class.

    let app = XCUIApplication()
    app.launchArguments = ["UITests"]
    app.launch()

2
投票

在didFinishLaunch中添加它

[UIApplication sharedApplication].keyWindow.layer.speed = 2;

默认值为1,使其速度加倍2倍。


2
投票

我想在快照测试期间禁用所有动画。我能够通过禁用Core Animation和UIView动画来实现这一点,如下所示。

请注意,因为我的应用程序使用故事板UIApplication.shared.keyWindow在启动时为零,所以我通过直接引用window属性来访问UIWindow。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    if ProcessInfo.processInfo.arguments.contains("SnapshotTests") {
        // Disable Core Animations
        window?.layer.speed = 0
        // Disable UIView animations
        UIView.setAnimationsEnabled(false)
    }
    return true
}

1
投票

并行运行它们。

如果您只有一台构建机器,则可以使用Bluepill:https://github.com/linkedin/bluepill

如果您有多台机器,可以使用Emcee:https://github.com/avito-tech/Emcee(它也适用于单机设置)

我们有50小时的UI测试,而Emcee允许我们在1小时内运行它们。有一些技巧可以让UI测试更快,但如果你没有并行运行它们就毫无意义。例如。你不能让你的25秒测试在0.5秒内运行。


技巧:

  1. 运行XCUIApplication而不重新安装它:
XCUIApplication(
    privateWithPath: nil,
    bundleID: "your.bundle.id"
)

注意:每次启动XCUI测试运行器时,您应该使用XCUIApplication().launch()启动应用程序至少一次以安装应用程序。这需要使用私有API。

  1. 你可以把东西移到后台线程。例如。
let someDataFromApi = getSomeData() // start request asynchronously and immediately return
launchApp() // this can be few seconds
useInTest(someDataFromApi) // access to data will wait request to finish

你可以让代码看起来没有异步的东西,它会更容易QA。我们希望实现这一点,但我们没有,所以这只是一个想法。

  1. 切换到EarlGrey并进行持续几秒钟的测试(但它们不会是黑盒子)。
  2. 如果您有深层链接,请通过深层链接打开屏幕。
  3. 使用很多私有API和其他黑客。例如:不是通过UI进入设置应用程序,然后重置隐私设置,您可以调用一些私有API。
  4. 永远不要长时间睡觉。使用轮询。
  5. 加快动画速度。不要禁用它们!
  6. 将一些标记从UI测试传递到应用程序以跳过初始警报/教程/弹出窗口。可以节省很多时间。确保至少有一个测试可以检查这些警报是否有效。

0
投票

我将我的UITests时间缩短了30%,请按照以下步骤操作:

运行应用程序时,添加参数:

let app = XCUIApplication()

override func setUp() {
    super.setUp()

    continueAfterFailure = false
    app.launchArguments += ["--Reset"]
    app.launch()
}

现在,在你的AppDelegate中添加:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    setStateForUITesting()
}

static var isUITestingEnabled: Bool {
    get {
        return ProcessInfo.processInfo.arguments.contains("--Reset")
    }
}

private func setStateForUITesting() {
    if AppDelegate.isUITestingEnabled {
        // If you need reset your app to clear state
        UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)

        // To speed up your tests
        UIApplication.shared.keyWindow?.layer.speed = 2
        UIView.setAnimationsEnabled(false)
    }
}

在您的代码中,要验证是否处于测试模式,您可以使用:

if AppDelegate.isUITestingEnabled {
    print("Test Mode")
}

另外,在我创建此扩展的元素加载时可以wait

import XCTest

extension XCUIElement {
    func tap(wait: Int, test: XCTestCase) {
        if !isHittable {
            test.expectation(for: NSPredicate(format: "hittable == true"), evaluatedWith: self, handler: nil);
            test.waitForExpectations(timeout: TimeInterval(wait), handler: nil)
        }
        tap()
    }
}

使用这样:

app.buttons["start"].tap(wait: 20, test: self)
© www.soinside.com 2019 - 2024. All rights reserved.