📝 面试求职: 「面试试题小程序」 ,内容涵盖 测试基础、Linux操作系统、MySQL数据库、Web功能测试、接口测试、APPium移动端测试、Python知识、Selenium自动化测试相关、性能测试、性能测试、计算机网络知识、Jmeter、HR面试,命中率杠杠的。(大家刷起来…)
📝 职场经验干货:
在 iOS 上实现快照测试
将快照测试与常规单元测试一起实现是很有价值的,因为它解决了一个常常被忽视的测试方面:用户界面的一致性。
虽然单元测试验证业务逻辑的正确性,但快照测试捕获并比较用户界面的渲染,防止意外的视觉回归。这在动态用户界面中特别有用,因为小的代码更改可能会破坏布局,而标准测试却无法检测到。
设置 iOS 项目
我们将创建一个普通的 iOS 应用程序项目,其中包含一个 Swift 测试目标(不是 XCTest):
要将swift-snapshot-testing包包含到你的项目中,请通过 Swift 包管理器(SPM)使用以下 URL 添加它: [https://github.com/pointfreeco/swift-snapshot-testing](https://github.com/pointfreeco/swift-snapshot-testing) 。
重要提示 :在添加包时,请确保将其分配给项目的测试目标。这是必要的,因为 swift-snapshot-testing是一个测试框架,应该只链接到你的测试包,而不是主应用目标。
我们将继续实现将要验证的视图:
结构体 根视图:视图{
@状态 变量 导航路径 = 导航路径()
var body: 一些 View{
NavigationStack(路径: $navigationPath) {
ContentView(路径: $navigationPath)
.导航目的地(对于: 字符串.自身) { 目标 在
switch目标 {
情况"SecondView":
SecondView(导航路径:$导航路径)
情况"ThirdView":
ThirdView(导航路径:$导航路径)
默认:
空白视图()
}
}
}
}
}
结构体 ContentView :视图{
@绑定 变量 导航路径: 导航路径
var body: some View{
VStack {
Text("First View")
.字体(.大标题)
.填充()
按钮(动作: {
navigationPath.append("SecondView")
}) {
文本("转到第二个视图")
.填充()
.背景(颜色.蓝色)
前景颜色(.白色)
.cornerRadius(10)
}
.accessibilityIdentifier("增加按钮")
}
.导航标题("第一视图")
}
功能 测试按钮按下() {
navigationPath.append("SecondView")
}
}
结构体 SecondView:视图{
@绑定 变量 导航路径: 导航路径
var body: some View{
VStack{
Text("Second View")
.字体(.大标题)
.填充()
按钮(动作: {
navigationPath.append("ThirdView")
}) {
文本("转到第三视图")
.填充()
.背景(颜色.绿色)
前景颜色(.白色)
.cornerRadius(10)
}
}
.导航标题("第二个视图")
}
}
结构体 ThirdView:View{
@绑定 变量 导航路径: 导航路径
var body: some View {
VStack{
Text("Third View")
.字体(.大标题)
.填充()
按钮(操作: {
// 弹出到根目录
navigationPath.removeLast(navigationPath.count) // 空栈
}) {
文本("返回第一个视图")
.填充()
.背景(颜色.红色)
前景颜色(.白色)
.cornerRadius(10)
}
}
.导航标题("第三个视图")
}
}
提供的 SwiftUI 代码定义了一个导航流程,用户可以在其中浏览三个视图: FirstView、 SecondView和 ThirdView。
它使用NavigationStack来管理导航路径,导航路径在各个视图之间共享一个 NavigationPath。在 ContentView中,用户可以通过按下按钮导航到 SecondView。
在 SecondView中,用户可以通过另一个按钮继续导航到 ThirdView。在 ThirdView中,有一个按钮可以清空导航栈,将用户带回 FirstView 。导航路径由 navigationPath 状态管理,要导航到的具体视图由导航路径中的字符串值决定。
快照测试
在 iOS 中,快照测试是一种专注于验证应用程序用户界面的视觉元素的方法,例如字体、颜色、布局和图像。它涉及捕获用户界面的屏幕截图并将其保存为参考图像,然后在后续测试中将新的屏幕截图逐像素进行比较。
这种技术允许开发人员快速检测由代码更改引起的意外视觉变化或回归,确保应用程序不同版本之间的用户界面一致性。通过自动化视觉验证,快照测试补充了其他测试方法,如单元测试和集成测试,专门解决应用程序的视觉方面问题,帮助维护高质量的用户体验。
Swift 测试允许测试函数被参数化。在我们的例子中,我们将根据我们感兴趣的设备屏幕来参数化测试函数。
协议 测试设备{
功能 查看图像配置(){ -> 查看图像配置
}
结构体 iPhoneSe:测试设备{
函数 查看图像配置() -> 查看图像配置{
查看图像配置.iPhoneSe
}
}
结构体 iPhone13ProMax:测试设备 {
函数 查看图像配置() -> 查看图像配置 {
查看图像配置.iPhone13ProMax (.纵向)
}
}
结构体 iPhone12Landscape:测试设备{
函数 查看图像配置()-> 查看图像配置 {
查看图像配置.iPhone12 (.landscape)
}
}
在我们的示例中,我们将使用 iPhone SE、iPhone 13 Pro Max 和 iPhone 12(横向模式)。最后,测试本身。
@MainActor
@Suite("快照测试")
结构体 快照测试{
var record = true// 记录模式!
static let devices: [TestDevice] = [iPhoneSe(), iPhone13ProMax(), iPhone12Landscape()]
@测试(参数: 设备) 函数 测试第一个视图(设备: 测试设备) {
let 根视图 = 根视图()
let 托管控制器 = UI托管控制器(根视图: 根视图)
var 名称 = 字符串(描述: 类型(设备))
断言快照(of: hostingController,
作为:.image(开启: device.viewImageConfig()),
命名: 命名,
记录: 记录)
}
@测试(参数: 设备) 函数 测试第二个视图(设备: 测试设备){
let secondView = SecondView(导航路径: .常量(导航路径()))
let 托管控制器 = UIHostingController(根视图: secondView)
变量 名称 = 字符串(描述: type(of: 设备))
断言快照(of: hostingController,
作为:.image(开启: device.viewImageConfig()),
命名: 命名,
记录: 记录)
}
@测试(参数: 设备) 函数 测试第三方视图(设备: 测试设备) {
let 第三方视图 = 第三方视图(导航路径: .常量(导航路径()))
let 托管控制器 = UI托管控制器(根视图: 第三方视图)
变量 名称 = 字符串(描述: type(of: 设备))
断言快照(of: hostingController,
作为:.image(开启: device.viewImageConfig()),
命名: 命名,
记录: 记录)
}
}
我们为每个屏幕定义了一个测试函数来验证。在第一次执行时, var record = true ,这意味着将捕获参考屏幕截图。运行测试时,不要担心失败的结果。
重要的是,已经创建了一个名为 \_\_ Snapshots\_\_的新文件夹来存储捕获的快照。这些快照将作为比较的参考点。别忘了提交屏幕截图。现在,将 record 切换为 false 以启用快照测试模式
var record = false // 捕获测试模式!
...
运行测试,现在所有内容都应该是绿色的:
让测试失败!
现在我们将在视图中引入一些更改:
启动测试:现在我们面临的问题是验证 `ContentView` 的测试失败了
当我们查看日志时,我们可以看到快照存储在哪个文件夹中。
使用你最喜欢的文件夹内容比较器比较两个文件夹:
在我的情况下,我使用 Beyond Compare,点击任意一对文件:
使用 BeyondCompare 中包含的图像比较器,我们可以轻松地看到哪些视图组件发生了变化。
结论
快照测试是单元测试的有力补充,因为它使你能够更有效地检测视图中的回归。
最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】