diff --git a/doc/rules.md b/doc/rules.md index ec9e4d091..5745ba4de 100644 --- a/doc/rules.md +++ b/doc/rules.md @@ -726,10 +726,20 @@ root of your workspace (i.e. `$(SRCROOT)`). ### Test Filtering -A subset of tests for a given target can be executed via the `--test_filter` parameter: +`swift_test` supports Bazel's `--test_filter` flag on all platforms (i.e., Apple +and Linux), which can be used to run only a subset of tests. The expected filter +format is the same as Xcode's `xctest` tool: -``` -bazel test //:Tests --test_filter=TestModuleName.TestClassName/testMethodName +* `ModuleName`: Run only the test classes/methods in module `ModuleName`. +* `ModuleName.ClassName`: Run only the test methods in class + `ModuleName.ClassName`. +* `ModuleName.ClassName/testMethodName`: Run only the method `testMethodName` + in class `ModuleName.ClassName`. + +Multiple such filters can be separated by commas. For example: + +```shell +bazel test --test_filter=AModule,BModule.SomeTests,BModule.OtherTests/testX //my/package/... ``` **ATTRIBUTES** diff --git a/examples/apple/test_filter/BUILD b/examples/xplatform/test_filter/BUILD similarity index 76% rename from examples/apple/test_filter/BUILD rename to examples/xplatform/test_filter/BUILD index 9d122bd9f..c251aa05a 100644 --- a/examples/apple/test_filter/BUILD +++ b/examples/xplatform/test_filter/BUILD @@ -11,7 +11,6 @@ swift_library( "TestHelper.swift", ], module_name = "test_filter", - target_compatible_with = ["@platforms//os:macos"], ) # Verify that tests fail as expected without test filtering. @@ -20,8 +19,7 @@ swift_test( env = { "EXPECT_FAILURE": "TRUE", }, - module_name = "test_filter", - target_compatible_with = ["@platforms//os:macos"], + module_name = "test_filter__baseline", deps = [":test_filter_lib"], ) @@ -31,8 +29,7 @@ swift_test( env = { "TESTBRIDGE_TEST_ONLY": "test_filter.PassTests", }, - module_name = "test_filter", - target_compatible_with = ["@platforms//os:macos"], + module_name = "test_filter__feature__target_class", deps = [":test_filter_lib"], ) @@ -42,7 +39,6 @@ swift_test( env = { "TESTBRIDGE_TEST_ONLY": "test_filter.PassFailTests/test_pass", }, - module_name = "test_filter", - target_compatible_with = ["@platforms//os:macos"], + module_name = "test_filter__feature__target_class_method", deps = [":test_filter_lib"], ) diff --git a/examples/apple/test_filter/FailTests.swift b/examples/xplatform/test_filter/FailTests.swift similarity index 100% rename from examples/apple/test_filter/FailTests.swift rename to examples/xplatform/test_filter/FailTests.swift diff --git a/examples/apple/test_filter/PassFailTests.swift b/examples/xplatform/test_filter/PassFailTests.swift similarity index 100% rename from examples/apple/test_filter/PassFailTests.swift rename to examples/xplatform/test_filter/PassFailTests.swift diff --git a/examples/apple/test_filter/PassTests.swift b/examples/xplatform/test_filter/PassTests.swift similarity index 100% rename from examples/apple/test_filter/PassTests.swift rename to examples/xplatform/test_filter/PassTests.swift diff --git a/examples/apple/test_filter/TestHelper.swift b/examples/xplatform/test_filter/TestHelper.swift similarity index 100% rename from examples/apple/test_filter/TestHelper.swift rename to examples/xplatform/test_filter/TestHelper.swift diff --git a/swift/swift_test.bzl b/swift/swift_test.bzl index ede3a350b..e97b49d29 100644 --- a/swift/swift_test.bzl +++ b/swift/swift_test.bzl @@ -709,10 +709,20 @@ root of your workspace (i.e. `$(SRCROOT)`). ### Test Filtering -A subset of tests for a given target can be executed via the `--test_filter` parameter: +`swift_test` supports Bazel's `--test_filter` flag on all platforms (i.e., Apple +and Linux), which can be used to run only a subset of tests. The expected filter +format is the same as Xcode's `xctest` tool: -``` -bazel test //:Tests --test_filter=TestModuleName.TestClassName/testMethodName +* `ModuleName`: Run only the test classes/methods in module `ModuleName`. +* `ModuleName.ClassName`: Run only the test methods in class + `ModuleName.ClassName`. +* `ModuleName.ClassName/testMethodName`: Run only the method `testMethodName` + in class `ModuleName.ClassName`. + +Multiple such filters can be separated by commas. For example: + +```shell +bazel test --test_filter=AModule,BModule.SomeTests,BModule.OtherTests/testX //my/package/... ``` """, executable = True, diff --git a/tools/test_discoverer/TestPrinter.swift b/tools/test_discoverer/TestPrinter.swift index 4b9fc3e79..d9653489d 100644 --- a/tools/test_discoverer/TestPrinter.swift +++ b/tools/test_discoverer/TestPrinter.swift @@ -144,6 +144,7 @@ struct TestPrinter { var contents = """ import BazelTestObservation + import Foundation import XCTest @main @@ -162,11 +163,26 @@ struct TestPrinter { """ } + // Bazel's `--test_filter` flag is passed to the test binary via the `TESTBRIDGE_TEST_ONLY` + // environment variable. Below, we read that value if it is present and pass it to `XCTMain`, + // where it behaves the same as the `-XCTest` flag value in Xcode's `xctest` tool. + // + // Note that `XCTMain` treats `arguments` as an actual command line, meaning that `arguments[0]` + // is expected to be the binary's path. So we only do the test filter logic if we've already + // been passed no other arguments. This lets the test binary still support other XCTest flags + // like `--list-tests` or `--dump-tests-json` if the user wishes to use those directly. contents += """ if let xmlObserver = BazelXMLTestObserver.default { XCTestObservationCenter.shared.addTestObserver(xmlObserver) } - XCTMain(tests) + + var arguments = CommandLine.arguments + if arguments.count == 1, + let testFilter = ProcessInfo.processInfo.environment["TESTBRIDGE_TEST_ONLY"] + { + arguments.append(testFilter) + } + XCTMain(tests, arguments: arguments) } } diff --git a/tools/xctest_runner/xctest_runner.sh.template b/tools/xctest_runner/xctest_runner.sh.template index 746c2d0f6..a198ae982 100644 --- a/tools/xctest_runner/xctest_runner.sh.template +++ b/tools/xctest_runner/xctest_runner.sh.template @@ -17,7 +17,7 @@ set -euo pipefail # This test script is used as the executable output of a `swift_test` rule when -# building macOS targets (unless the "swift.bundled_tests" feature is disabled) +# building macOS targets (unless the target has `discover_tests = False`) # because the test binary is an `MH_BUNDLE` that needs to be loaded dynamically # and runtime reflection is used to locate the test methods.