XCTestCase has many methods as part of its lifecycle. It has a class setup method that executes only once before the execution of the first test. In this method, we can setup the initial state of all test methods. XCTestCase also offers the class teardown method, called after all tests have been executed to provide an opportunity for clean-up. Similar to class setup and class teardown, we have the setup and teardown methods that called accordingly on the beginning and the end of each test method.
The following code—based on the Apple’s documentation https://developer.apple.com/documentation/xctest/xctestcase/understanding_setup_and_teardown_for_test_methods—shows the sequence of which each method is being called:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
import XCTest @testable import TestCaseLifecycle class TestCaseLifecycleTests: XCTestCase { // This code is based on Apples' documentation https://developer.apple.com/documentation/xctest/xctestcase/understanding_setup_and_teardown_for_test_methods override class func setUp() { // 1. super.setUp() // This is the setUp() class method. // It is called before the first test method begins. // Set up any overall initial state here. print("LOG: Class setup") } override func setUp() { // 2. super.setUp() // This is the setUp() instance method. // It is called before each test method begins. // Set up any per-test state here. print("LOG: instance method setup") } func testMethod1() { // 3. // This is the first test method. // Your testing code goes here. print("LOG: test method 1") addTeardownBlock { // 4. // Called when testMethod1() ends. print("LOG: teardown block test method 1") } } func testMethod2() { // 5. // This is the second test method. // Your testing code goes here. print("LOG: test method 2") addTeardownBlock { // 6. // Called when testMethod2() ends. print("LOG: first teardown block test method 2") } addTeardownBlock { // 7. // Called when testMethod2() ends. print("LOG: second teardown block test method 2") } } override func tearDown() { // 8. // This is the tearDown() instance method. // It is called after each test method completes. // Perform any per-test cleanup here. super.tearDown() print("LOG: instance method tearDown") } override class func tearDown() { // 9. // This is the tearDown() class method. // It is called after all test methods complete. // Perform any overall cleanup here. super.tearDown() print("LOG: Class tearDown") } } |
By executing the above code we get the following logs:
LOG: Class setup
LOG: instance method setup
LOG: test method 1
LOG: teardown block test method 1
LOG: instance method tearDown
LOG: instance method setup
LOG: test method 2
LOG: second teardown block test method 2
LOG: first teardown block test method 2
LOG: instance method tearDown
LOG: Class tearDown
One interesting thing we notice is that the teardown blocks execute in “last-in-first-out” order. This is something expected according to the documentation.