Running tests that doesn't use SwiftData with iOS 16

Hi! I'm using SwiftData for iOS 17 widgets in a project that with a minimum target of iOS 15. Our CI is having issues running the iOS 17 simulator (it takes more than 10 minutes to start up) so I'm trying to run the tests using iOS 16, obviously skipping all the SwiftData usages. The app runs just fine in iOS 16 and it has all the @available(iOS 17, iOSApplicationExtension 17, *) annotations for the @Model classes.

But the tests crashes when trying to start the app because it tries to get the metadata of my model classes, which crashes with a nil as the SwiftData library doesn't exist, because the test framework initializes all classes before running.

Is there a workaround for this? Running the tests in an app-supported iOS version should work as we should be able to test different behaviors, right?

Thanks in advance!

Emanuel

(I'm attaching the stack trace of the crash)

Thread 1 Queue : com.apple.main-thread (serial)
#0	0x0000000000000000 in 0x00000000 ()
#1	0x00000001029d13ee in type metadata completion function for WidgetModel.Set ()
#2	0x00000001248cd660 in swift::MetadataCacheEntryBase<(anonymous namespace)::SingletonMetadataCacheEntry, int>::doInitialization(swift::MetadataWaitQueue::Worker&, swift::MetadataRequest) ()
#3	0x00000001248bc327 in swift_getSingletonMetadata ()
#4	0x00000001029ccdd5 in type metadata accessor for WidgetModel.Set ()
#5	0x00000001029d132d in ObjC metadata update function for WidgetModel.Set ()
#6	0x0000000115b25b18 in realizeClassMaybeSwiftMaybeRelock(objc_class*, locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool) ()
#7	0x0000000115b2c907 in realizeAllClasses() ()
#8	0x0000000115b2f05f in objc_copyClassList ()
#9	0x000000015aea6dcd in +[XCTestCase(RuntimeUtilities) _allSubclasses] ()
#10	0x000000015aea6f17 in +[XCTestCase(RuntimeUtilities) allSubclasses] ()
#11	0x000000015ae6de91 in +[XCTestSuite suitesForBundlesIncludingEmptySuites:] ()
#12	0x000000015ae718c2 in -[XCTestSuite _initWithTestConfiguration:] ()
#13	0x000000015ae722b0 in +[XCTestSuite testSuiteForTestConfiguration:] ()
#14	0x000000015ae33943 in __53-[XCTTestRunSession initWithTestConfiguration:error:]_block_invoke_2 ()
#15	0x000000015ae6d0d0 in +[XCTContext _runInChildOfContext:forTestCase:markAsReportingBase:block:] ()
#16	0x000000015ae6cfb0 in +[XCTContext runInContextForTestCase:markAsReportingBase:block:] ()
#17	0x000000015ae338df in __53-[XCTTestRunSession initWithTestConfiguration:error:]_block_invoke ()
#18	0x000000015ae33525 in +[XCTTestRunSession performTestSuiteConstructionInBlock:] ()
#19	0x000000015ae33757 in -[XCTTestRunSession initWithTestConfiguration:error:] ()
#20	0x000000015ae34e4c in -[XCTTestRunSessionProvider executionExtensionWithTestConfiguration:reportingSession:completion:] ()
#21	0x000000015ae3b11c in __128+[XCTExtensionProvider(XCTExecutionExtension_Internal) allExecutionExtensionsWithTestConfiguration:reportingSession:completion:]_block_invoke ()
#22	0x000000015ae83a4b in __69-[NSArray(XCTestAdditions) xct_arrayByApplyingAsyncBlock:completion:]_block_invoke ()
#23	0x000000015ae83bd9 in __XCTAsyncEnumerate_block_invoke.39 ()
#24	0x000000015ae837cb in -[NSArray(XCTestAdditions) xct_arrayByApplyingAsyncBlock:completion:] ()
#25	0x000000015ae3af98 in +[XCTExtensionProvider allExecutionExtensionsWithTestConfiguration:reportingSession:completion:] ()
#26	0x000000015ae68af6 in -[XCTestDriver _runTests] ()
#27	0x000000015ae3290e in _XCTestMain ()
#28	0x000000010ffc8759 in __RunTests_block_invoke_2 ()
#29	0x000000012038e986 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ ()
#30	0x000000012038e148 in __CFRunLoopDoBlocks ()
#31	0x00000001203889cf in __CFRunLoopRun ()
#32	0x0000000120388264 in CFRunLoopRunSpecific ()
#33	0x0000000125a4a24e in GSEventRunModal ()
#34	0x00000001347a47bf in -[UIApplication _run] ()
#35	0x00000001347a95de in UIApplicationMain ()
#36	0x0000000102a3ecef in main at /opt/projects/quizlet-ios/Quizlet-iPhone/AppDelegate.swift:24
#37	0x000000010fe02384 in start_sim ()
#38	0x00000002075243a6 in start ()

You will need to perform conditional compilations.

#if canImport(SwiftData)
import SwiftData
#endif
import UIKit

#if swift(>=5.9)

// Do swift 5.9 things

#else

// Do things before swift 5.9

#endif

Hi! Thanks for the response. That didn't work for me as I'm using Xcode 15 and latest Swift version, so it actually builds ok, but the problem is at runtime.

However, I found out a TEST constant that is set when building for test so I managed to use like this to avoid referencing SwiftData at all when building for test:

#if !TEST
    @Model
#endif
    final class Set {
        // ...
    }

I'm not allowed to test anything related to this part of the application, but at least I don't have to disable the entire test suite in order to merge this feature.

And I hope the CI is fixed soon so I can delete all these conditional code. 🙏

Running tests that doesn't use SwiftData with iOS 16
 
 
Q