{"id":18818058,"url":"https://github.com/pointfreeco/swift-macro-testing","last_synced_at":"2025-05-16T01:07:28.403Z","repository":{"id":195403039,"uuid":"677781848","full_name":"pointfreeco/swift-macro-testing","owner":"pointfreeco","description":"Magical testing tools for Swift macros.","archived":false,"fork":false,"pushed_at":"2025-04-17T18:37:32.000Z","size":111,"stargazers_count":298,"open_issues_count":6,"forks_count":30,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-05-15T18:53:54.307Z","etag":null,"topics":["macros","snapshot-testing","testing"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pointfreeco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-12T16:07:52.000Z","updated_at":"2025-05-14T09:02:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"2cdd5e9b-61e4-4aa4-9a8e-8458ac37683b","html_url":"https://github.com/pointfreeco/swift-macro-testing","commit_stats":null,"previous_names":["pointfreeco/swift-macro-testing"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-macro-testing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-macro-testing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-macro-testing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-macro-testing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pointfreeco","download_url":"https://codeload.github.com/pointfreeco/swift-macro-testing/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254404330,"owners_count":22065639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["macros","snapshot-testing","testing"],"created_at":"2024-11-08T00:14:44.058Z","updated_at":"2025-05-16T01:07:23.392Z","avatar_url":"https://github.com/pointfreeco.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# Macro Testing\n\n[![CI](https://github.com/pointfreeco/swift-macro-testing/workflows/CI/badge.svg)](https://github.com/pointfreeco/swift-macro-testing/actions?query=workflow%3ACI)\n[![Slack](https://img.shields.io/badge/slack-chat-informational.svg?label=Slack\u0026logo=slack)](https://www.pointfree.co/slack-invite)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-macro-testing%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/pointfreeco/swift-macro-testing)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-macro-testing%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/pointfreeco/swift-macro-testing)\n\nMagical testing tools for Swift macros.\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://pointfreeco-blog.s3.amazonaws.com/posts/0114-macro-testing/macro-testing-full-dark.gif\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://pointfreeco-blog.s3.amazonaws.com/posts/0114-macro-testing/macro-testing-full.gif\"\u003e\n  \u003cimg alt=\"An animated demonstration of macro tests being inlined.\" src=\"https://pointfreeco-blog.s3.amazonaws.com/posts/0114-macro-testing/macro-testing-full.gif\"\u003e\n\u003c/picture\u003e\n\n## Learn more\n\nThis library was designed to support libraries and episodes produced for [Point-Free][point-free], a\nvideo series exploring the Swift programming language hosted by [Brandon Williams][mbrandonw] and\n[Stephen Celis][stephencelis].\n\nYou can watch all of the episodes [here][macro-testing-episodes].\n\n\u003ca href=\"https://www.pointfree.co/collections/macros\"\u003e\n  \u003cimg alt=\"video poster image\" src=\"https://d3rccdn33rt8ze.cloudfront.net/episodes/0250.jpeg\" width=\"600\"\u003e\n\u003c/a\u003e\n\n## Motivation\n\nThis library comes with a tool for testing macros that is more powerful and ergonomic than the\ndefault tool that comes with SwiftSyntax. To use the tool, simply specify the macros that you want\nto expand as well as a string of Swift source code that makes use of the macro.\n\nFor example, to test the `#stringify` macro that comes with SPM's macro template all one needs to\ndo is write the following: \n\n```swift\nimport MacroTesting\nimport Testing\n\n@Suite(.macros([StringifyMacro.self]))\nstruct StringifyTests {\n  @Test func stringify() {\n    assertMacro {\n      \"\"\"\n      #stringify(a + b)\n      \"\"\"\n    }\n  }\n}\n```\n\nWhen you run this test the library will automatically expand the macros in the source code string\nand write the expansion into the test file:\n\n```swift\n@Suite(.macros([StringifyMacro.self]))\nstruct StringifyTests {\n  @Test func stringify() {\n    assertMacro {\n    \"\"\"\n    #stringify(a + b)\n    \"\"\"\n  } expansion: {\n    \"\"\"\n    (a + b, \"a + b\")\n    \"\"\"\n  }\n}\n```\n\nThat is all it takes.\n\nIf in the future the macro's output changes, such as adding labels to the tuple's arguments, then\nrunning the test again will produce a nicely formatted message:\n\n```diff\n❌ Actual output (+) differed from expected output (−). Difference: …\n\n- (a + b, \"a + b\")\n+ (result: a + b, code: \"a + b\")\n```\n\nYou can even have the library automatically re-record the macro expansion directly into your test\nfile by providing the `record` argument to ``Testing/Trait/macros(_:indentationWidth:record:)``:\n\n```swift\n@Suite(.macros([StringifyMacro.self], record: .all))\n```\n\nNow when you run the test again the freshest expanded macro will be written to the `expansion` \ntrailing closure.\n\nMacro Testing can also test diagnostics, such as warnings, errors, notes, and fix-its. When a macro\nexpansion emits a diagnostic, it will render inline in the test. For example, a macro that adds\ncompletion handler functions to async functions may emit an error and fix-it when it is applied to a\nnon-async function. The resulting macro test will fully capture this information, including where\nthe diagnostics are emitted, how the fix-its are applied, and how the final macro expands:\n\n```swift\nfunc testNonAsyncFunctionDiagnostic() {\n  assertMacro {\n    \"\"\"\n    @AddCompletionHandler\n    func f(a: Int, for b: String) -\u003e String {\n      return b\n    }\n    \"\"\"\n  } diagnostics: {\n    \"\"\"\n    @AddCompletionHandler\n    func f(a: Int, for b: String) -\u003e String {\n    ┬───\n    ╰─ 🛑 can only add a completion-handler variant to an 'async' function\n       ✏️ add 'async'\n      return b\n    }\n    \"\"\"\n  } fixes: {\n    \"\"\"\n    @AddCompletionHandler\n    func f(a: Int, for b: String) async -\u003e String {\n      return b\n    }\n    \"\"\"\n  } expansion: {\n    \"\"\"\n    func f(a: Int, for b: String) async -\u003e String {\n      return b\n    }\n\n    func f(a: Int, for b: String, completionHandler: @escaping (String) -\u003e Void) {\n      Task {\n        completionHandler(await f(a: a, for: b, value))\n      }\n    }\n    \"\"\"\n  }\n}\n```\n\n## Integration with Swift Testing\n\nIf you are using Swift's built-in Testing framework, this library also supports it. Instead of relying solely\non XCTest, you can configure your tests using the `Trait` system provided by `swift-testing`. For example:\n\n```swift\nimport Testing\nimport MacroTesting\n\n@Suite(\n  .macros(\n    [\"stringify\": StringifyMacro.self],\n    record: .missing // Record only missing snapshots\n  )\n)\nstruct StringifyMacroSwiftTestingTests {\n  @Test\n  func testStringify() {\n    assertMacro {\n      \"\"\"\n      #stringify(a + b)\n      \"\"\"\n    } expansion: {\n      \"\"\"\n      (a + b, \"a + b\")\n      \"\"\"\n    }\n  }\n}\n```\n\nAdditionally, the `record` parameter in `macros` can be used to control the recording behavior for all\ntests in the suite. This value can also be configured using the `SNAPSHOT_TESTING_RECORD` environment\nvariable to dynamically adjust recording behavior based on your CI or local environment.\n\n## Documentation\n\nThe latest documentation for this library is available [here][macro-testing-docs].\n\n## License\n\nThis library is released under the MIT license. See [LICENSE](LICENSE) for details.\n\n[macro-testing-docs]: https://swiftpackageindex.com/pointfreeco/swift-macro-testing/main/documentation/macrotesting\n[macro-testing-episodes]: https://www.pointfree.co/collections/macros\n[mbrandonw]: https://github.com/mbrandonw\n[point-free]: https://www.pointfree.co\n[stephencelis]: https://github.com/stephencelis\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-macro-testing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpointfreeco%2Fswift-macro-testing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-macro-testing/lists"}