AutomationTools-Host 5.0.0

AutomationTools-Host 5.0.0

Alberto De Bortoli维护。



  • Alberto De Bortoli和Sneha Narayana Swamy

AutomationTools

Core

CI Status Version License Platform

Host

CI Status Version License Platform

关于

AutomationTools是一个框架,帮助您编写更佳且更易于维护的UI测试。它允许启动应用,注入标志以加载正确的配置和自动化重复操作(例如填写篮子、用户登录等)。用于将从测试案例注入状态到待测试应用中的机制是通过使用启动参数和环境变量。启动参数是以字符串数组的形式传递给XCUIApplication的启动方法的,而环境变量则作为字典传递。

除了状态配置功能之外,AutomationTools还包含我们在测试套件中使用的最常用功能。诸如页面对象基类、合理的等待方法以及XCUIApplication的扩展等,都意味着我们的测试套件易于维护,可读性高、灵活且代码可重用。

AutomationTools 包含 2 个 Pod:AutomationTools-Core 和 AutomationTools-Host。Core 包含应用状态配置、基本类和实用工具。Host 通过展开测试用例注入的标志提供了一个测试用例和应用之间的桥梁。使用 2 个独立的 podspec 而不是 subspec 的原因是支持 Apple 的新构建系统。CocoaPods 对从 subspec 生成的框架的命名有已知的 限制

Core

  • ATTestCase.swift 是从 XCTestCase 继承的基础类,用于所有 UI 测试套件。它保存对 XCUIApplication 的引用并提供一个 launchApp 方法,用于从测试运行应用。
launchApp(featureFlags: [Flag] = [], 
          automationFlags: [Flag] = [], 
          envVariables: [String : String] = [:],
          otherArgs: [String] = [])

我们将标志数组传递给 launchApp 方法,然后使用 LaunchArgumentBuilder 通过添加适当的 "EPHEMERAL" 和 "AUTOMATION" 前缀并转换为字符串表示来打包。

  • LaunchArgumentsBuilder.swiftExtensionXCUIApplication.swift 中使用了以下 2 个公开方法
static public func launchArgumentForEphemeralConfiguration(_ ephemeralConfiguration: NSDictionary) -> String
static public func launchArgumentForAutomationConfiguration(_ automationConfiguration: NSDictionary) -> String

这里有一个巧妙的技巧:由于 UI 测试进程到应用进程的信息是通过 ProcessInfo.processInfo.arguments 传递的,它是类型为 [String] 的,我们将标志的字典转换为单个字符串表示并进行打包/解包。我们为功能标志和自动化标志分别传递单独的数组。功能标志驱动决策路径,而自动化标志用于设置应用环境(例如,直接跳转到特定屏幕,在启动时模拟用户已登录等)。LaunchArgumentBuilder 将为功能标志添加 "EPHEMERAL" 前缀,并将 "AUTOMATION" 前缀添加到自动化标志参数中,以便在应用中进行轻松解包(通过后面描述的 AutomationBridge.swift)。

标志定义为 structs

public struct Flag {
    public let key: String
    public let value: Any
}
  • PageObject.swift 是在客户端代码中定义的页面对象的父类。它保存对 XCUIApplication 和当前 XCTestCase 的引用。

Extensions

  • ExtensionXCTestCase.swift 包含在测试套件中使用的常用方法。还可以找到更多类似的实用方法,如 EarlGrey。公开的方法包括
func waitForElementToNotExist(element: XCUIElement, timeout: Double = 10)
func waitForElementToExist(element: XCUIElement, timeout: Double = 10)
func waitForElementValueToExist(element: XCUIElement, valueString: String, timeout: Double = 10)

Host

客户端应该有一个能够检查 ProcessInfo 中标志的组件。这可以通过 AutomationBridge.swift 实现,该组件公开了以下方法

public var ephemeralConfiguration: NSDictionary?
public var automationConfiguration: NSDictionary?
public func launchArgumentsContain(_ launchArgument: String) -> Bool

通过 ATTestCaselaunchApp 方法运行测试用例,现在可以从 ProcessInfo 中提取的参数不应超过 2 个

  • 一个包含所有功能标志(可选)
  • 一个包含所有自动化标志(可选)

客户端代码中扩展 AutomationBridge 时,应公开类似 simulateUserAlreadyLoggedIn() 的方法以检查自动化配置中值的是否存在。客户端应用程序使用这些方法来驱动决策并简化UI测试的执行。

AutomationBridge 还公开暴露了 ephemeralConfiguration 属性(类型为 NSDictionary),最终用于在客户端代码中设置特性标志。这个名字来自 JustTweaks,其中 NSDictionaryNSMutableDictionary 分别与 ConfigurationMutableConfiguration 兼容,我们建议使用它来设置栈以简化特性标志的用法。

示例

核心

从测试用例中调用相关配置的 launchApp() 方法来设置并运行继承自 ATTestCase 的测试用例。launchApp() 方法通过 LaunchArgumentsBuilder 的注入标志/参数,以正确的配置启动应用程序。

import XCTest
import AutomationTools_Core

class ExampleTestCases: ATTestCase {
    func testExample1() {
        launchApp(featureFlags: [Flag(key: Constants.feature1, value: false)],
                  automationFlags: [Flag(key: Constants.simulateUserAlreadyLoggedIn, value: true)],
                  otherArgs: [Constants.defaultStubBundle])

        // Test steps
       ...
    }
} 

主机

扩展 AutomationBridge 来包含配置环境的所需方法。

import Foundation
import AutomationTools_Host

public extension AutomationBridge {

     public var simulateUserAlreadyLoggedIn: Bool {
        return automationConfiguration?[Constants.simulateUserAlreadyLoggedIn] as? Bool ?? false
    }
} 

并使用临时配置来设置应用程序配置。

if let ephemeralConfiguration = automationBridge.ephemeralConfiguration {
    // use ephemeralConfiguration to setup app configuration
    // or setup a TweakManager with JustTweak
}

以下是一个使用 JustTweak 设置堆栈的示例

lazy var tweakManager: TweakManager = {
    let ephemeralConfiguration = automationBridge.ephemeralConfiguration
    
    let userDefaultsConfiguration = UserDefaultsConfiguration(userDefaults: UserDefaults.standard)

    let jsonURL = Bundle.main.url(forResource: "Tweaks", withExtension: "json")!
    let localConfiguration = LocalConfiguration(jsonURL: jsonFileURL)
    
    let configurations: [Configuration] = [ephemeral, userDefaultsConfiguration, localConfiguration].compactMap { $0 }

    return TweakManager(configurations: configurations)
}()

安装

在 Checkout 模块的 pod 文件中包含 AutomationTools pod 引用

target 'YourProject_MainTarget' do
pod 'AutomationTools-Host', '5.0.0'
end

target 'YourProject_UITestsTarget' do
pod 'AutomationTools-Core', '5.0.0'
end
  • Just Eat iOS 团队