Thanks for your interest in improving swift-mockable! This guide covers the project layout, how to build and test, and the conventions we follow.
Sources/Mockable/— the runtime module clients depend on. It declares the@Mockablemacro and theMockableLockused by generatedSendable/actor mocks.Sources/MockableMacros/— the macro implementation (built on swift-syntax).MockableMacrois the entry point; theMockGenerator+*files generate each kind of member.Tests/MockableMacroTests/— macro-expansion tests that pin the exact generated source.Tests/MockableTests/— runtime tests that exercise the behavior of generated mocks.
swift build
swift testTests use swift-testing (@Test /
#expect), which ships with Swift 6 toolchains. On Swift 5.9 / 5.10 the package
builds but the test suite is Swift 6 only.
scripts/export-coverage.shThe script runs the test suite with coverage enabled, prints a per-file summary,
and writes coverage.lcov to the repository root. Coverage is measured over
Sources/ only — test code and dependency sources are excluded — and the paths
in the report are relative to the repository root. It works with both the macOS
and Linux toolchains, so it produces the same report locally as it does in CI.
CI runs the same script and uploads the macOS report to
Codecov, which comments on pull
requests with the resulting change. codecov.yml holds the thresholds: the
project total may drift by 1%, while new and changed lines are expected to reach
80%. Pull requests from forks skip the upload, because they cannot read the
repository's Codecov token; run the script locally to check coverage on those.
The package supports Swift 5.9, 5.10, and 6.2+ through three manifests:
Package.swift (Swift 6.2+), Package@swift-5.10.swift, and
Package@swift-5.9.swift. All three accept swift-syntax
509.0.0..<604.0.0, so dependency resolution can agree with whatever
swift-syntax major the other packages in a consuming project pin. When a new
swift-syntax major is released, bump the upper bound in all three manifests
and add the new major to the swift-syntax-compat CI matrix.
Any use of a version-sensitive swift-syntax API must go through a shim in
Sources/MockableMacros/SwiftSyntaxCompatibility.swift so it compiles against
every version in the range. swift-syntax ships empty marker modules
(SwiftSyntax600, SwiftSyntax601, ...) that #if canImport checks use to
detect the version; gate each API on the major that actually introduced it.
CI builds the package against the floor of the range and the latest patch of
every other swift-syntax major, while tests always run against the version in
Package.resolved.
Most changes should include both:
- A macro-expansion test in
Tests/MockableMacroTests/, using theassertMacroExpansionForTesting(_:expandedSource:diagnostics:macros:)helper. It wraps swift-syntax'sassertMacroExpansionand reports mismatches through swift-testing. Paste the input protocol and the exact expected expansion; if the whitespace is hard to predict, run the test once and copy the "Actual expanded source" from the failure. - A runtime test in
Tests/MockableTests/, adding the protocol toTestProtocols.swiftand asserting the generated mock behaves as expected.
Diagnostics are tested by passing a diagnostics: array to
assertMacroExpansionForTesting.
When a change affects generated output or user-facing behavior, update all of these together so they don't drift:
README.mddocs/advanced-usage.mdllms.txtandllms-full.txt- the DocC catalog under
Sources/Mockable/Mockable.docc/
- Use Conventional Commits for commit
and PR titles (
feat:,fix:,refactor:,chore:,ci:,docs:). - Keep pull requests focused and reviewable.
- Fill in the pull request template, including the testing and docs checklist.