Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve MacroTesting Documentation and Add Swift Testing Integration #35

Merged
merged 2 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading