iOS学习笔记iOS程序猿

iOS UnitTest 学习 (二) 了解单元测试的机制,以

2021-07-07  本文已影响0人  DingGa

前言

除了断言,还有更多的测试。XCTest 什么时候创建和运行测试?iOS程序员特别容易对测试生命周期做出错误的假设。这些假设会导致测试设计中的错误。

比如我们经常遇到的,一个测试用例,在单独运行的情况下可以测试通过,但是在项目组合测试中失败,为了避免不稳定的测试,我们需要给测试一个稳定,干净的环境.

测试方法中的代码组织成三个部分来明确这些阶段:

记住AAA 是单元测试的重要部分

XCTest的使用

   func test_methodOne() {
        let sut = MyClass()

        sut.methodOne()

        // Normally, assert something
    }

名称sut代表被测系统,通常缩写为SUT。这是“我们正在测试的东西”的常用术语。与这个简单的例子不同,测试通常有很多对象在起作用。使用像sut这样一致的名称可以清楚地表明测试将作用于哪个对象。它还可以更轻松地重用测试代码片段。

XCTest 测试机制

class MyClassTests: XCTestCase {
    private let sut = MyClass()

    func test_methodOne() {
        sut.methodOne()

        // Normally, assert something
    }

    func test_methodTwo() {
        sut.methodTwo()

        // Normally, assert something
    }
}
举例

MyClassTests 有两个测试方法 test_methodOnetest_methodTwo
那么,在XCTest运行时, 会找到MyClassTests。它搜索以test开头的方法名称,并找到两个。所以它创建了MyClassTests 的两个实例:一个实例运行test_methodOne,另一个运行test_methodTwo

使用setUp(),tearDown()优化

XCTestCase定义了两个方法,setUp和tearDown,这两个方法设计为在子类中被覆盖。

XCTest 中的测试运行程序保证每个测试用例的顺序如下:

class MyClassTests: XCTestCase {
    private var sut: MyClass!

    override func setUp() {
        super.setUp()
        sut = MyClass()
    }

    override func tearDown() {
        sut = nil
        super.tearDown()
    }

    func test_methodOne() {
        sut.methodOne()

        // Normally, assert something
    }

    func test_methodTwo() {
        sut.methodTwo()

        // Normally, assert something
    }
}

注意: 初始化存储属性的测试类中。要将这些属性从let更改为var。并且添加

Tips 检测测试Log

通过如图所示,我们可以快速找到test的失败消息


截屏2021-07-07 下午8.03.37.png

如何写好项目里的测试?

代码测试覆盖率

在 Xcode 菜单中,选择ProductSchemeEdit Scheme...或按 - <

截屏2021-07-07 下午9.13.20.png

现在我们就设置好了测试覆盖率

+ U 试一下

截屏2021-07-07 下午9.21.27.png

并且 Xcode 菜单中选择Editor ▶ Code Coverage。

截屏2021-07-07 下午9.23.06.png

红色区域的数字代表我们这段代码测试了几次,在红色条纹区域。将鼠标光标悬停在该区域,您会看到情况发生了变化,如下所示:

截屏2021-07-07 下午9.24.42.png

绿色部分显示了我们接触过的代码。带有else 的那一行部分是绿色的,部分是红色的。这为我们提供了一种查看行内代码覆盖率的方法。

为现有代码添加测试

举例

class CoveredClass {

    static func max(_ x: Int, _ y: Int) -> Int {
        if x < y {
            return y
        } else {
            return x
        }
    }
}

如果代码正在使用中,我们就不需要从需求逆向工作。相反,我们可以编写有效地使用遗留代码称为特性测试的内容。这些是捕获代码实际行为的测试。

要编写特性测试,请执行以下操作:

1,2部分

    func test_max_with1And2_shouldReturnSomething() {
        let result = CoveredClass.max(1, 2)

        XCTAssertEqual(result, -123)
    }
截屏2021-07-07 下午9.33.33.png

3.运行测试。这给了我们一条失败消息

4.我们从失败消息中复制实际值2并粘贴到断言中

    func test_max_with1And2_shouldReturn2() {
        let result = CoveredClass.max(1, 2)

        XCTAssertEqual(result, 2)
    }

5.运行

截屏2021-07-07 下午9.37.40.png

我们本次的测试就完成了!!! 通过~

当然,如果你想要更好的测试覆盖率,让我们添加一个测试来覆盖后半部分。
条件是if x < y

    func test_max_with3And2_shouldReturn3() {
        let result = CoveredClass.max(3, 2)

        XCTAssertEqual(result, 3)
    }

这应该给我们 100% 的覆盖率。但是实际上,会由于有个},很难做到100%覆盖率

截屏2021-07-07 下午9.45.53.png

多写几个,也是可以完成100% 覆盖率的,但是,我们不应该成为测试覆盖率的奴隶.

Tips

一个好的测试名称包含三个部分:

上一篇 下一篇

猜你喜欢

热点阅读