UITests Memory Allocation

Dear all,

In my current company we heavily rely on UITests in oder to test end to end our feature. Our setup has

  • An home made interprocess communication protocol to communicate between the test target and the app target to communicate complex information without affecting Production Code (e.g. into an #IF DEBUG we can command the app the reset his state without relaunching the simulator instance)

  • over 600 UITests (between iPhone and iPad)

  • we don't use yet Swift UI in our application, everything is handled via UIKit (and no storyboards)

What we observe is that during a Test session the Test target itself keep allocating memory, storing several Malloc blocks that are never deallocated from memory: we are here talking about queries, assertions, xcwaiter results and so on.

From an inspection via the memory debugger we cannot pin point anything related to our current setup, the only visible data is that the memory allocation goes up to about over 800Mb and that the simulator becomes slower and slower.

Does anyone observed such behaviour so far?

I am also looking at some official documentation on the internal of XCTest and how it handles memory allocation, can anyone pinpoint to a possible solution?

Thanks a lot for your attention

Answered by DarioDR in 695058022

Hi,

Thanks for the quick response!

Yes that's exactly what we do, to elaborate more our setup has

  • One BaseTestCase class where we configure the setup and teardown method in oder to allocate and deallocate the app object and other entities that every test case can benefit from.

  • every TestClass inherits from this BaseTestCase and whenever required it makes use of the proper setup and teardown (by overriding the default and naturally invoking their super version)

Is there a way that we can pursue to study what actually Xcode doesn't deallocate?

Is there a reason why Xcode cannot guarantee that the memory would be deallocate per each test and not at the end of the entire test suite? I am asking not because I want to complain about it but because I am genuinely interested in understanding the rationale behind :)

Hoping into an answer I wish you a good day!

Test cases are all instantiated at the start of your test, and don't guaranteed to be deallocated (they usually do at the end of all tests) which means that your XCTestCases live for the full duration of all tests (except if your test runner crashes).

We encourage you to you use -[XCTestCase setUp] (or its variants) to initialize your test case with data (especially large blobs), and -[XCTestCase tearDown] (or its variants) to release it / nil it out.

So instead of

final class MyTestCase: XCTestCase {
    var largeImage = UIImage(named: "LargeImage") // Don't do this, it will live from the very beginning to the very end of all your test runs

    func testA() {}
}

do this:

final class MyTestCase: XCTestCase {
    var largeImage: UIImage!

    func setUp() {
        largeImage = UIImage(named: "LargeImage")
    }

    func tearDown() {
        largeImage = nil
    }

    func testA() {}
}
Accepted Answer

Hi,

Thanks for the quick response!

Yes that's exactly what we do, to elaborate more our setup has

  • One BaseTestCase class where we configure the setup and teardown method in oder to allocate and deallocate the app object and other entities that every test case can benefit from.

  • every TestClass inherits from this BaseTestCase and whenever required it makes use of the proper setup and teardown (by overriding the default and naturally invoking their super version)

Is there a way that we can pursue to study what actually Xcode doesn't deallocate?

Is there a reason why Xcode cannot guarantee that the memory would be deallocate per each test and not at the end of the entire test suite? I am asking not because I want to complain about it but because I am genuinely interested in understanding the rationale behind :)

Hoping into an answer I wish you a good day!

UITests Memory Allocation
 
 
Q