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

Posted

技术标签:

【中文标题】UnitTest 我应该使用拆卸和设置吗【英文标题】:UnitTest should I have to use teardown and setup 【发布时间】:2019-05-06 12:00:35 【问题描述】:

我想测试这样一个类:

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(static) 和 instance setUptearDown 方法。 static 被调用一次,instanceeach 测试之前和之后被调用。参考:developer.apple.com/documentation/xctest/xctestcase/… qualitycoding.org/xctestcase-teardown 【参考方案1】:

注意

var foo: Foo! = Foo()

override func tearDown() 
    foo = nil

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

这可能会导致问题,特别是如果 Foo 向共享控制器(如 NotificationCenter)注册自身。

相反,做

private var foo: Foo!

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


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

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

【讨论】:

" 在运行任何测试之前。"你的意思是有 5 个实例吗 1 在键入 5 个测试用例之后 2. 在单击 FooTests 的测试按钮之后(运行所有测试用例) 3. 单击 5 个测试用例中的任何一个来运行测试。 (即使点击一个测试用例,已经有 5 个实例了?)谢谢! 是的。即使您“运行单个测试”,我也很确定它会先实例化每个测试,然后运行您指定的测试。【参考方案2】:

他们的行为相似但有区别。要了解差异,您可以添加到测试类的 init 和 deinit 方法中:

class Foo 
    var number: Int = 0

    init() 
        print("Init")
    

    deinit 
        print("Deinit")
    

现在您将看到在第一个案例中 init 和 deinit 在每个测试中调用。 因为 setUp 和 tearDown 是实例方法,在运行测试之前和之后调用。

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

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

【讨论】:

如果这样number应该在testBCD中改为10,对吧? 没有。因为 XCTest 为每个测试用例创建了两个测试类的实例。因此,您在每次测试时都使用 Foo 实例的副本。 嘿@Anton,我知道了。 Acutally 相同的功能,只是没有tearDown,然后在完成每个测试用例时发布。谢谢! 我什至在没有setUptearDown 的情况下进行了测试,initdeinit 都被调用了两次。 :)

以上是关于UnitTest 我应该使用拆卸和设置吗的主要内容,如果未能解决你的问题,请参考以下文章

unittest测试框架_4_装饰器

unittest单元测试框架总结

我们应该在 UnitTest 程序集上使用 FxCop 吗?

Python基础入门-unittest单元测试框架

unittest 用例编写,套件执行

在 django 中设置拆卸登录注销的正确方法