Swift 快速框架内存泄漏
Swift Quick framework memory leak
我正在使用 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
在测试套件中不被调用是正常的?
显然我写的代码不仅保留了对象,而且还是一个反模式。
即使是普通的旧 XCTestCase
也会保留一个对象:
class MyClass {
deinit {
print(self, #function)
}
}
final class MyClassTest: XCTestCase {
let foo = MyClass()
func testMyClass() {
print(foo)
XCTAssert(true)
}
}
deinit
未被调用 foo
。
这是由于XCTestCase
—it never really gets deinit
ed的性质。
因此,应该始终使用 setUp
和 tearDown
来管理 一切 (或更准确地说,具有引用语义的对象)。
我相信这也直接转化为 QuickSpec
,所以我应该始终使用 beforeEach
和 afterEach
来管理对象。
对于 "fix" 这个问题,我应该这样测试:
final class MyClassSpec: QuickSpec {
override func spec() {
describe("") {
let foo: MyClass!
beforeEach { foo = MyClass() }
afterEach { foo = nil }
it("") {
print(foo)
expect(true).to(beTrue())
}
}
}
}
我正在使用 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
在测试套件中不被调用是正常的?
显然我写的代码不仅保留了对象,而且还是一个反模式。
即使是普通的旧 XCTestCase
也会保留一个对象:
class MyClass {
deinit {
print(self, #function)
}
}
final class MyClassTest: XCTestCase {
let foo = MyClass()
func testMyClass() {
print(foo)
XCTAssert(true)
}
}
deinit
未被调用 foo
。
这是由于XCTestCase
—it never really gets deinit
ed的性质。
因此,应该始终使用 setUp
和 tearDown
来管理 一切 (或更准确地说,具有引用语义的对象)。
我相信这也直接转化为 QuickSpec
,所以我应该始终使用 beforeEach
和 afterEach
来管理对象。
对于 "fix" 这个问题,我应该这样测试:
final class MyClassSpec: QuickSpec {
override func spec() {
describe("") {
let foo: MyClass!
beforeEach { foo = MyClass() }
afterEach { foo = nil }
it("") {
print(foo)
expect(true).to(beTrue())
}
}
}
}