I didn’t think I needed or wanted another testing framework. Turns out it takes ten minutes to learn and actually makes my life easier. What’s not to like?
Assertions
The new framework replaces all XCTAssert functions with just three:
#expect()
#expect(throws:)
#require()
Mind the change:
Natural language assertions are deprecated in favor of more expressive and concise APIs. We see this trend in many features of the language: async/await, trailing closure syntax, property wrappers, result builders, implicit return, keypath expressions, macros, etc.
Apple explicitly commented on this change on the document ‘A New Direction for Testing in Swift’. They favor a concise API that is easy to learn and maintain, without specialized matchers.
Organizing Tests
A test is a function annotated with @Test.
Organizing Tests in Suites
Optionally, functions may be grouped in objects and be annotated with @Suite.
Fine print:
Suites can be any type (struct, enum, class, or actor), but classes must be final. Note that classes may inherit from another, but tests can only run from those that are final.
A suite object must have an initializer without arguments. It doesn’t matter its kind, whether it is private, async, throwing or not.
Suites can be nested.
A separate instance of the object is created to run each test function. This means you can use init/deinit as replacement for XCTest setup/teardown.
Organizing Tests with Tags
Objects and functions may have arbitrary tags created by the user. This enhances your ability to group them in different ways in the Xcode test navigator.
Tests Traits
Optionally, add more traits to your tests:
Parameterizing functions
Did you ever tested values from an array of data? Now you can declare your intention to do so and let the library record the results. This is accomplished using the @Test arguments trait.
Noteworthy:
Enums can also be passed as allCases if they support CaseIterable.
You may also pass Array, Set, OptionSet, Dictionary, and Range.
Tests can be parameterized with a maximum of two collections.
Testing Asynchronous Conditions
As with XCTest, you may add async and/or throws to the signature of a test function. If your test should run in @MainActor, you are free to add that too.
Compatibility with XCTest
You can mix XCTest and Testing in the same target. Migrating is easy: drop every XCTest reference and add the Testing annotations we saw in this document.