[Question] How to allow test files inside Source folder?

When using projects started and managed by Xcode, I let the test files in the same directory as the production-code-files. For instance

Common/Components/ActionButton
├── ActionButton+FormattedTitle.swift
├── ActionButton.swift
├── ActionButtonTest.swift
├── ActionButtonTheme.swift
├── SmallTextField.swift
└── __Snapshots__
    └── ActionButtonTest
        ├── testBorderlessActionButton.1.png
        ├── testBorderlessActionButtonWithMultiColoredTitle.1.png
        ├── testCustomThemedActionButton.1.png
        ├── testGhostActionButton.1.png
        ├── testGhostActionButtonLoading.1.png
        ├── testGhostActionButtonLoading_WithBigTitle.1.png
        ├── testPrimaryActionButton.1.png
        ├── testPrimaryActionButtonLoading.1.png
        └── testPrimaryActionButtonLoading_WithBigTitle.1.png

I would like to know whether it is possible to do the same with SPM or not. I know that I could ignore files, which means I could ignore the test files on the Source folder. However, I do not know how to compile the test target with files on the Source and files that are spread across the code, like in the example above.

So, basically, how to tell the test target it will need to look up for tests on the Source folder. And, how to make the test target to compile only the test files on Source folder?

When I am using Xcode, that is quite easy. I just have to mark that file on the target I want it to be compiled into.

3 Likes

Yes, you can manually specify the paths of each file in your target/testTarget. See https://developer.apple.com/documentation/swift_packages/target/3583314-target. Notice that there is a sources parameter.

By why do you need to do this? Why not just put the test files in a separate "Tests" directory outside the "Sources" folder?

When you add your .testTarget(…) to Package.swift, you should be able to pass in a custom path or sources value. I’m not sure what wildcards if any it supports in there, but you might be able to do something like path: "./Sources/*Test.swift". Or if that doesn’t work, you might need to enumerate all the files in Sources/ and construct an array of file names to pass to sources (which should be possible with FileManager)

see also: https://developer.apple.com/documentation/swift_packages/target/3583315-testtarget

Though Apple Developer Documentation makes it sound like the default behavior should be to include Sources in test targets if I'm reading that correctly

It is not a pattern search; it expects literal paths. Pattern support would be a reasonable pitch though.

There is no reliable way to find the package directory from inside the manifest.

Even #filePath will only point to were the manifest file was when SwiftPM (or Xcode, etc.) compiled it, not to where the manifest file originated. The other source files may not even have been fetched yet either.


Some combination of path, sources, and exclude should make it possible to use nearly any layout, but those arguments are primarily designed for specifying a small number of overarching directories. The level of verbosity required for your particular layout would be cumbersome, and so I do not think any satisfying answer to your question exists.

2 Likes