Is ENABLE_TESTABILITY visible from Swift code?

Hello,

Is the ENABLE_TESTABILITY build setting visible from source code in a way or another?

#if ENABLE_TESTABILITY
// Expose extra APIs dedicated to tests
#endif

The naive code above does not work, hence my question.

My goal is to test some inner behavior which shouldn't be visible through any public or internal apis. Practically speaking, I was about to count instances of some inner private class:

// MyModule.swift
#if ENABLE_TESTABILITY
var myClassInstanceCount = 0
#endif

private class MyClass {
    init() {
        #if ENABLE_TESTABILITY
        myClassInstanceCount += 1
        #endif
    }
}

// MyModuleTests.swift
import XCTest
@testable import MyModule

func testStuff() {
    // No instance of MyClass was created
    XCTAssertEqual(myClassInstanceCount, 0)
}

It's not, but you can add DEBUG to your "Active Compilation Conditions" in Xcode. (SwiftPM does this by default when building in debug mode.)

Thank you @jrose, yes it is a possibility.

Yet:

  • DEBUG can also be used by clients of the module, and in this case one does not want this testing-only code to be compiled.
  • It is reasonable to run tests without DEBUG, in order to catch release-only issues.

So let's consider this a feature request: please let us distinguish DEBUG from ENABLE_TESTABILITY with #if :-)

Compilation conditions don't affect libraries, only the current module being compiled. (This is different from C preprocessor macros.)

True, but, uh, you can define another condition?

It's a reasonable feature request, and it's been brought up before; no one's really taken it up to champion and implement it because the workaround is so simple.

I 100% understand your pragmatic answers :+1:

Compilation conditions don't affect libraries, only the current module being compiled. (This is different from C preprocessor macros.)

This may reveal a misunderstanding of mine. Aren't dependencies compiled with DEBUG when the main SPM/Xcode target is compiled with DEBUG?

You know, while I'm sure that the "Active Compilation Conditions" build setting is not passed down to dependencies, the current configuration probably is, and in SwiftPM the default addition of -DDEBUG would come from that. Boris or someone else more familiar with SwiftPM and/or Xcode would know better, though.

Thank you Jordan :-)