【问题标题】:Swift Quick framework memory leakSwift Quick 框架内存泄漏
【发布时间】:2020-05-16 11:01:45
【问题描述】:

我正在使用Quick 来测试我的 Swift 代码。 但是,我认为它不会释放在describe 范围内定义的对象:

class MyClass {
    deinit {
        print(self, #function)
    }
}

final class MyClassSpec: QuickSpec {
    override func spec() {
        describe("") {
            let foo = MyClass()
            it("") {
                print(foo)
                expect(true).to(beTrue())
            }
        }
    }
}

我在deinit 中看不到来自print 的任何输出,并且deinit 中的调试断点没有被捕获。 如果我将foo 移动到it 中,则会调用deinit

这是 Quick 中的错误,还是在测试套件中不调用 deinit 是正常的?

【问题讨论】:

    标签: swift memory-leaks quick-nimble


    【解决方案1】:

    显然我写的代码不仅保留了对象,而且还是一种反模式。

    即使是一个普通的旧 XCTestCase 也会保留一个对象:

    class MyClass {
        deinit {
            print(self, #function)
        }
    }
    
    final class MyClassTest: XCTestCase {
        let foo = MyClass()
    
        func testMyClass() {
            print(foo)
            XCTAssert(true)
        }
    }
    

    deinit 未被调用为 foo

    这是由于XCTestCaseit never really gets deinited 的性质。 所以应该始终使用setUptearDown 来管理一切(或者更准确地说,是具有引用语义的对象)。

    我相信这也直接转换为QuickSpec,所以我应该始终使用beforeEachafterEach 来管理对象。 为了“解决”这个问题,我应该像这样测试:

    final class MyClassSpec: QuickSpec {
        override func spec() {
            describe("") {
                let foo: MyClass!
    
                beforeEach { foo = MyClass() }
                afterEach { foo = nil }
    
                it("") {
                    print(foo)
                    expect(true).to(beTrue())
                }
            }
        }
    }
    

    【讨论】:

    • 我遇到了完全相同的问题,并且我无法在 Web 上找到许多与 Quick specs 中的内存管理相关的资源。我整理了一个非常简单的规范来测试这一点,我自己的发现似乎反映了你的。看起来该行为确实模仿了 XCTest 的行为。因此,除非其他人有比为每个分配实施 afterEach 更好的建议,否则我将继续这样做 ?
    猜你喜欢
    • 2011-01-05
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    相关资源
    最近更新 更多