Xcode项目中使用Quick测试的正确打开方式

本人的运行环境Xcode 9.2 + Swift 4.0 + CocoaPods 1.5.3,虽然不是最新版本但也基本符合目前总体的开发环境。

Quick库是用于Swift(和ObjC)语言的TDD框架,它的最佳伴侣是Nimble库。

参考github中Quick库在Pods中的配置方法:

# Podfile

use_frameworks!

target "MyApp" do
  # Normal libraries

  abstract_target 'Tests' do
    inherit! :search_paths
    target "MyAppTests"
    target "MyAppUITests"

    pod 'Quick'
    pod 'Nimble'
  end
end

在实际项目中出错,提示不可以在抽象目标中继承:

[!] Invalid Podfile file: [!] Cannot set inheritance for abstract target definition..

测试发现,应该变通写为如下形式:

target 'LightHabitTests' do
      inherit! :search_paths

      pod 'Quick'
      pod 'Nimble'
end

使用子目标的原因是我们只希望在测试时使用Quick和Nimble库,而不是在实际项目中。如果你在实际项目中使用import Quick,就会出现找不到Quick库的情况,而你在测试类中导入Quick库,一切都很美好 ;)

因为项目最初没有包含测试,现在需要加入测试(半途才加入测试,很坏的习惯,不要学!!!)

在Xcode中新建一个测试target:


这里写图片描述

打开新建的XXXTests.swift文件,删除其中全部内容,替换为如下代码:

import Quick
import Nimble

@testable import LightHabit

class LightHabitTests:QuickSpec{
    override func spec(){
        //所有测试放在这里
    }
}

这样做之所以行得通的原因是Quick & Nimble的底层仍是XCTest,只是做了进一步的包装.

下面我们实际写2个测试来看看。

RecentAccessValue是我在项目中使用的一个类,用来存放最近访问过的目录,当用户访问一个目录时会调用RecentAccessValue.accessedWith(folderNode:NodeEx)方法。RecentAccessValue有两个特点:

  1. 最多只保留3条访问记录
  2. 忽略重复访问的目录

据此我们很快可以figure out出3个测试

  1. 当记录不满3条时插入会导致记录增加
  2. 当记录达到3条时插入不会导致记录增加
  3. 当插入重复记录时不会导致记录增加

我们首先需要创建“全局”变量和“先决”hook方法(用过Ruby里的RSpec都知道…)

所谓”全局”变量是3个测试都会用到的变量,我们把它提升一个层次;而“先决”hook方法就是每个测试在执行前都会先运行的方法,一般用来初始化全局变量:

override func spec(){
    var folders:[Folder]!
    var recentAccessValue:RecentAccessValue!

    describe("RecentAccessValueSpec"){
        beforeEach {
            let normalFolder = Folder(name: "一般", expand: false)
            let myFolder = Folder(name: "已完成", expand: true, isInRoot: true)
            let trashFolder = Folder(name: "垃圾箱", expand: true, isInRoot: true)

            folders = [normalFolder,myFolder,trashFolder]

            recentAccessValue = RecentAccessValue()
            recentAccessValue.accessedWith(folderNode: normalFolder.selfNode)
            recentAccessValue.accessedWith(folderNode: myFolder.selfNode)
        }
    }
}

以下分别对应上面3个测试:

context("当插入非重复的FolderNode时"){ it("应该可以插入"){ recentAccessValue.accessedWith(folderNode: folders[2].selfNode) expect(recentAccessValue.count).to(equal(3)) } } context("当已经含有3条记录时"){ it("再插入时应该始终保持3条记录"){ recentAccessValue.accessedWith(folderNode: folders[2].selfNode) let newFolder = Folder(name: "NewFolder", expand: true) recentAccessValue.accessedWith(folderNode: newFolder.selfNode) expect(recentAccessValue.count).to(equal(3)) } } context("当插入重复的FolderNode时"){ it("应该忽略插入"){ recentAccessValue.accessedWith(folderNode: folders[0].selfNode) expect(recentAccessValue.count).to(equal(2)) } }

可以看到Quick是符合DSL设计模式的,像英语一样可读性很好。

Xcode中使用Cmd+U快捷键开始单元测试,测试结果应该全部通过:


这里写图片描述

当然通常TDD测试不是这么玩的,应该是

失败->成功->重构

的模式,但这里从学习的角度来看,也是可以的。

我们除了可以用Quick做普通的功能测试外,还可以做UI测试,但限于篇幅这里不做展开,大家可以自行google check。

感谢观赏 ;)

相关文章
相关标签/搜索