AutomationTools 4.1.1

AutomationTools 4.1.1

Alberto De BortoliDimi ChakarovMark CousinsJust Eat Takeaway.com iOS Team 维护。



  • 作者
  • Alberto De Bortoli和Sneha Narayana Swamy

AutomationTools

CI Status Version License Platform

关于

AutomationTools是一个框架,可以帮助您编写更好且更易于维护的UI测试。它允许启动应用程序,注入标记以加载正确的配置并自动化重复性操作(例如填充购物车、用户登录等)。从测试案例将状态注入正在测试的应用程序的机制是通过使用启动参数和环境变量。启动参数作为字符串数组传递到XCUIApplication的启动方法,环境变量作为字典传递。

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

AutomationTools分为核心和HostApp部分。核心由应用程序状态配置、基类和实用工具组成。HostApp通过展开注入测试案例的标志来在测试案例和应用程序之间提供桥梁。

核心

  • ATTestCase.swift是从TestCases继承的基类,用于所有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将“AUTOMATION”前缀添加到功能标志,并将“AUTOMATION”前缀添加到自动化标志参数,以便于在应用程序中(通过后面将要描述的AutomationBridge.swift)进行解包。

标志是定义为结构的:

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

扩展

  • 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)

主机应用程序

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

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

通过ATTestCase's launchApp方法运行测试时,现在可以从ProcessInfo中提取的参数不应超过2个

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

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

AutomationBridge还公开了ephemeralConfiguration属性(NSDictionary类型),最终用于在客户端代码中设置功能标志。其名称来自JustTweaks,其中NSDictionaryNSMutableDictionary分别被转换为兼容的ConfigurationMutableConfiguration,我们建议使用它来设置一个堆栈,以便更容易使用功能标志。

示例

核心

在测试用例中调用 launchApp() 方法,并传入相关配置以设置和运行继承自 ATTestCase 的测试案。launchApp() 方法从 LaunchArgumentsBuilder 注入的标志/参数中获取打包好的标志/参数,并使用正确配置启动应用程序。

import XCTest
import AutomationTools

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 以包括配置环境所需的方 Kloppemethode.de.

import Foundation
import AutomationTools

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/HostApp', '1.0.0'
end

target 'YourProject_UITestsTarget' do
pod 'AutomationTools/Core', '1.0.0'
end
  • Just Eat iOS 团队