Hammer

如果你无法触碰它,那就是 Hammer time!

Demo

目录
  1. 简介
  2. 安装
  3. 设置
  4. 用法
  5. 故障排除
  6. 许可证

简介

Hammer 是一个用于模拟用户交互事件的触摸、触控笔和键盘合成库。它能够以更好的方式在单元测试中触发 UI 操作,尽可能地复现真实世界的环境。

⚠️重要提示:此库大量使用了私有 API,绝不应包含在生产应用程序中。

安装

要求

Hammer 需要 Swift 5.3 和 iOS 11.0 或更高版本。

使用 SwiftPM

.package(url: "https://github.com/lyft/Hammer.git", from: "0.13.0")

使用 CocoaPods

pod 'HammerTests', '~> 0.13.1'

设置

Hammer 单元测试需要在宿主应用程序中运行才能生成触摸事件。要配置此项,请在侧边栏中选择您的项目,选择您的测试目标,然后在常规选项卡中选择一个宿主应用程序。宿主应用程序可以是您的主应用程序或一个空的包装器,例如 TestHost

SwiftPM 目前不支持创建应用程序。要将 Hammer 与 SwiftPM 框架一起使用,您需要创建一个 xcodeproj 并设置一个宿主应用程序。

用法

Hammer 允许您模拟手指、触控笔和键盘事件。它还提供了各种便捷方法来模拟更高级别的用户交互。

要能够将事件发送到视图,您必须首先创建一个 EventGenerator

// Initialize for an existing UIWindow, ensure that the window is key and visible.
let eventGenerator = EventGenerator(window: myWindow)

// Initialize for a UIView, automatically wrapping it in a temporary window.
let eventGenerator = EventGenerator(view: myView)

// Initialize for a UIViewController, automatically wrapping it in a temporary window.
let eventGenerator = EventGenerator(viewController: myViewController)

当模拟手指或触控笔触摸时,有多种方法可以指定触摸位置

  1. 默认:如果您不指定位置,它将使用屏幕中心。
  2. 点:屏幕坐标系中的 CGPoint。
  3. 视图:对 UIView 或 UIViewController 的引用,位置将是视图可见部分的中心。
  4. 标识符:视图的辅助功能标识符字符串,位置将是视图可见部分的中心。

默认情况下,Hammer 将在视图上显示模拟的触摸。您可以为您的事件生成器更改此行为。

eventGenerator.showTouches = false

模拟手指

手指是 iOS 上最常见的用户交互方法。Hammer 支持同时处理屏幕上的多个手指,直至设备上的限制。您可以指定您想要使用的特定手指索引,如果未指定,它将自动选择最合适的。

原始事件是用户交互的基本构建块,它们可以组合在一起以创建完整的手势。某些方法允许您指定持续时间,并将在此期间插值更改。

try eventGenerator.fingerDown(at: CGPoint(x: 10, y: 10))
try eventGenerator.fingerMove(to: CGPoint(x: 20, y: 10), duration: 0.5)
try eventGenerator.fingerUp()

为了方便起见,Hammer 提供了许多更高级别的手势。如果您不指定位置,它将自动默认为视图的中心。

try eventGenerator.fingerTap()
try eventGenerator.fingerDoubleTap()
try eventGenerator.fingerLongPress()
try eventGenerator.twoFingerTap()

许多高级手势也可用。

try eventGenerator.fingerDrag(from: CGPoint(x: 10, y: 10), to: CGPoint(x: 20, y: 10), duration: 0.5)
try eventGenerator.fingerPinch(fromDistance: 100, toDistance: 50, duration: 0.5)
try eventGenerator.fingerRotate(angle: .pi, duration: 0.5)

模拟触控笔

触控笔在 iPad 上运行时可用。它允许指定额外的属性,如压力、高度角和方位角。

与手指类似,原始事件是触控笔交互的基本构建块。

try eventGenerator.stylusDown(at: CGPoint(x: 10, y: 10), azimuth: 0, altitude: 0, pressure: 0.5)
try eventGenerator.stylusMove(to: CGPoint(x: 20, y: 10), duration: 0.5)
try eventGenerator.stylusUp()

Hammer 还为触控笔提供了许多更高级别的手势。如果您不指定位置,它将自动默认为视图的中心。

try eventGenerator.stylusTap()
try eventGenerator.stylusDoubleTap()
try eventGenerator.stylusLongPress()

模拟键盘

键盘方法接受显式的 KeyboardKey 对象或 Character。字符将被映射到最接近的键盘按键,如果需要,您必须使用 shift 键修饰符包装它们。这意味着指定小写字符“a”等同于指定大写字符“A”,对于带有符号的键也是如此。

// Explicit `KeyboardKey`
try eventGenerator.keyDown(.letterA)
try eventGenerator.keyUp(.letterA)

// Automatic `Character` mapping
try eventGenerator.keyDown("a")
try eventGenerator.keyUp("a")

// Convenience key down and up events
try eventGenerator.keyPress(.letterA)
try eventGenerator.keyPress("a")

要键入字符或更长的字符串并获得自动 shift 包装,您可以使用 keyType() 方法。

try eventGenerator.keyType("This will type the string as specified, including symbols!")

查找子视图

当在全屏应用程序上运行或测试导航时,指定屏幕坐标系中的 CGPoint 可能很困难。为此,Hammer 提供了便捷的方法,可以通过辅助功能标识符在层级结构中查找视图。

let myButton = try eventGenerator.viewWithIdentifier("my_button", ofType: UIButton.self)
try eventGenerator.fingerTap(at: myButton)

如果在层级结构中未找到视图,此方法将抛出错误。如果您正在测试导航或屏幕更改,并且需要等待视图出现,则可以添加超时。这将等待层级结构更新并返回视图。

let myButton = try eventGenerator.viewWithIdentifier("my_button", ofType: UIButton.self, timeout: 1)
try eventGenerator.fingerTap(at: myButton)

您也可以直接将辅助功能标识符传递给事件方法。

try eventGenerator.fingerDown(at: "my_draggable_object")
try eventGenerator.fingerMove(to: "drop_target", duration: 0.5)
try eventGenerator.fingerUp()

等待

您通常需要等待模拟器完成在屏幕上显示某些内容或等待动画结束。Hammer 提供了多种方法来等待视图在屏幕上可见或控件可点击

try eventGenerator.waitUntilVisible("my_label", timeout: 1)
try eventGenerator.waitUntilHittable("my_button", timeout: 1)

故障排除

确保您在宿主应用程序中运行单元测试(设置说明)。要与视图交互,它必须在屏幕上可见,并且应用程序必须已完成呈现。您可以通过在测试中添加延迟并验证您的视图是否出现在屏幕上来测试这一点。

确保您指定的视图与用于创建 EventGenerator 的视图在同一层级结构中。如果您使用了辅助功能标识符,请检查其拼写是否正确。

这意味着该视图在层级结构中,但当前在屏幕上不可见,因此无法为其生成触摸事件。确保视图在可见 bounds 内,未被其他视图覆盖,未隐藏,并且 alpha 值大于 0.01。

这意味着该视图在层级结构中且在屏幕上可见,但目前无法接收触摸事件。确保视图在其中心坐标中响应点击测试,并且用户交互已启用。

许可证

Hammer 在 Apache 许可证下发布。请参阅 LICENSE