iOS.& Swift Books Swifui由教程

16
测试& Debugging 由账单更多地德里菲尔德

向您的应用程序添加测试提供了内置和自动化的方法,以确保您的应用程序执行您的期望。测试不仅要检查您的代码是否正常工作,但也有一些保证,即将未来的变化不会破坏现有功能。

在本章中,您将学习如何实现UI测试您的应用程序SwiftUI,并观看了在这一新模式可以测试你的UI时,为了什么。

不同类型的测试

您将在您的应用中使用三种类型的测试。按越来越复杂性的顺序,它们是:单元测试,集成测试和用户界面测试。

所有测试的基础,以及所有其他测试的基础,是 单元测试 。每个单元测试可确保在函数处理给定输入时获得预期输出。多个单元测试可以测试相同的代码,但每个单元测试本身应该只关注单个代码。单元测试应毫秒才能执行。你会经常运行它们,所以你希望他们快速运行。

下一个测试测试层次结构是 集成试验。 Integration Tests验证您的代码的不同部分以及每个应用程序的工作方式以及应用程序在应用程序之外的世界与外部API之外的世界合作。集成试验比单位测试更复杂;他们通常需要更长时间才能运行,因此您将不经常运行它们。

最复杂的测试是用户界面测试,或 UI测试 ;这些测试验证了应用程序的面向用户的行为。它们模拟用户与应用程序的交互,并在响应交互后验证用户界面是否正常行为。

As you move up the testing hierarchy, each level of test checks a broader scope of action in the app. For example, a unit test would verify that the calculateTotal() method in your app returns the correct amount for an order. An integration test would verify that your app correctly determines that the items in the order are in stock. A UI test would verify that after adding an item to an order, the amount displayed to the user displays the correct value.

Swifui是一个新的视觉框架,所以本章侧重于如何为Swifui应用程序编写UI测试。您还将学习如何通过将UI测试添加到简单的计算器应用程序来了解如何调试您的Swifui应用程序和测试。

调试SWIFTUI应用程序

为本章打开Starter项目,并构建和运行应用程序;这是一个简单的计算器。该应用程序还支持Catalyst,因此它适用于iOS,iPados和Mac。使用计算器运行一些计算,以了解它的工作原理。

Button(action: {
  if let val = Double(self.display) {
    self.memory = self.memory + val
    self.display = ""
    self.pendingOperation = .none
  } else {
    // Add Bug Fix Here
    self.display = " 错误 "
  }
}) {
  Text(" M + ")
    .frame(width: 45, height: 45)
  .addButtonBorder(Color.gray)
}

设置断点

要在执行应用程序的执行期间停止代码,请设置一个断点,以便在达到特定代码行时停止调试器停止代码。然后,您可以检查变量,步骤通过代码并调查代码中的其他元素。

探索断点控制

在断点停止时,您将在代码编辑器和调试区域之间看到一个工具栏。打印工具栏中的第一个按钮可切换调试区域的可见性。第二个按钮禁用所有口袋断点不会删除它们。第三个按钮继续执行该应用程序。您还可以选择CAN 调试▸继续 在继续应用程序执行的菜单中。

po self.memory

添加UI测试

这段代码中有一个错误,你会注意到你的时候 继续 。显示的默认值是空字符串,显示器将空字符串转换为 0。但是,代码 M + 按钮尝试将空字符串转换为a 双倍的 。当转换失败时,值 错误 appears to the user.

continueAfterFailure = false

创建UI测试

适当的测试名称应精确且清除测试验证的内容,因为应用程序最终有大量测试。清除名称使其很容易理解失败。测试名称应说明它测试的内容,测试的情况以及结果应该是什么。

访问UI元素

将以下代码添加到测试方法的末尾:

let memoryButton = app.buttons[" M + "]
memoryButton.tap()
Button, 0x600002498540, {{184.5, 102.5}, {45.0, 45.0}}, label: ’M+’

读取用户界面

你找到了 M + 按钮按钮的标签。但是,它不会为显示器工作,因为控制的文本基于应用的状态。但是,您可以将属性添加到接口的元素中,以便在测试中更容易找到。打开 ContentView.swift.. In the view, look for the two comments // Add display identifier and replace both with the following line:

.accessibility(identifier: "display")
// 1
let display = app.staticTexts["display"]
// 2
let displayText = display.label
// 3
XCTAssert(displayText == "0")

修复错误

打开 ContentView.swift.,找到对该行动的评论 M + button that reads // Add Bug Fix Here, and change the next line to read:

self.display = ""

添加更复杂的测试

理想情况下,您将在您构建UI时同时构建UI测试。这样,随着你的UI变得更加圆顶,你的测试套件会随它扩展。但是,随着现代发展的现实,您通常会在测试应用程序中添加。

