The Swift Testing Framework

Apple's modern testing framework (Xcode 16) replaces XCTest's classes and assertions with macros. Learn import Testing , @Test functions, #expect and #require , parameterized tests with arguments: , @Suite , tags, and async tests.

Learn The Swift Testing Framework in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ @Test and #expect

Import Testing , mark a function @Test , and check results with #expect . No base class and no test prefix required.

2️⃣ #require and Expected Errors

#require throws to stop a test early — ideal for unwrapping. #expect(throws:) verifies that code throws the error you expect.

3️⃣ Parameterized Tests

Pass a collection to @Test(arguments:) and the function runs once per input, reporting each case independently — far cleaner than a hand-written loop.

Your turn. Fill in the import, the test attribute, and the assertion macro.

4️⃣ Suites, Tags, and Async

@Suite groups related tests; traits like .tags(...) add filterable metadata; and any @Test can be async to await directly.

📋 Quick Reference

Write a parameterized test plus a negative case for an age validator.

Practice quiz

Which module do you import to use the Swift Testing framework?

  • Testing
  • SwiftTest
  • Foundation
  • XCTest

Answer: Testing. Swift Testing is provided by the Testing module, so you write import Testing.

Which attribute marks a function as a test in Swift Testing?

  • @TestCase
  • @Check
  • @Test
  • @Spec

Answer: @Test. You annotate a function with the @Test macro to register it as a test.

Which macro replaces XCTAssert for ordinary checks?

  • #check
  • #expect
  • #assert
  • #verify

Answer: #expect. #expect(...) is the core assertion macro in Swift Testing.

What does #require do that #expect does not?

  • Runs faster
  • Logs only
  • Skips the test
  • Stops the test by throwing when the condition fails

Answer: Stops the test by throwing when the condition fails. #require throws and halts the test on failure, so you can safely unwrap or stop early.

How do you run the same test over many inputs?

  • @Test with an arguments: parameter
  • Copy the test
  • @Repeat
  • A for loop only

Answer: @Test with an arguments: parameter. Parameterized tests use @Test(arguments:) to run the function once per input value.

Which attribute groups related tests into a named collection?

  • @Bundle
  • @Suite
  • @Set
  • @Group

Answer: @Suite. @Suite marks a type as a test suite that organizes related @Test functions.

How do you write an asynchronous test in Swift Testing?

  • Use waitForExpectations
  • You cannot
  • Wrap it in DispatchQueue
  • Mark the @Test function async and use await

Answer: Mark the @Test function async and use await. A @Test function can be async, letting you await asynchronous code directly.

How do you express that a test should throw an error?

  • @Throws
  • try?
  • #expect(throws:)
  • XCTAssertThrows

Answer: #expect(throws:). #expect(throws:) verifies that the enclosed expression throws the expected error.

What are traits like .tags(...) used for?

  • Speeding up tests
  • Adding metadata to filter and organize tests
  • Mocking
  • Compiling

Answer: Adding metadata to filter and organize tests. Traits such as tags attach metadata so you can group, filter, and select tests to run.

How does Swift Testing relate to XCTest?

  • It is a modern alternative that can coexist with XCTest
  • It deletes XCTest
  • It is identical to XCTest
  • It only runs on Linux

Answer: It is a modern alternative that can coexist with XCTest. Swift Testing is a newer, macro-based framework that runs alongside existing XCTest tests.