Skip to content

Add CuckooPluginModular for per-module mock generation#595

Merged
MatyasKriz merged 4 commits into
Brightify:masterfrom
SylvainRX:feature/per-module-plugin
Jun 3, 2026
Merged

Add CuckooPluginModular for per-module mock generation#595
MatyasKriz merged 4 commits into
Brightify:masterfrom
SylvainRX:feature/per-module-plugin

Conversation

@SylvainRX

@SylvainRX SylvainRX commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new CuckooPluginModular build tool plugin that generates separate mock files per module dependency, improving modularity for multi-target Swift Packages.

Related issue: #555

Motivation

The existing CuckooPluginSingleFile generates all mocks into a single GeneratedMocks.swift file in derived data. In a Swift Package with multiple targets, each test target compiles independently and may not have visibility into types from unrelated modules, making a single shared mock file problematic.

Changes

New Plugin: CuckooPluginModular

  • Located in Generator/Plugin/Modular/
  • Inspects the test target's dependencies (excluding Cuckoo) and runs the generator once per dependency module
  • Each module gets its own build command with CUCKOO_MODULE_NAME environment variable
  • Generates one mock file per module: GeneratedMocks_<ModuleName>.swift
  • Also emits a build command keyed by the test target's own name, aggregating all dependency sources — this allows Cuckoofile.toml to have a [modules.<TestTargetName>] entry to control which files are mocked and which imports are added
  • A Cuckoofile.toml entry is required for each module; modules without a matching entry produce an empty file

Usage

Package.swift:

.testTarget(
    name: "TargetATests",
    dependencies: ["TargetA", "Cuckoo"],
    plugins: [
        .plugin(name: "CuckooPluginModular", package: "Cuckoo"),
    ]
),
.testTarget(
    name: "AggregationTargetTests",
    dependencies: ["AggregationTarget", "Cuckoo"],
    plugins: [
        .plugin(name: "CuckooPluginModular", package: "Cuckoo"),
    ]
)

Cuckoofile.toml:

# TargetA mocks
[modules.TargetATests]
imports = ["Foundation"]
testableImports = ["TargetA"]
sources = [
    "Sources/TargetA/InternalProtocolA.swift"
]

# AggregationTarget mocks - multiple imports
[modules.AggregationTargetTests]
imports = ["Foundation", "TargetA", "TargetB"]
sources = [
    "Sources/TargetA/ProtocolA.swift",
    "Sources/TargetB/ProtocolB.swift",
]

Breaking Changes

None. All changes are backward compatible with existing plugins and configurations.

Comment thread Generator/Sources/CLI/GenerateCommand.swift Outdated
Comment thread Package.swift Outdated
Comment thread Generator/Sources/CLI/GenerateCommand.swift

@MatyasKriz MatyasKriz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I appreciate you taking the time to improve the project like this. Especially the automatic source detection might be nice for small projects.

One more thing, though – please mention this new modular build tool in README, so that users don't miss it. 🙂

@SylvainRX

Copy link
Copy Markdown
Contributor Author

@MatyasKriz Thank you for the review and feedbacks! I'll address them as soon as I have some time.

@SylvainRX SylvainRX force-pushed the feature/per-module-plugin branch from f517ecb to e63d7f8 Compare April 3, 2026 19:37

@SylvainRX SylvainRX left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @MatyasKriz !
I pushed changes addressing your comments, and updated the readme as well.
Please let me know if there's thing I can keep improving on.
Thanks!

Comment thread Package.swift Outdated
Comment thread Generator/Sources/CLI/GenerateCommand.swift Outdated
Comment thread Generator/Sources/CLI/GenerateCommand.swift
@SylvainRX SylvainRX requested a review from MatyasKriz April 7, 2026 14:14
@SylvainRX SylvainRX changed the title Add CuckooPluginPerModule for per-module mock generation Add CuckooPluginModular for per-module mock generation Apr 30, 2026

@MatyasKriz MatyasKriz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay, looks good! The documentation is a nice touch as well. 👏

SylvainRX added 4 commits June 3, 2026 12:13
- Create new CuckooPluginPerModule plugin that generates separate mock files per module dependency
- Add content-equality guards in GenerateCommand to prevent unnecessary file rewrites
- Skip writing output files when content unchanged

This allows test targets to depend only on specific module mocks rather than all mocks in a single file, while maintaining the original plugin for existing users.
Enables test targets to override shared module mock generation by introducing CUCKOO_COMPOUND_MODULE_NAME (TARGET/MODULE format).

- Plugin:
  - Pass CUCKOO_COMPOUND_MODULE_NAME env var for each dependency
  - Generate build command for test target itself (not just deps)
- Generator:
  - Prioritize compound module key over plain module name
  - Support suppressor pattern (empty sources = empty output)

This allows Cuckoofile.toml to specify different mock sources for the
same module when used in different test targets, fixing issues where
shared dependencies generate unwanted mocks.
Rename CuckooPluginPerModule plugin to CuckooPluginModular
Refactor module filtering
Revert the write logic for mock generation (get rid of the large string comparison)
I deemed the compound module concept as useless for now.
If we want to import protocol with an identical name from different targets, we should work on prefixing them with their target name in the generated mocks.
@MatyasKriz MatyasKriz force-pushed the feature/per-module-plugin branch from e63d7f8 to e678ce2 Compare June 3, 2026 10:13
@MatyasKriz MatyasKriz merged commit 0358f9d into Brightify:master Jun 3, 2026
3 checks passed
@SylvainRX

Copy link
Copy Markdown
Contributor Author

Thank you @MatyasKriz !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants