Требуется ли вызов tearDown?

Что-то меня считают давно. Допустим, мы написали тестовый класс:

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"),
        ])
    }
}

Является tearDown вызов для очистки необходим?

Почему я подумал, что в этом нет необходимости:

  • Перед каждым следующим тестом setUp сбрасывает все.
  • Когда тесты в BearerTokenManagerTests заканчивается, тогда все должно быть освобождено

Почему я не уверен

  • Предполагая, что "Когда тесты в BearerTokenManagerTests заканчивается, тогда все должно быть освобождено "может быть неправильно
  • Я беспокоился о RxScheduler побочные эффекты
  • Кое-что я еще не знаю

Может кто-нибудь поделится своим опытом? Вы убираете вещи вtearDown? Сбрасывает свойства вsetUp довольно?

0 ответов

Быстрый ответ

Согласно этой статье: https://qualitycoding.org/xctestcase-teardown/

XCTest создает новый XCTestCase экземпляр для каждого отдельного вызова теста, но не deinit любой из них после завершения.

Демо

Я создал демонстрационное приложение в Xcode 11.7, и его поведение осталось прежним.

Тестируемая система

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.
    }
}

TestCase с 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)
    }
}

Вывод:

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

TestCase без 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)
    }
}

Вывод:

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

Длинный ответ

Как вы можете видеть в примере без tearDown() инициализировать внутри setUp()не назначает новый объект тому же свойству. Каждый тест создает отдельный экземпляр и не deinitэто после завершения. Только конец всего XCTestCase экземпляры будут освобождены.

В небольшом проекте это, наверное, не имеет большого значения.

Но если у вас много тестов в одном XCTestCase и вы создаете много данных в setUp() (например, заглушки, занимающие много памяти), вам следует подумать об использовании tearDown() потому что каждый тест будет хранить свою копию данных из setUp() пока не все XCTestCase будет завершена, и вы можете столкнуться с проблемами ограничения памяти.

Другие вопросы по тегам