[Swift]单元测试

编写单元测试是确保你的代码质量和功能正确性的重要步骤

一、编写单元测试的详细流程

1. 创建一个新的Xcode项目

如果你尚未创建一个项目,首先你需要在Xcode中创建一个新的iOS项目:

  • 打开Xcode,选择“File” > “New” > “Project”。

  • 选择一个适合的项目模板,例如“App”,然后点击“Next”。

  • 填写项目的详细信息(如项目名称、团队、组织名称和语言选择Swift),确保勾选“Include Tests”选项,然后点击创建。

2. 理解测试目标和框架

创建项目时,如果你选择了“Include Tests”,Xcode会自动为你的项目生成一个测试目标(Target)。这个测试目标使用XCTest框架,这是Apple提供的用于编写单元测试的框架。

3. 编写测试用例

单元测试通常是围绕你的应用程序的单一功能或类来编写的。

下面是编写单元测试的基本步骤:

(1).找到测试文件

在Xcode的项目导航器中,找到以“Tests”结尾的目标文件夹。默认的测试文件可能类似于YourProjectNameTests.swift。

(2).导入测试模块

在测试文件的顶部,确保导入了XCTest框架和你的主项目模块。例如:

import XCTest
@testable import YourProjectName

(3).创建测试类

Xcode默认创建的测试类继承自XCTestCase。你可以在这个类中添加测试方法。

(4).编写测试方法

每个测试方法都必须以test开头。方法内部使用断言来验证代码的功能。例如,测试一个简单的加法函数:

func testAddition() {let result = Calculator.add(1, 2)XCTAssertEqual(result, 3, "The addition function failed.")
}

这里,XCTAssertEqual是一个断言,用于检查Calculator.add(1, 2)的结果是否等于3。

(5).默认生成的代码

一般上面几步不用手动敲代码,YourProjectNameTests.swift文件中会包含如下代码,XCTestCase类提供了多个方法来帮助设置、执行和拆分测试。

