AutomationTools-Core 5.0.0

AutomationTools-Core 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 扩展,这些都意味着我们的测试套件易于维护且具有高可读性、灵活性和代码重用性。

自动化工具由2个Pods组成:AutomationTools-Core和AutomationTools-Host。Core包含应用状态配置、基本类和工具。Host通过取消封装注入的标志符,在测试用例和应用之间提供桥梁。使用两个独立的Podspec而不是子spec的原因是为了支持苹果的新构建系统。CocoaPods对由子spec生成的框架命名的已知局限性

Core

  • ATTestCase.swift是从UITestCase继承的基本类,用于所有UI测试套件。它包含对XCUIApplication的引用,并为测试提供launchApp方法,用于从测试中运行应用。
launchApp(featureFlags: [Flag] = [], 
          automationFlags: [Flag] = [], 
          envVariables: [String : String] = [:],
          otherArgs: [String] = [])

我们将标志符数组传递给launchApp方法,然后通过在LaunchArgumentBuilder中添加适当的“临时”和“自动化”前缀,将它们序列化并转换为字符串表示形式。

  • LaunchArgumentsBuilder.swift用于ExtensionXCUIApplication.swift中,有如下2个公开方法:
static public func launchArgumentForEphemeralConfiguration(_ ephemeralConfiguration: NSDictionary) -> String
static public func launchArgumentForAutomationConfiguration(_ automationConfiguration: NSDictionary) -> String

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

标志符定义为以下结构体:

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)
}()

安装

将AutomationTools pod引用包含在Checkout模块的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团队