In this project, each file has an implementation and a corresponding test. It looks like keeping unit tests in the Tests directory may be the recommended approach, but I prefer to keep them in Sources/ because I view unit tests as an extension of the documentation and there's also more visibility with respect to the implementation.
So, Sources/foo/add.swift looks like:
import Testing
class Addition {
func add(_ num1: Int, _ num2: Int) -> Int {
return num1 + num2
}
}
struct AdditionTests {
@Test func testAdd() {
let calc = Addition()
let result = calc.add(2, 3)
let expected = 5
#expect(result == expected)
}
}
and Sources/bar/subtract.swift is similar.
( I'm going to be adding more directories in Sources/, each of which will contain a .swift files )
I'm looking to call all unit tests in Sources/main.swift and plan on running something like swift run Sources/main.swift (or swift test Sources/main.swift, or something similar) from the project root.
How would packages.swift and Sources/main.swift look like if want to run all unit tests in Sources ?
Swift Package Manager expects tests to be located in the Tests directory by default. You cannot currently intermingle test code with production code, so you cannot e.g. place AdditionTests in the same file as Addition.
We refer to this concept as "co-located tests" and it's something we'd love to do in the future, but it is not currently supported. @smontgomery do you have a GitHub issue or radar number handy?
Its a toy project - it just has unit tests (no integration tests, UI tests, etc.). If there's any way to do this, possibly without Swift package Manager that'll be ideal..
To provide a bit more context, it's not that you can't, strictly speaking, place test code in the same files or the same module as your "regular" (i.e. production) code. If you try this, you may find that you can get your project to build successfully. But doing so has some practical downsides that aren't ideal for most projects. It means:
Your product (non-test) targets will link the testing library, which means if you attempt to distribute your built product it will require the testing library at runtime.
Your test code will be part of regular builds of your product code—that is, unless you take special steps on your own to omit them, such as surrounding them with #if DEBUG or similar. (Of course, doing that then typically prohibits testing release builds [those with optimizations enabled], so it's an imperfect workaround.) Including test code in distribution builds has multiple downsides, including that it wastes space and could reveal inner-workings you don't want exposed to clients.
If your tests require any associated resource files, those also need to be somehow dealt with/omitted from distribution builds too. (With SwiftPM this may be easier, this is more of a challenge with Xcode projects.)
So while you can technically get this to work, co-locating test code with your product code is not something we generally recommend right now. But we do want to support this eventually, and improve the various tools and libraries involved to work in together and eliminate/mitigate the downsides I mentioned above.
For now, my recommendation is that if you choose to use Swift Package Manager, it's easiest to follow its expected convention and place your tests in distinct files within the top-level Tests/ directory. That will have the lowest maintenance cost and follow the general community pattern. However, if you have a strong preference to place your tests near their associated product code, then I'd recommend @maartene's suggestion to place them in separate files within Sources/ but still in a distinct test target. Just know that if you go that route, you'll have to configure your product targets to exclude those files at that location and configure your test targets to include them at that location.
I'm just trying to do something like swift test to see whether all tests have passed or not, nothing more.
I'm not going to distribute this project, there are no associated resources, or anything remotely complex. Its a bare-bones project - simply a bigger extension of the directory layout I gave.
The word "target" in that quote is referring to targets defined in your Swift package manifest: for example .target(...) or .testTarget(...). To use the technique discussed above, if you want to place source files in a nonstandard location, you need to pass one of the relevant parameters to those functions in your package manifest to instruct SwiftPM where to locate the files. The documentation for how to do this for .target(...) is here.