Something consider me a long time. Lets say that we have written test class:
final class BearerTokenManagerTests: XCTestCase {
private var bearerTokenManager: BearerTokenManager!
private var bearerTokenProvider: BearerTokenProvider!
private var stubKeyValueStore: KeyValueStoreDummyStub!
private var scheduler: TestScheduler!
private var disposeBag: DisposeBag!
override func setUp() {
super.setUp()
stubKeyValueStore = KeyValueStoreDummyStub()
bearerTokenProvider = BearerTokenProvider(keyValueStore: stubKeyValueStore)
bearerTokenManager = BearerTokenManager(bearerTokenProvider: bearerTokenProvider)
scheduler = TestScheduler(initialClock: 0)
disposeBag = DisposeBag()
}
override func tearDown() {
stubKeyValueStore = nil
bearerTokenProvider = nil
bearerTokenManager = nil
scheduler = nil
disposeBag = nil
super.tearDown()
}
func test_bearerToken_observeChanges() {
let bearerToken = scheduler.createObserver(BearerTokenManagerType.BearerToken.self)
bearerTokenManager.bearerToken
.bind(to: bearerToken)
.disposed(by: disposeBag)
scheduler.start()
// every update should be saved in key value store
bearerTokenManager.update(bearerToken: "123")
XCTAssertEqual(stubKeyValueStore.string(forKey: "BearerToken"), "123")
bearerTokenManager.update(bearerToken: "456")
XCTAssertEqual(stubKeyValueStore.string(forKey: "BearerToken"), "456")
bearerTokenManager.update(bearerToken: "789")
XCTAssertEqual(stubKeyValueStore.string(forKey: "BearerToken"), "789")
// every udpate should be emited
XCTAssertEqual(bearerToken.events, [
.next(0, nil), // by default (on start) token equal to nil
.next(0, "123"),
.next(0, "456"),
.next(0, "789"),
])
}
}
Is tearDown
calling for cleaning purposes necessary?
Why I thinking it could be not necessary:
setUp
resets everything.BearerTokenManagerTests
ends then everything should deallocatesWhy I not sure
BearerTokenManagerTests
ends then everything should deallocates” could be wrongRxScheduler
side effectsCould someone share their experience? Do you clean up stuff in tearDown
? Is reseting properties in setUp
enough?
According to this article: https://qualitycoding.org/xctestcase-teardown/
XCTest creates a new
XCTestCase
instance for every individual test invocation but doesn'tdeinit
any of them after completion.
I have created demo app in Xcode 11.7 and behavior is still the same.
import UIKit
var counter = 0
class ViewController: UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
counter += 1;
print("Created ViewController, currently living: \(counter)")
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
deinit {
counter -= 1;
print("Destroyed ViewController, currently living: \(counter)")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
tearDown()
class ViewControllerTests: XCTestCase {
var vc: ViewController!
override func setUp() {
super.setUp()
vc = ViewController()
}
override func tearDown() {
vc = nil
super.tearDown()
}
func test_a() {
XCTAssert(true == true)
}
func test_b() {
XCTAssert(true == true)
}
func test_c() {
XCTAssert(true == true)
}
}
Output:
Test Suite 'ViewControllerTests' started at 2020-09-13 14:44:15.889
Test Case '-[DemoTests.ViewControllerTests test_a]' started.
Created ViewController, currently living: 1
Destroyed ViewController, currently living: 0
Test Case '-[DemoTests.ViewControllerTests test_a]' passed (0.001 seconds).
Test Case '-[DemoTests.ViewControllerTests test_b]' started.
Created ViewController, currently living: 1
Destroyed ViewController, currently living: 0
Test Case '-[DemoTests.ViewControllerTests test_b]' passed (0.000 seconds).
Test Case '-[DemoTests.ViewControllerTests test_c]' started.
Created ViewController, currently living: 1
Destroyed ViewController, currently living: 0
Test Case '-[DemoTests.ViewControllerTests test_c]' passed (0.000 seconds).
Test Suite 'ViewControllerTests' passed at 2020-09-13 14:44:15.891.
Executed 3 tests, with 0 failures (0 unexpected) in 0.002 (0.003) seconds
Test Suite 'sdadasTests.xctest' passed at 2020-09-13 14:44:15.892.
Executed 3 tests, with 0 failures (0 unexpected) in 0.002 (0.003) seconds
Test Suite 'Selected tests' passed at 2020-09-13 14:44:15.892.
Executed 3 tests, with 0 failures (0 unexpected) in 0.002 (0.004) seconds
tearDown()
class ViewController2Tests: XCTestCase {
var vc: ViewController!
override func setUp() {
vc = ViewController()
}
func test_a() {
XCTAssert(true == true)
}
func test_b() {
XCTAssert(true == true)
}
func test_c() {
XCTAssert(true == true)
}
}
Output:
Test Suite 'ViewController2Tests' started at 2020-09-13 14:47:43.067
Test Case '-[sdadasTests.ViewController2Tests test_a]' started.
Created ViewController, currently living: 1
Test Case '-[DemoTests.ViewController2Tests test_a]' passed (0.001 seconds).
Test Case '-[DemoTests.ViewController2Tests test_b]' started.
Created ViewController, currently living: 2
Test Case '-[DemoTests.ViewController2Tests test_b]' passed (0.000 seconds).
Test Case '-[DemoTests.ViewController2Tests test_c]' started.
Created ViewController, currently living: 3
Test Case '-[DemoTests.ViewController2Tests test_c]' passed (0.000 seconds).
Test Suite 'ViewController2Tests' passed at 2020-09-13 14:47:43.070.
Executed 3 tests, with 0 failures (0 unexpected) in 0.002 (0.003) seconds
Test Suite 'sdadasTests.xctest' passed at 2020-09-13 14:47:43.070.
Executed 3 tests, with 0 failures (0 unexpected) in 0.002 (0.003) seconds
Test Suite 'Selected tests' passed at 2020-09-13 14:47:43.071.
Executed 3 tests, with 0 failures (0 unexpected) in 0.002 (0.004) seconds
Like you can see in the example without tearDown()
initialize inside setUp()
does not assign new object to the same property. Every tests create individual instance and doesn't deinit
it after completion. Only the end of the whole XCTestCase
instances will be deallocated.
In small project it probably doesn't matter that much.
But if you have a lot of tests in one XCTestCase
and you are creating a lot of data in setUp()
(e.g. stubs that takes a lot of memory) you should consider using tearDown()
because every test will keep it own copy of data from setUp()
until whole XCTestCase
will be completed and you can end up with memory limits issues.