import XCTest
@testable import GameDeDemofinal class GameDeDemoTests: XCTestCase {/**将设置代码放在这里。此方法在类中的每个测试方法调用之前被调用。用途:这个方法在每个测试方法之前被调用。它用于设置测试环境,确保每个测试都在干净且已知的状态下开始。例子:在这个方法中,你可以初始化一些对象,设置或重置模拟数据,或配置环境(如数据库连接、网络环境等)。*/override func setUpWithError() throws {}/**把拆卸代码放在这里。在调用类中的每个测试方法之后调用此方法。用途:这个方法在每个测试方法之后被调用。它用于清理或拆分测试后的环境,确保一个测试的执行不会影响到其他测试。例子:释放在setUpWithError()中创建的对象,关闭数据库连接,清理模拟数据等。*/override func tearDownWithError() throws {}/**这是一个功能测试用例。使用XCTAssert和相关函数来验证测试是否产生正确的结果。为XCTest编写的任何测试都可以被注释为抛出和async。当测试遇到未捕获的错误时,标记测试抛出以产生意外失败。将测试标记为async,允许等待异步代码完成。之后用断言检查结果。*/func testExample() throws {}/**用途:这个方法用于性能测试,主要用来测量一段代码的执行时间。通过measure方法,Xcode会多次执行代码块,并记录执行时间,从而帮助开发者了解代码的性能。例子:测量一个复杂算法的执行时间,或者评估一个数据处理函数的性能。*/func testPerformanceExample() throws {// 这是一个性能测试用例的示例。self.measure {// 把要测量时间的代码写在这里。}}}

4. 运行测试

(1).使用快捷键

可以直接在Xcode中使用快捷键Command + U来运行所有测试。

(2).切换运行按钮

长按运行按钮,切换到Build for Testing,后面点击运行就是运行所有测试。

(3).使用测试导航器

在Xcode的侧边栏中,切换到测试导航器(测试图标),然后可以单独运行某个测试类或测试方法。

(4).单元测试文件运行

文件中,选择方法前面的“开始”,就是重新运行某个方法。选择文件名前面的“开始”,就是重新运行某个类。

5. 查看测试结果

测试完成后,Xcode会在编辑器左侧的测试导航器中显示测试结果。成功的测试会标记为绿色勾选,失败的测试会标记为红色叉号。如果测试失败,可以查看失败原因,并根据失败信息调整代码或测试逻辑。

除此之外,调试面板还会打印详细日志。 会展示每个方法执行时间,整个文件所执行的时间,以及报错信息。

Test Suite 'GameDeDemoTests' started at 2024-04-24 23:08:55.753.Test Case '-[GameDeDemoTests.GameDeDemoTests testExample1]' started.
/Users/gamin/Desktop/GameDeDemo/GameDeDemoTests/GameDeDemoTests.swift:53: error: -[GameDeDemoTests.GameDeDemoTests testExample1] : XCTAssertTrue failed - Result should be true
Test Case '-[GameDeDemoTests.GameDeDemoTests testExample1]' failed (0.023 seconds).Test Case '-[GameDeDemoTests.GameDeDemoTests testExample]' started.
Test Case '-[GameDeDemoTests.GameDeDemoTests testExample]' passed (0.002 seconds).Test Case '-[GameDeDemoTests.GameDeDemoTests testOneExample]' started.
Test Case '-[GameDeDemoTests.GameDeDemoTests testOneExample]' passed (1.351 seconds).Test Case '-[GameDeDemoTests.GameDeDemoTests testPerformanceExample]' started.
/Users/gamin/Desktop/GameDeDemo/GameDeDemoTests/GameDeDemoTests.swift:62: Test Case '-[GameDeDemoTests.GameDeDemoTests testPerformanceExample]' measured [Time, seconds] average: 0.000, relative standard deviation: 179.574%, values: [0.000083, 0.000009, 0.000006, 0.000005, 0.000005, 0.000005, 0.000004, 0.000004, 0.000005, 0.000004], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , polarity: prefers smaller, maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
Test Case '-[GameDeDemoTests.GameDeDemoTests testPerformanceExample]' passed (0.258 seconds).Test Suite 'GameDeDemoTests' failed at 2024-04-24 23:08:57.389.Executed 4 tests, with 1 failure (0 unexpected) in 1.634 (1.636) seconds

6. 重构和维护测试

随着项目的发展,持续维护和更新单元测试是非常重要的。确保在添加新功能或修改现有代码后更新相应的测试,以保持测试覆盖率和代码质量。

二、如何组织单元测试代码?

在进行单元测试时,组织和结构化测试代码是非常重要的。虽然技术上可以将所有测试写入一个单一的测试类中,但这通常不是最佳实践。

以下是一些关于如何组织单元测试代码的建议和优点:

1.分开测试文件的理由

(1).可维护性

将测试分散到不同的文件中可以提高代码的可维护性。当测试文件专注于特定的功能模块时,相关的测试更容易查找和更新。

(2).可读性

小型、专注的测试文件比一个庞大的测试文件更易于阅读和理解。每个测试类可以对应于应用程序中的一个模块或类,这样代码结构会更清晰。

(3).避免冲突

在团队环境中,多个开发者可能同时工作在不同的模块上。分开测试文件可以减少版本控制中的合并冲突。

(4).并行测试

当测试被组织到多个文件中时,运行测试的工具(如Xcode)可能能更有效地并行执行这些测试,从而减少总的测试时间。

2.如何组织测试?

(1).按类或模块组织

对于每个主要的类或功能模块,都应该有一个对应的测试类。例如,如果你有一个Game类和一个Player类,你可以创建GameTests.swiftPlayerTests.swift

(2).遵守命名约定

保持一致的命名约定有助于团队成员快速理解测试结构。通常,测试文件的命名应与被测试的类相对应,并加上Tests后缀。

(3).利用XCTest的设置和拆解方法

使用setUp()tearDown()方法来为每个测试案例配置必要的环境,这可以在每个测试类中独立进行。

三、XCTest中各种断言如何使用?

在XCTest框架中,断言是用来验证单元测试中条件是否符合预期的关键工具。每个断言都会对表达式或条件进行评估,如果条件不满足则会引发一个失败,这有助于开发者识别和修复错误。

这些断言是XCTest框架的核心部分,通过使用它们,你可以确保你的代码按照预期工作,及时发现和修正潜在的问题。

1.XCTAssert

用途:验证一个条件是否为真。

示例

func testExample() {let result = trueXCTAssert(result, "Result should be true")
}

2.XCTAssertTrue 和 XCTAssertFalse

用途:XCTAssertTrue 用来验证条件是否为真;XCTAssertFalse 用来验证条件是否为假。

示例

func testBooleanLogic() {let success = truelet failure = falseXCTAssertTrue(success, "Success should be true")XCTAssertFalse(failure, "Failure should be false")
}

3.XCTAssertEqual 和 XCTAssertNotEqual

用途:XCTAssertEqual 用来验证两个表达式的值是否相等;XCTAssertNotEqual 用来验证两个表达式的值是否不相等。

示例

func testEquality() {XCTAssertEqual(1 + 1, 2, "One plus one should equal two")XCTAssertNotEqual(1 + 1, 3, "One plus one should not equal three")
}

4.XCTAssertNil 和 XCTAssertNotNil

用途:XCTAssertNil 用来验证一个表达式的结果是否为nil;XCTAssertNotNil 用来验证一个表达式的结果是否不为nil。

示例

func testOptional() {var optionalValue: Int? = nilXCTAssertNil(optionalValue, "Value should be nil")optionalValue = 10XCTAssertNotNil(optionalValue, "Value should not be nil")
}

5.XCTAssertThrowsError 和 XCTAssertNoThrow

用途:XCTAssertThrowsError 用来验证一个表达式是否抛出错误;XCTAssertNoThrow 用来验证一个表达式是否没有抛出错误。

示例

func testThrowingFunction() {XCTAssertThrowsError(try throwingFunction(), "Function should throw an error")XCTAssertNoThrow(try nonThrowingFunction(), "Function should not throw an error")
}func throwingFunction() throws {throw NSError(domain: "", code: 0, userInfo: nil)
}func nonThrowingFunction() throws {// No error is thrown here
}

6.XCTAssertGreaterThan, XCTAssertGreaterThanOrEqual, XCTAssertLessThan, XCTAssertLessThanOrEqual

用途:这些断言用于比较数值,检查一个值是否大于、大于或等于、小于、小于或等于另一个值。

示例

func testComparisons() {XCTAssertGreaterThan(10, 9, "10 should be greater than 9")XCTAssertGreaterThanOrEqual(10, 10, "10 should be greater than or equal to 10")XCTAssertLessThan(9, 10, "9 should be less than 10")XCTAssertLessThanOrEqual(9, 9, "9 should be less than or equal to 9")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

window驱动开发-内核线程

在内核开发中,不可避免需要用到多线程技术,毕竟驱动是针对所有进程,而非某个特定进程,故驱动自然也是多线程的。在设计目标中,已经明确了驱动例程设计中,需要考虑的问题之一就是"重入"的概念&…

重生之我是Nginx服务专家

nginx服务访问页面白色 问题描述 访问一个域名服务返回页面空白,非响应404。报错如下图。 排查问题 域名解析正常,网络通讯正常,绕过解析地址访问源站IP地址端口访问正常,nginx无异常报错。 在打开文件时,发现无法…

R可视化:ggplot2绘制双y轴图

介绍 ggplot2绘制双y轴图加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE) library(tidyverse) library(readxl)# rm(list = ls()) options(stringsAsFactors = F) options(future.globals.maxSize = 10000 * 1024^2)Importing data 下载Underdetection of c…

IDEA实现Springboot项目自动热部署

每当我们在修改代码时,往往需要重新启动项目,这样不仅浪费时间而且很麻烦,我们可以通过IDEA的热部署来提高效率 1、首先点file >> settings >> Build Excution >> Compire,选择Build project auto matically 2.…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择,如g、c、clang等,如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项: /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

flutter笔记-主要控件及布局

文章目录 1. 富文本实例2. Image2.1 本地图片2.2 网络图片 笔记3. 布局4. 滑动相关view4.1 GridView类似九宫格view4.2 ListView 关于widget的生命周期的相关知识这里就不做介绍,和很多语言类似; 1. 富文本实例 Dart中使用richtext,示例如下…

int和byte数组相互转换详解

转换之前我们需要了解各种进制之间的关系,不太了解的可以先看下计算机组成原理和体系 这篇文章 byte byte是字节的意思,一个字节等于8位,范围是 0000 0000 ~ 1111 1111(十六进制:0x0~0xff),总共包含256个数。 有符号的byte表示的…

java 和 php 的AES 128位 256位 加解密 【java解密php的AES加密方案】

项目需要 需要java可以解密 php加密的 字符串 , 使用的方法是 AES128位加解密 坑一踩完 ,还是直接上代码 package com.xxx.init.utils;import com.xxx.init.utils.BaseDataUtil; import com.xxx.init.exception.xxxRuntimeException; import com.xxx.i…

ARCGIS PRO SDK POINT层唯一值渲染按角度旋转

c 代码: 按Direction字段旋转&#xff0c;旋转样式为数学 protected override async void OnClick(){var featLayer MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().First();await QueuedTask.Run(() >{var render featLayer.GetRenderer()…

Python异步编程详解:asyncio和多线程

Python 的异步编程是一种通过协程、事件循环和异步I/O操作来实现并发的技术。在 Python 中&#xff0c;asyncio 是用于编写单线程并发代码的库&#xff0c;而多线程则涉及使用 Python 的 threading 模块。下面我们将详细探讨这两种技术的使用和它们的适用场景。 ### 1. asynci…

6 Zookeeper 配置说明

Zookeeper 的三种工作模式 单机模式:存在单点故障。集群模式:在多台机器上部署 Zookeeper 集群,适合线上环境使用。伪集群模式:在一台机器同时运行多个 Zookeeper 实例,仍然有单点故障问题,当然其中配置的端口号要错开的,适合实验环境模拟集群使用。Zookeeper 的三种端口…

C 练习实例36 - 求100之内的素数

C 练习实例36 - 求100之内的素数 题目&#xff1a; 求100之内的素数。 程序分析&#xff1a; 质数&#xff08;prime number&#xff09;又称素数&#xff0c;有无限个。一个大于1的自然数&#xff0c;除了1和它本身外&#xff0c;不能被其他自然数整除。 程序源代码&#x…

Vue3+Vite开发的项目进行加密打包

本文主要介绍Vue3+Vite开发的项目如何进行加密打包。 目录 一、vite简介二、混淆工具三、使用方法1. 安装插件:2. 配置插件:3. 运行构建:4. 自定义混淆选项:5. 排除文件:下面是Vue 3+Vite开发的项目进行加密打包的方法。 一、vite简介 Vite 是一个由 Evan You 创造的现代…

XBoot:基于Spring Boot 2.x的一站式前后端分离快速开发平台

XBoot&#xff1a;基于Spring Boot 2.x的一站式前后端分离快速开发平台 摘要 随着信息技术的迅速发展&#xff0c;快速构建高质量、高可靠性的企业级应用成为了迫切需求。XBoot&#xff0c;作为一个基于Spring Boot 2.x的一站式前后端分离快速开发平台&#xff0c;通过整合微信…

python_AI库 matplotlib在AI程序中的应用介绍

本文默认读者具备以下技能&#xff1a; 熟悉Python基础知识&#xff0c;能自行阅读并理解代码含义 对AI有基础了解 基础高等数学知识 前文对matplotlib在日常生活的基础应用作了介绍&#xff0c;那么matplotlib与我们的AI又有什么联系呢&#xff1f; 在 AI 程序中&#xff0c…

针对icon报错

针对上篇文章生成图标链接中图标报错 C# winfrom应用程序添加图标-CSDN博客 问题&#xff1a;参数“picture”必须是可用作Icon的参数 原因&#xff1a;生成的ico图标类型不匹配 解决方法&#xff1a; 更改导出的ico类型

iOS - 多线程-读写安全

文章目录 iOS - 多线程-读写安全1. 多读单写1.1 场景1.2 实现方案1.2.1 pthread_rwlock&#xff1a;读写锁1.2.1.1 示例 1.2.2 dispatch_barrier_async&#xff1a;异步栅栏调用1.2.2.1 示例 iOS - 多线程-读写安全 假设有一个文件&#xff0c;A线程进行读取操作&#xff0c;B…

数智时代的AI人才粮仓模型解读白皮书(2024版)

来源&#xff1a;极客邦科技 自 2023 年上半年起&#xff0c;ChatGPT 等大模型技术蓬勃发展&#xff0c;AI 技术不断突破边界&#xff0c;展现 出惊人的潜力和发展速度。从早期的逻辑推理、专家系统&#xff0c;到如今的深度学习、神经网络&#xff0c; AI 技术显著缩小了科学…

ASP.NET企业投资价值分析系统

摘 要 本文将影响股票投资价值的宏观因素、行业因素、企业内部等诸多因素予以量化分析&#xff0c;对钢铁板块和汽车板块各上市公司进行综合评估&#xff0c;为广大股民的投资方向和资金安全提供了有力的支持。本文还阐述了企业投资价值分析的必要性&#xff0c;说明了企业投…

K8s: 持久化存储之卷, NFS卷

卷 Volume 1 ) 概述 容器中的文件在磁盘上是临时存放的&#xff0c;这给容器中运行的特殊应用程序带来一些问题 首先&#xff0c;当容器崩溃时&#xff0c;kubelet 将重新启动容器&#xff0c;容器中的文件将会丢失——因为容器会以干净的状态重建其次&#xff0c;当在一个 Po…