[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 GameDeDemo

final 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 = true
    XCTAssert(result, "Result should be true")
}

2.XCTAssertTrue 和 XCTAssertFalse

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

示例

func testBooleanLogic() {
    let success = true
    let failure = false
    XCTAssertTrue(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? = nil
    XCTAssertNil(optionalValue, "Value should be nil")

    optionalValue = 10
    XCTAssertNotNil(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")
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【黑马点评Redis——004达人探店】

1.发布探店笔记 2.点赞 利用Redis中的Set集合来判断是否点赞过。 3.点赞排行榜 可以通过SortedSet来按点赞时间进行排序。 4.好友关注 4.1.关注和取关 4.2.共同关注 可以通过set实现交集的功能 4.3.关注推送 4.3.1 拉模式 拉模式(Pull)&#x…

Android 13 Layer数据结构

Layer::State state的定义 State mDrawingState; 一个mDrawingState的变量struct State {Geometry active_legacy;Geometry requested_legacy;int32_t z;ui::LayerStack layerStack;#endifuint32_t flags;uint8_t reserved[2];int32_t sequence; // changes when visible regi…

解决Oracle锁表的方法

在实际工作中,并发量比较大的项目,经常会出现锁表的问题,下面我将复现这个问题,并给出解决方法。 一、问题复现 1、session1修改aabb表的B字段为迪迦奥特曼,但是不提交该事务。 2、session2也修改这行的这个字段。 发…

基于Springboot的网上商城购物系统

基于SpringbootVue的网上商城购物系统的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录 首页 商品信息 商品资讯 后台登录页面 后台管理首页 用户管理 商品分类管…

SVG 绘制微信订阅号icon

效果 代码 <!DOCTYPE html> <html> <body><svg xmlns"http://www.w3.org/2000/svg" version"1.1" width"600" height"600"><rect x"0" y"0" rx"0" ry"0" width&…

【C++】5.C语言/C++内存管理

一、C/C内存分布 栈中存储的是局部变量&#xff0c;函数参数&#xff0c;返回值等 堆主要用于动态内存分配 数据段用以存储全局数据和静态数据 代码段存储可执行代码和常量 二、C语言和C中的内存管理方式 在C语言中&#xff0c;我们使用 malloc、calloc、realloc、free来进…

AI-数学-高中-43常见函数的导数

原作者视频&#xff1a;【导数】【一数辞典】2常见函数的导数_哔哩哔哩_bilibili

【C++】——类和对象(构造函数,析构函数,拷贝构造函数,赋值运算符重载)

创作不易&#xff0c;多多支持&#xff01; 前言 相信你对这几个知识点有点混淆&#xff0c;相信看完以后&#xff0c;你会对此有一个清晰的认识。 一 类的6个默认成员函数 如果我们写一个类&#xff0c;但是类里面什么都没有&#xff0c;我们称之为空类。 其实这个类也不…

AWS SES发送邮件如何正确配置?操作指南?

AWS SES发送邮件有哪些限制&#xff1f;AWS SES发信的注意事项&#xff1f; AWS SES作为亚马逊云服务提供的一项高效、可靠的电子邮件发送服务&#xff0c;受到了众多企业的青睐。然而&#xff0c;如何正确配置AWS SES发送邮件。AokSend将详细解析AWS SES发送邮件的配置过程&a…

《苍穹外卖》Day07部分知识点记录

一、菜品缓存 减少查询数据库的次数&#xff0c;优化性能 客户端&#xff1a; package com.sky.controller.user;import com.sky.constant.StatusConstant; import com.sky.entity.Dish; import com.sky.result.Result; import com.sky.service.DishService; import com.sky…

搜维尔科技:如何选择最佳的xsens动作捕捉设备

xsens介绍 如何选择最佳的xsens动作捕捉设备 选择最佳的 Xsens 动作捕捉设置并不总是像我们希望的那样简单。根据每个人的情况&#xff0c;会有不同的选择、要求和挑战。 这就是我们创建此博客的原因&#xff1a;帮助您做出最适合您的决定。 您已经决定继续使用 Xsens 了吗…

电表抄表系统:现代能源管理的革新

1.界定和功能 电表抄表系统是一种前沿的自动化控制&#xff0c;用以远程控制搜集、解决与分析电表数据。它取代了传统的人工抄水表方法&#xff0c;提高了效率&#xff0c;降低了不正确&#xff0c;并且为供电公司带来了实时能源消耗信息。系统软件的主要作用包含全自动载入电…

大模型实战—通义千问大模型微调

通义千问大模型微调 在之前的文章中&#xff0c;我分享了一些使用大语言模型开发应用的方法&#xff0c;也介绍了几个开源大语言模型的部署方式&#xff0c; 有同学给我留言说想知道怎么训练自己的大语言模型&#xff0c;让它更贴合自己的业务场景。完整的大语言模型训练成本…

第十五届蓝桥杯省赛第二场PythonB组A题【进制】题解(AC)

解题思路 按照题意进行模拟&#xff0c;计算 x x x 的 b b b 进制过程中&#xff0c;若出现余数大于 9 9 9&#xff0c;则说明 x x x 的 b b b 进制一定要用字母进行表示。 x 8100178706957568def check(x, b):while x:if x % b > 10:return Falsex // breturn True…

Flink的安装、项目创建、任务打包和部署完整实现,任务实现使用JAVA语言

Flink资源下载地址 Flink安装包下载地址 一、本地模式安装Flink 1、在Linux服务上&#xff0c;创建flink文件夹 mkdir flink 2、上传文件并解压 tar -zxvf flink-1.14.6-bin-scala_2.11.tgz 解压完成后&#xff0c;如图&#xff1a; 3、启动Flink 进入到解压目录下&#x…

男士休闲裤比较好的品牌有哪些?高品质休闲男装推荐

穿衣服最重要的并不是要求多好看多时尚&#xff0c;相信绝大部分年纪在23岁以上的男同胞们更希望穿一些简约好搭配的款式&#xff0c;更重要的其实就是要求质量耐穿&#xff0c;以及有足够好的舒适性。 但是现在市面上的品牌实在是太多了&#xff0c;而且质量也参差不齐&#x…

【保姆级讲解下gateway基本配置】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

pwn--realloc [CISCN 2019东南]PWN5

首先学习一下realloc这个函数&#xff0c;以下是文心一言的解释&#xff1a; realloc是C语言库函数之一&#xff0c;用于重新分配内存空间。它的主要功能是调整一块内存空间的大小。当需要增加内存空间时&#xff0c;realloc会分配一个新的更大的内存块&#xff0c;然后将原内…

QT从入门到实战x篇_22_番外1_Qt事件系统

文章目录 1. Qt事件系统简介1.1 事件的来源和传递1.2 事件循环和事件分发1.2.1 QT消息/事件循环机制1.2.1.1 机制解释1.2.1.2 两个问题 1.2.2 事件分发 2. 事件过滤基础2.1 什么是事件过滤器&#xff08;Event Filter&#xff09;&#xff1f;2.2 如何安装事件过滤器 3. 事件过…

《QT实用小工具·四十》显示帧率的控件

1、概述 源码放在文章末尾 该项目实现了可以显示帧率的控件&#xff0c;项目demo演示如下所示&#xff1a; 、 项目部分代码如下所示&#xff1a; #ifndef FPSITEM_H #define FPSITEM_H#include <QQuickItem>class FpsItem : public QQuickItem {Q_OBJECTQ_PROPERTY(i…