UnitTest 我应该使用拆解和设置吗

UnitTest should I have to use teardown and setup

我想测试这样一个class:

class Foo {
    var number: Int = 0
}

在iOS单元测试中,通常测试用例应该是:

class FooTests: XCTestCase {

    var foo: Foo!

    override func setUp() {
        foo = Foo()
    }

    override func tearDown() {
        foo = nil
    }

    func testAbc() {
        print(foo.number)
        foo.number = 10
    }

    func testBCD() {
        print(foo.number)
    }

}

class FooTests: XCTestCase {

     let foo = Foo()

     func testAbc() {
        print(foo.number)
        foo.number = 10
    }

    func testBCD() {
        print(foo.number)
    }

}

我看到输出都是 0,这意味着当每个启动测试用例时,foo 似乎又被初始化了。就像使用 setUptearDown.

两种方法一样吗?

编辑: 感谢@Anton 的回答,我什至在没有 setUp 但使用 tearDown 的情况下进行了测试,然后与同时使用 setUptearDown.

相同
    var foo: Foo! = Foo()

    override func tearDown() {
        foo = nil
    }

他们的行为相似但又有所不同。要了解您可以添加到测试 class init 和 deinit 方法中的区别:

class Foo {
    var number: Int = 0

    init() {
        print("Init")
    }

    deinit {
        print("Deinit")
    }
}

现在您将看到在第一种情况下每次测试都会调用 init 和 deinit。 因为 setUp 和 tearDown 是实例方法并且在 运行 测试之前和之后调用。

但在第二种情况下,init 在创建测试套件期间被调用了两次。发生这种情况是因为您对 foo 常量使用了默认初始化程序。它在 运行 任何测试之前发生的测试用例初始化期间调用。

所以,最好使用第一个选项。因为如果被测试的实例使用了一些全局状态或有副作用,那么你可能会得到不稳定的测试。它们并行存在于内存中。

注意

var foo: Foo! = Foo()

override func tearDown() {
    foo = nil
}

仍然不正确。问题是 Foo 将在实例化测试时创建。所有测试都立即实例化。所以如果这个套件中有 5 个测试用例,那就意味着将有 5 个 FooTests 实例,每个实例都有自己的 Foo。在任何测试之前都是 运行.

这可能会导致问题,尤其是当 Foo 将自己注册到 NotificationCenter 等共享控制器时。

相反,

private var foo: Foo!

override func setUp() {
    super.setUp()
    foo = Foo()
}

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

这保证 foo 将在 运行ning 测试用例的上下文中创建。