0

I have created test class like this:

import XCTest

class ExampleTests: XCTestCase {
    private let context = NSManagedObjectContext.mr_()
    func testA() {
        print(#function)
        print(context)
        XCTAssertTrue(true)
    }

    func testB() {
        print(#function)
        print(context)
        XCTAssertTrue(true)
    }
}

and the output on console is the following:

Test Suite 'ExampleTests' started at 2021-08-04 16:33:42.426
Test Case '-[PLZ_Tests.ExampleTests testA]' started.
testA()
NSManagedObjectContext: 0x28210a630> //DIFFERENT INSTANCE
Test Case '-[PLZ_Tests.ExampleTests testA]' passed (0.004 seconds).
Test Case '-[PLZ_Tests.ExampleTests testB]' started.
testB()
NSManagedObjectContext: 0x282109c70> //DIFFERENT INSTANCE
Test Case '-[PLZ_Tests.ExampleTests testB]' passed (0.000 seconds).
Test Suite 'ExampleTests' passed at 2021-08-04 16:33:42.431.

Does it instantiate a whole class again for every unit test in that class?

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
  • 2
    Yes it does. You should read https://developer.apple.com/documentation/xctest/xctestcase/understanding_setup_and_teardown_for_test_methods so you can set up things for each method or for the whole test case – Joakim Danielson Aug 04 '21 at 14:50

1 Answers1

2

Does it instantiate a whole class again for every unit test in that class?

Pedantic, but no. No classes are instantiated. New instances (objects) are instantiated, from the class.

Why there is a new instance of object between unit tests in the same XCTestCase?

Because it’s not the same XCTestCase. The XCTest framework will instantiate one ExampleTests object for every test method. Just like any other Swift type, instance properties with default values will have those evaluated and set before the initializer gets called on the new instance.

In all, there will be 2 NSManagedObjectContext objects, each owned by one of 2 XCTestCase objects. testA will be invoked on one of them, and testB on the other.

That’s an international design decision, probably inspired from other xUnit testing frameworks.

It has several benefits/conveniences.

The most important one is that it allows test methods to use instance variables without trampling over each other (if they were to run in parallel, that would be a huge deal).

Another benefit is that it discourages “communication” between test cases, to prevent them from being order dependant (where one test case sets up some state necessary for another test case to pass). Of course, you could still achieve this by storing the state elsewhere (class variables, global variables, the file system, etc.), but doing that would be “wrong” in a more obvious/noticeable way.

Alexander
  • 59,041
  • 12
  • 98
  • 151