@@ -136,10 +136,38 @@ public class TestToolOptions: ToolOptions {
136136 /// Generate LinuxMain entries and exit.
137137 var shouldGenerateLinuxMain = false
138138
139- var testCaseSpecifier : TestCaseSpecifier = . none
139+ var testCaseSpecifier : TestCaseSpecifier {
140+ testCaseSpecifierOverride ( ) ?? _testCaseSpecifier
141+ }
142+
143+ var _testCaseSpecifier : TestCaseSpecifier = . none
140144
141145 /// Path where the xUnit xml file should be generated.
142146 var xUnitOutput : AbsolutePath ?
147+
148+ /// Returns the test case specifier if overridden in the env.
149+ private func testCaseSpecifierOverride( ) -> TestCaseSpecifier ? {
150+ guard let override = ProcessEnv . vars [ " _SWIFTPM_SKIP_TESTS_LIST " ] else {
151+ return nil
152+ }
153+
154+ do {
155+ let skipTests : [ String . SubSequence ]
156+ // Read from the file if it exists.
157+ if let path = try ? AbsolutePath ( validating: override) , localFileSystem. exists ( path) {
158+ let contents = try localFileSystem. readFileContents ( path) . cString
159+ skipTests = contents. split ( separator: " \n " , omittingEmptySubsequences: true )
160+ } else {
161+ // Otherwise, read the env variable.
162+ skipTests = override. split ( separator: " : " , omittingEmptySubsequences: true )
163+ }
164+
165+ return . skip( skipTests. map ( String . init) )
166+ } catch {
167+ // FIXME: We should surface errors from here.
168+ }
169+ return nil
170+ }
143171}
144172
145173/// Tests filtering specifier
@@ -152,6 +180,7 @@ public enum TestCaseSpecifier {
152180 case none
153181 case specific( String )
154182 case regex( String )
183+ case skip( [ String ] )
155184}
156185
157186public enum TestMode {
@@ -234,7 +263,7 @@ public class SwiftTestTool: SwiftTool<TestToolOptions> {
234263 )
235264 ranSuccessfully = runner. test ( )
236265
237- case . regex, . specific:
266+ case . regex, . specific, . skip :
238267 // If old specifier `-s` option was used, emit deprecation notice.
239268 if case . specific = options. testCaseSpecifier {
240269 diagnostics. emit ( data: SpecifierDeprecatedDiagnostic ( ) )
@@ -419,7 +448,7 @@ public class SwiftTestTool: SwiftTool<TestToolOptions> {
419448
420449 binder. bind (
421450 option: parser. add ( option: " --specifier " , shortName: " -s " , kind: String . self) ,
422- to: { $0. testCaseSpecifier = . specific( $1) } )
451+ to: { $0. _testCaseSpecifier = . specific( $1) } )
423452
424453 binder. bind (
425454 option: parser. add ( option: " --xunit-output " , kind: PathArgument . self) ,
@@ -429,7 +458,7 @@ public class SwiftTestTool: SwiftTool<TestToolOptions> {
429458 option: parser. add ( option: " --filter " , kind: String . self,
430459 usage: " Run test cases matching regular expression, Format: <test-target>.<test-case> or " +
431460 " <test-target>.<test-case>/<test> " ) ,
432- to: { $0. testCaseSpecifier = . regex( $1) } )
461+ to: { $0. _testCaseSpecifier = . regex( $1) } )
433462
434463 binder. bind (
435464 option: parser. add ( option: " --enable-code-coverage " , kind: Bool . self,
@@ -925,6 +954,14 @@ fileprivate extension Sequence where Iterator.Element == TestSuite {
925954 } )
926955 case . specific( let name) :
927956 return allTests. filter { $0. specifier == name }
957+ case . skip( let skippedTests) :
958+ var result = allTests
959+ for skippedTest in skippedTests {
960+ result = result. filter {
961+ $0. specifier. range ( of: skippedTest, options: . regularExpression) == nil
962+ }
963+ }
964+ return result
928965 }
929966 }
930967}
0 commit comments