I've been slowly working on test discovery for Linux and I think the implementation is in a reasonable state now. I've tested it on some OSS Swift packages but it would be great if others can try it out and report any issues they run into. It can be enabled by passing --enable-test-discovery flag to the swift test invocation.
Would would be really useful is being able to do a diff between user defined linuxmain files and what is auto generated and in this way I have more confidence that I can just delete all the manual files.
This is really amazing Ankit, thanks a lot for publishing the toolchain too.
I just tried on some projects I have laying around and found no issues in discovering tests in any of them, it correctly discovered all of our tests
I have discovered one difference though; which we actually do not rely on, but perhaps someone could / does, so might as well mention the case right away, even if we'd e.g. ship a first version without supporting that (which would already be tremendously useful, as I don't know if people actually do this base class "trick"):
Structure:
class CommonTests: XCTestCase { func test_common() {} }
final class SpecificOneTests: CommonTests {}
On mac this discovers the SpecificOneTests.test_common as well as the one in the base class, the current --enable-test-discovery does not discover the one in the SpecificOneTests.
Having that said, I'm not sure how critical this is, since I've not seen it used, but I could be totally mistaken and people could expect it to work. Even the existing PRed discovery would already be amazing and I'd love to be able to use it in normal swift builds
Ah, yeah. This is a little complex to implement in the current approach but it should be technically possible. I don't think this is a common enough scenario though and it is easy to workaround (by just explicitly writing a new test method in the subclass and then calling the method in the super class).
I've just been trying out the new --enable-test-discovery flag on the latest Swift 5.1 docker image and found it's great for tests, so thanks for the great work
Unfortunately I've found that just running swift build still requires the LinuxMain.swift file to exist, even though it's not needed any more. I'm not sure why just doing a plain build without the tests requires the LinuxMain.swift file. Is there a reason for this and are there any plans to change it in future?
Just hit this issue when building an app inside Docker that's had the LinuxMain and all the allTests stripped out as it's no longer needed. A completely empty LinuxMain.swift fixes the issue but as mentioned it seems weird to require it for the build to pass (I'm assuming it's because the build command also attempts to build the Test target as well). It also isn't required when building on macOS. Another fix is to build it with the --enable-test-discovery flag as well.
@SDGGiesbrecht@Aciid I misdiagnosed the problem. It has nothing to do with multiple test targets. The problem occurs with extensions of a test class over multiple files:
ExampleTests.swift
import XCTest
final class ExampleTests: XCTestCase {
func testExample() {}
}
ExampleTests2.swift
extension ExampleTests {
func testExample2() {}
}
Gives
[9/12] Compiling ExamplePackageTests ExampleTests.swift
/package/.build/x86_64-unknown-linux/debug/testlist.derived/ExampleTests.swift:11:16: error: invalid redeclaration of '__allTests__ExampleTests'
static let __allTests__ExampleTests = [
^
/package/.build/x86_64-unknown-linux/debug/testlist.derived/ExampleTests.swift:5:16: note: '__allTests__ExampleTests' previously declared here
static let __allTests__ExampleTests = [
^
(And if you are looking for a workaround in the meantime, then it should be relatively trivial to temporarily change each instance of extension ExampleTests to final class ExampleTestsExtension[1, 2, 3, ...]: XCTestCase. It would at least be less work than maintaining test manifests.)
I used this trick in a project where the same tests had to run against a local network mock and against a real network. The actual tests were in the base class, and the subclasses were responsible for configuring the differing environments. In Xcode, I had the tests in the base class marked as do-not-run.
Is testing in release mode working for anyone else? I'm getting the following error:
$ swift test -c release --enable-test-discovery --enable-index-store
/src/.build/x86_64-unknown-linux/release/testlist.derived/InkTests.swift:2:18: error: module 'InkTests' was not compiled for testing
@testable import InkTests
^
This happens with my project, as well as other projects I cloned from GitHub that use swift test ‑‑enable‑test‑discovery.
Should @testable only be added to the generated test list when testing with -c debug?