Skip to content

Commit

Permalink
Improve MacroTesting Documentation and Add Swift Testing Integration
Browse files Browse the repository at this point in the history
  • Loading branch information
ajkolean committed Jan 18, 2025
1 parent 1a9dc97 commit 10e7b89
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 41 deletions.
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ You can even have the library automatically re-record the macro expansion direct
file by providing the `record` argument to `assertMacro`:
```swift
assertMacro(["stringify": StringifyMacro.self], record: true) {
assertMacro(["stringify": StringifyMacro.self], record: .all) {
"""
#stringify(a + b)
"""
Expand Down Expand Up @@ -126,13 +126,13 @@ class StringifyMacroTests: XCTestCase {
}
```

You can pass the `isRecording` parameter to `withMacroTesting` to re-record every assertion in the
You can pass the `record` parameter to `withMacroTesting` to re-record every assertion in the
test case (or suite, if you're using your own custom base test case class):

```swift
override func invokeTest() {
withMacroTesting(
isRecording: true
record: .all
) {
super.invokeTest()
}
Expand Down Expand Up @@ -187,6 +187,41 @@ func testNonAsyncFunctionDiagnostic() {
}
```

## Integration with Swift Testing

If you are using Swift's built-in Testing framework, this library also supports it. Instead of relying solely
on XCTest, you can configure your tests using the `Trait` system provided by `swift-testing`. For example:

```swift
import Testing
import MacroTesting

@Suite(
.macros(
record: .missing // Record only missing snapshots
macros: ["stringify": StringifyMacro.self],
)
)
struct StringifyMacroSwiftTestingTests {
@Test
func testStringify() {
assertMacro {
"""
#stringify(a + b)
"""
} expansion: {
"""
(a + b, "a + b")
"""
}
}
}
```

Additionally, the `record` parameter in `macros` can be used to control the recording behavior for all
tests in the suite. This value can also be configured using the `SNAPSHOT_TESTING_RECORD` environment
variable to dynamically adjust recording behavior based on your CI or local environment.

## Documentation

The latest documentation for this library is available [here][macro-testing-docs].
Expand Down
42 changes: 25 additions & 17 deletions Sources/MacroTesting/AssertMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import XCTest
/// }
/// ```
///
/// > Tip: Use ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j`` in your
/// > Tip: Use ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s`` in your
/// > test case's `invokeTest` to avoid the repetitive work of passing the macro mapping to every
/// > `assertMacro`:
/// >
Expand All @@ -96,17 +96,19 @@ import XCTest
///
/// - Parameters:
/// - macros: The macros to expand in the original source string. Required, either implicitly via
/// ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j``, or explicitly
/// ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s``, or explicitly
/// via this parameter.
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion
/// (e.g., `.spaces(2)`). Defaults to the original source's indentation if unspecified. If the
/// original source lacks indentation, it defaults to `.spaces(4)`.
/// - isRecording: Always records new snapshots when enabled.
/// - record: The recording strategy to use for the macro expansion. If not provided, it defaults to the current
/// configuration, which can be set using the `SNAPSHOT_TESTING_RECORD` environment variable
/// - originalSource: A string of Swift source code.
/// - diagnosedSource: Swift source code annotated with expected diagnostics.
/// - fixedSource: Swift source code with expected fix-its applied.
/// - expandedSource: Expected Swift source string with macros expanded.
/// - file: The file where the assertion occurs. The default is the filename of the test case
/// - fileID: The file ID where the assertion occurs.
/// - filePath: The file where the assertion occurs. The default is the filename of the test case
/// where you call this function.
/// - function: The function where the assertion occurs. The default is the name of the test
/// method where you call this function.
Expand Down Expand Up @@ -480,22 +482,24 @@ extension BasicMacroExpansionContext {

/// Asserts that a given Swift source string matches an expected string with all macros expanded.
///
/// See ``assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:file:function:line:column:)-pkfi``
/// See ``assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:fileID:file:function:line:column:)-90l38``
/// for more details.
///
/// - Parameters:
/// - macros: The macros to expand in the original source string. Required, either implicitly via
/// ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j``, or explicitly
/// ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s``, or explicitly
/// via this parameter.
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion
/// (e.g., `.spaces(2)`). Defaults to the original source's indentation if unspecified. If the
/// original source lacks indentation, it defaults to `.spaces(4)`.
/// - isRecording: Always records new snapshots when enabled.
/// - record: The recording strategy to use. If not provided, it defaults to the current
/// configuration, which can be set using the `SNAPSHOT_TESTING_RECORD` environment variable.
/// - originalSource: A string of Swift source code.
/// - diagnosedSource: Swift source code annotated with expected diagnostics.
/// - fixedSource: Swift source code with expected fix-its applied.
/// - expandedSource: Expected Swift source string with macros expanded.
/// - file: The file where the assertion occurs. The default is the filename of the test case
/// - fileID: The file ID where the assertion occurs.
/// - filePath: The file where the assertion occurs. The default is the filename of the test case
/// where you call this function.
/// - function: The function where the assertion occurs. The default is the name of the test
/// method where you call this function.
Expand Down Expand Up @@ -557,7 +561,7 @@ public func assertMacro(
/// ```swift
/// class StringifyTests: XCTestCase {
/// override func invokeTest() {
/// withMacroTesting(isRecording: true, macros: [StringifyMacro.self]) {
/// withMacroTesting(record: .all, macros: [StringifyMacro.self]) {
/// super.invokeTest()
/// }
/// }
Expand All @@ -568,7 +572,8 @@ public func assertMacro(
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion
/// (e.g., `.spaces(2)`). Defaults to the original source's indentation if unspecified. If the
/// original source lacks indentation, it defaults to `.spaces(4)`.
/// - isRecording: Determines if a new macro expansion will be recorded.
/// - record: The recording strategy to use for the macro expansion. If not provided, it defaults to the current
/// configuration, which can be set using the `SNAPSHOT_TESTING_RECORD` environment variable.
/// - macros: Specifies the macros to be expanded in the input Swift source string.
/// - operation: The operation to run with the configuration updated.
public func withMacroTesting<R>(
Expand All @@ -589,14 +594,15 @@ public func withMacroTesting<R>(

/// Customizes `assertMacro` for the duration of an operation.
///
/// See ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j`` for
/// See ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s`` for
/// more details.
///
/// - Parameters:
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion
/// (e.g., `.spaces(2)`). Defaults to the original source's indentation if unspecified. If the
/// original source lacks indentation, it defaults to `.spaces(4)`.
/// - isRecording: Determines if a new macro expansion will be recorded.
/// - record: The recording strategy to use for the macro expansion. If not provided, it defaults to the current
/// configuration, which can be set using the `SNAPSHOT_TESTING_RECORD` environment variable.
/// - macros: Specifies the macros to be expanded in the input Swift source string.
/// - operation: The operation to run with the configuration updated.
public func withMacroTesting<R>(
Expand All @@ -617,14 +623,15 @@ public func withMacroTesting<R>(

/// Customizes `assertMacro` for the duration of an operation.
///
/// See ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j`` for
/// more details.
/// See ``assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:fileID:file:function:line:column:)-90l38``
/// for more details.
///
/// - Parameters:
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion
/// (e.g., `.spaces(2)`). Defaults to the original source's indentation if unspecified. If the
/// original source lacks indentation, it defaults to `.spaces(4)`.
/// - isRecording: Determines if a new macro expansion will be recorded.
/// - record: The recording strategy to use for the macro expansion. If not provided, it defaults to the current
/// configuration, which can be set using the `SNAPSHOT_TESTING_RECORD` environment variable.
/// - macros: Specifies the macros to be expanded in the input Swift source string.
/// - operation: The operation to run with the configuration updated.
public func withMacroTesting<R>(
Expand All @@ -643,14 +650,15 @@ public func withMacroTesting<R>(

/// Customizes `assertMacro` for the duration of an operation.
///
/// See ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j`` for
/// See ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s`` for
/// more details.
///
/// - Parameters:
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion
/// (e.g., `.spaces(2)`). Defaults to the original source's indentation if unspecified. If the
/// original source lacks indentation, it defaults to `.spaces(4)`.
/// - isRecording: Determines if a new macro expansion will be recorded.
/// - record: The recording strategy to use for the macro expansion. If not provided, it defaults to the current
/// configuration, which can be set using the `SNAPSHOT_TESTING_RECORD` environment variable
/// - macros: Specifies the macros to be expanded in the input Swift source string.
/// - operation: The operation to run with the configuration updated.
public func withMacroTesting<R>(
Expand Down
10 changes: 6 additions & 4 deletions Sources/MacroTesting/Documentation.docc/AssertMacro.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# ``MacroTesting/assertMacro(_:record:of:diagnostics:fixes:expansion:file:function:line:column:)-6hxgm``
# ``MacroTesting/assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:fileID:file:function:line:column:)-8zqk4``

## Topics

### Overloads

- ``assertMacro(_:record:of:diagnostics:fixes:expansion:file:function:line:column:)-3hjp``
- ``assertMacro(_:record:of:matches:fileID:file:function:line:column:)-2wi38``
- ``assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:fileID:file:function:line:column:)-90l38``

### Deprecations

- ``assertMacro(_:applyFixIts:record:of:matches:file:function:line:column:)-4xamb``
- ``assertMacro(_:applyFixIts:record:of:matches:file:function:line:column:)-7jwrb``
- ``assertMacro(_:record:of:matches:fileID:file:function:line:column:)-6vxvm``
- ``assertMacro(_:applyFixIts:record:of:matches:fileID:file:function:line:column:)-4381w``
- ``assertMacro(_:applyFixIts:record:of:matches:fileID:file:function:line:column:)-9mzoj``
14 changes: 7 additions & 7 deletions Sources/MacroTesting/Documentation.docc/MacroTesting.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ running the test again will produce a nicely formatted message:

You can even have the library automatically re-record the macro expansion directly into your test
file by providing the `record` argument to
``assertMacro(_:record:of:diagnostics:fixes:expansion:file:function:line:column:)-6hxgm``
``assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:fileID:file:function:line:column:)-8zqk4``
```swift
assertMacro(["stringify": StringifyMacro.self], record: true) {
assertMacro(["stringify": StringifyMacro.self], record: .all) {
"""
#stringify(a + b)
"""
Expand Down Expand Up @@ -103,14 +103,14 @@ class StringifyMacroTests: XCTestCase {
}
```

You can pass the `isRecording` parameter to
``withMacroTesting(isRecording:macros:operation:)-2vypn`` to re-record every assertion in the test
You can pass the `record` parameter to
``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s`` to re-record every assertion in the test
case (or suite, if you're using your own custom base test case class):

```swift
override func invokeTest() {
withMacroTesting(
isRecording: true
record: .all
) {
super.invokeTest()
}
Expand Down Expand Up @@ -169,5 +169,5 @@ func testNonAsyncFunctionDiagnostic() {

### Essentials

- ``assertMacro(_:record:of:diagnostics:fixes:expansion:file:function:line:column:)-6hxgm``
- ``withMacroTesting(isRecording:macros:operation:)-2vypn``
- ``assertMacro(_:indentationWidth:record:of:diagnostics:fixes:expansion:fileID:file:function:line:column:)-8zqk4``
- ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s``
15 changes: 11 additions & 4 deletions Sources/MacroTesting/Documentation.docc/WithMacroTesting.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# ``MacroTesting/withMacroTesting(isRecording:macros:operation:)-2vypn``
# ``MacroTesting/withMacroTesting(indentationWidth:record:macros:operation:)-6ayf5``

## Topics

### Overloads

- ``withMacroTesting(isRecording:macros:operation:)-6bf9b``
- ``withMacroTesting(isRecording:macros:operation:)-7jgpz``
- ``withMacroTesting(isRecording:macros:operation:)-7fx9t``
- ``withMacroTesting(indentationWidth:record:macros:operation:)-7cm1s``
- ``withMacroTesting(indentationWidth:record:macros:operation:)-5a7qi``
- ``withMacroTesting(indentationWidth:record:macros:operation:)-9ghea``

### Deprecations

- ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-1yql2``
- ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-9du8s``
- ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-91prk``
- ``withMacroTesting(indentationWidth:isRecording:macros:operation:)-5id9j``
11 changes: 7 additions & 4 deletions Sources/MacroTesting/MacrosTestTrait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import SwiftSyntaxMacros
import Testing

@_spi(Experimental)
extension Trait where Self == _MacrosTestTrait {
/// Configure snapshot testing in a suite or test.
///
/// - Parameters:
/// - record: The record mode of the test.
/// - diffTool: The diff tool to use in failure messages.
/// - indentationWidth: The `Trivia` for setting indentation during macro expansion (e.g., `.spaces(2)`).
/// Defaults to the original source's indentation if unspecified.
/// - record: The recording strategy to use for macro expansions. This can be set to `.all`, `.missing`,
/// `.never`, or `.failed`. If not provided, it uses the current configuration, which can also be set via
/// the `SNAPSHOT_TESTING_RECORD` environment variable.
/// - macros: A dictionary mapping macro names to their implementations. This specifies which macros
/// should be expanded during testing.
public static func macros(
indentationWidth: Trivia? = nil,
record: SnapshotTestingConfiguration.Record? = nil,
Expand All @@ -27,7 +31,6 @@
}

/// A type representing the configuration of snapshot testing.
@_spi(Experimental)
public struct _MacrosTestTrait: SuiteTrait, TestTrait {
public let isRecursive = true
let configuration: MacroTestingConfiguration
Expand Down
4 changes: 2 additions & 2 deletions Tests/MacroTestingTests/SwiftTestingTests.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#if canImport(Testing)
@_spi(Experimental) import MacroTesting
import MacroTesting
import Testing

@Suite(
.macros(
//record: .failed,
// record: .failed,
macros: ["URL": URLMacro.self]
)
)
Expand Down

0 comments on commit 10e7b89

Please sign in to comment.