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

tct7dpnv  于 2023-06-25  发布在  iOS
关注(0)|答案(9)|浏览(112)

自从Xcode 7以来,我们有了一个很好的UI测试API。基本上我对它很满意。唯一的问题是速度。
一开始,一个普通的UI测试用例(大约15个动作)运行了大约25秒。然后我完全嘲笑了网络。现在需要20秒。考虑到时间仅由动画和启动时间(1秒或更少)所花费的事实,我假设,必须有一种方法来加速它。

w9apscun

w9apscun1#

尝试在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中有一些更方便的提示。

az31mfrm

az31mfrm2#

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

[UIView setAnimationsEnabled:NO];

Swift 3:

UIView.setAnimationsEnabled(false)
b5lpy0ml

b5lpy0ml3#

在@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()
isr3a4wc

isr3a4wc4#

在didFinishLaunch中添加

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

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

qvsjd97n

qvsjd97n5#

并行运行它们。
编辑:这可能已经过时了,因为我在2019年的原始答案,因为Xcode现在允许在一台机器上测试多个模拟器:
如果您只有一台构建计算机,则可以使用Bluepill:https://github.com/linkedin/bluepill
编辑:然而,我不使用这两个(bluepill / Xcode),所以我会在这个答案中继续提到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并进行持续几秒钟的测试(但它们不会是黑盒)。
1.如果你有深层链接,通过深层链接打开屏幕。
1.使用大量的私有API和其他黑客。例如:而不是通过UI到设置应用程序,然后重置隐私设置,你可以调用一些私人API。
1.千万不要睡太久。使用轮询。
1.加速动画。不要禁用它们!(我们在每个视图上使用layer.speed = 100,我们在值为10000时遇到了严重的问题,完整代码:https://pastebin.com/AnsZmzuQ
1.将一些标志从UI测试传递到应用程序,以跳过初始警报/教程/弹出窗口。可以保存很多时间。确保至少有一个测试来检查这些警报是否有效。
广告:其中大部分是在https://github.com/avito-tech/Mixbox中实现的。免责声明:我是这个测试框架的主要贡献者。设置起来很繁琐,但如果不想重用整个框架,至少可以重用一些代码。

svujldwt

svujldwt6#

我想在快照测试期间禁用所有动画。我能够通过禁用核心动画和UIView动画来实现这一点,如下所示。
请注意,因为我的应用程序使用了故事板UIApplication.shared.keyWindow在启动时为nil,所以我直接引用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
}
q1qsirdb

q1qsirdb7#

我减少我的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)
cvxl0en2

cvxl0en28#

请注意,keyWindow自iOS 13起已弃用。具体来说,AppDelegate中的UIApplication.sharedApplication.keyWindowself.window.keyWindow都返回nil。This answer说循环遍历UIApplication.shared.windows并找到具有isKeyWindow的那个为true,但在我使用ios14的测试中,即使是这样,我唯一的窗口也返回false。最后,设置self.window.layer.speed对我来说很有用。

wfypjpf4

wfypjpf49#

您可以通过在UI测试代码中设置以下整数UserDefault来提高键入速度(从而加快测试速度):

UserDefaults.standard.set(-1, forKey: "com.apple.xctest.iOSMaximumTypingFrequency")

我本来有问题的字符被跳过,所以正在寻找一种方法来放慢打字。我发现低于80的任何东西都解决了我的问题。但也发现-1瞬间进入文本,也很高的数字如6000。
这在任何地方都没有记录,所以行为可能会随着Xcode/iOS的新版本而改变。我在iOS 16上运行了Xcode 14.3的模拟器

相关问题