func testAddingTwoDigits() {
  let app = XCUIApplication()
  app.launch()

  let threeButton = app.buttons["3"]
  threeButton.tap()

  let addButton = app.buttons["+"]
  addButton.tap()

  let fiveButton = app.buttons["5"]
  fiveButton.tap()

  let equalButton = app.buttons["="]
  equalButton.tap()

  let display = app.staticTexts["display"]
  let displayText = display.label
  XCTAssert(displayText == "8")
}
XCTAssert(displayText == "8.0")

模拟用户互动

您可以先添加一个姿势,使刷卡内存显示器的左侧将其清除。手势的效果的工作方式相同轻敲 马克 key by setting the value of self.memory to zero.

let memorySwipe = DragGesture(minimumDistance: 20)
  .onEnded { _ in
    self.memory = 0.0
}
.gesture(memorySwipe)
.accessibility(identifier: "memoryDisplay")

func testSwipeToClearMemory() {
  let app = XCUIApplication()
  app.launch()

  let threeButton = app.buttons["3"]
  threeButton.tap()
  let fiveButton = app.buttons["5"]
  fiveButton.tap()

  let memoryButton = app.buttons[" M + "]
  memoryButton.tap()

  let memoryDisplay = app.staticTexts["memoryDisplay"]
  // 1
  XCTAssert(memoryDisplay.exists)
  // 2
  memoryDisplay.swipeLeft()
  // 3
  XCTAssertFalse(memoryDisplay.exists)
}

测试multiple platforms

Swifui的大部分承诺来自建立在多个Apple平台上工作的应用程序。您的iOS应用程序可以成为一个很少的工作:本章的示例项目支持Catalyst,让应用程序在MacOS上运行。但是,总是有一些东西可以照顾好自己,以确保您的应用以及他们的测试,在所有平台上正常工作。

#if !targetEnvironment(macCatalyst)
  // Test to exclude
#endif
#if !os(watchOS)
  // Your XCTest code
#endif

关键点

  • 构建和调试测试需要更多的关注,因为在SwiftUI代码和用户界面元素的组合。
  • 您可以在标准SWIFT代码中使用Swifui中使用断点和调试。
  • 测试自动检查你的代码的行为。测试应确保给定的一个已知的输入和一个已知的初始状态,就会发生预期的输出。
  • 用户界面或UI测试验证与应用程序的界面的交互是否会产生预期的结果。
  • Add an accessibilityIdentifer to elements that do not have static text for their label to improve location for testing.
  • You find all user interface elements from the XCUIApplication element used to launch the app in the test.
  • 方法和属性允许您在您的测试中定位和交互,因为您的用户将在测试中。
  • 不同的平台往往需要不同的用户界面测试。使用条件编译来匹配测试的平台和操作系统。

挑战

如前所述,刷卡姿势清除内存不起作用。在应用程序中,您需要提供一种制作相同结果的替代方法。

挑战解决方案

您应该首先添加新的双击手势。将当前的手势定义更改为:

#if targetEnvironment(macCatalyst)
let doubleTap = TapGesture(count: 2)
  .onEnded { _ in
    self.memory = 0.0
}
#else
let memorySwipe = DragGesture(minimumDistance: 20)
  .onEnded { _ in
    self.memory = 0.0
}
#endif
#if targetEnvironment(macCatalyst)
Text("\(self.memory)")
  .accessibility(identifier: "memoryDisplay")
  .padding(.horizontal, 5)
  .frame(width: geometry.size.width * 0.85,
         alignment: .trailing)
  .overlay(RoundedRectangle(cornerRadius: 8)
           .stroke(lineWidth: 2)
           .foregroundColor(Color.gray))
  .gesture(doubleTap)
#else
Text("\(self.memory)")
  .accessibility(identifier: "memoryDisplay")
  .padding(.horizontal, 5)
  .frame(width: geometry.size.width * 0.85, 
         alignment: .trailing)
  .overlay(RoundedRectangle(cornerRadius: 8)
           .stroke(lineWidth: 2)
           .foregroundColor(Color.gray))
  .gesture(memorySwipe)
#endif
#if targetEnvironment(macCatalyst)
memoryDisplay.doubleTap()
#else
memoryDisplay.swipeLeft()
#endif

然后去哪儿?

本章提供了测试和调试您的SWIFTUI项目的介绍。您走得更深入的起点应该是Apple关于XCTest的文档 //developer.apple.com/documentation/xctest.

有一个技术问题?想报告一个错误吗? 您可以向官方书籍论坛中的书籍作者提出问题和报告错误 这里 .

有反馈分享在线阅读体验吗? 如果您对UI,UX,高亮反馈,或者我们的在线读者的其他功能,你可以将它们发送给设计团队与下面的表格:

© 2021 Razeware LLC

您可以免费读取,本章的部分显示为 混淆了 文本。解锁这本书,以及我们整个书籍和视频目录,带有Raywenderlich.com的专业订阅。

现在解锁

要突出或记笔记,您需要在订阅中拥有这本书或自行购买。