fix: Pass explicitlySpecified and selectors for testOnly so @DoNotDiscover suites run (#5609)

**Problem**
When the user runs testOnly with an explicit suite name (e.g. testOnly com.example.MySuite),
ScalaTest suites annotated with @DoNotDiscover were not run because sbt always passed
explicitlySpecified=false to the test framework.

**Solution**
In Tests.processOptions, when the user has specified test filters (orderedFilters.nonEmpty),
mark the filtered tests as explicitlySpecified=true with SuiteSelector so frameworks
can run @DoNotDiscover suites when explicitly requested.

- main-actions: set explicitlySpecified and selectors in processOptions for testOnly path
- scripted test: tests/i5609-do-not-discover-testonly (testOnly com.test.TestSpec2)
This commit is contained in:
Eruis2579 2026-02-10 08:56:27 -05:00
parent 6d94d6db61
commit cfa88c3cde
6 changed files with 85 additions and 2 deletions

View File

@ -281,8 +281,23 @@ object Tests {
if (orderedFilters.isEmpty) filtered0
else orderedFilters.flatMap(f => filtered0.filter(d => f(d.name))).toList.distinct
val uniqueTests = distinctBy(tests)(_.name)
// When user ran testOnly with explicit args and the filter restricted the set, mark matching
// tests as explicitlySpecified so frameworks (e.g. ScalaTest) can run @DoNotDiscover suites.
// Do not mark when orderedFilters is "run all" (e.g. test with no args -> selectedFilter(Nil) -> match all).
val filteredToSubset = orderedFilters.nonEmpty && uniqueTests.size < discovered.size
val testsToUse =
if (!filteredToSubset) uniqueTests
else
uniqueTests.map(t =>
new TestDefinition(
t.name,
t.fingerprint,
explicitlySpecified = true,
Array(new SuiteSelector: Selector)
)
)
new ProcessedOptions(
uniqueTests.toVector,
testsToUse.toVector,
setup.toVector,
cleanup.toVector,
testListeners.toVector
@ -555,7 +570,6 @@ object Tests {
c.topLevel
case _ => false
})
// TODO: To pass in correct explicitlySpecified and selectors
val tests =
for {
(df, di) <- discovered

View File

@ -0,0 +1,9 @@
val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
ThisBuild / scalaVersion := "2.12.21"
lazy val root = (project in file("."))
.settings(
libraryDependencies += scalatest,
Test / testOptions += Tests.Argument("-C", "custom.CustomReporter")
)

View File

@ -0,0 +1,30 @@
package custom
import java.io._
import org.scalatest._
import events._
class CustomReporter extends Reporter {
private def writeFile(filePath: String, content: String): Unit = {
val file = new File(filePath)
val writer =
if (!file.exists)
new FileWriter(new File(filePath))
else
new FileWriter(new File(filePath + "-2"))
writer.write(content)
writer.flush()
writer.close()
}
def apply(event: Event): Unit = {
event match {
case SuiteStarting(_, suiteName, _, _, _, _, _, _, _, _) => writeFile("target/SuiteStarting-" + suiteName, suiteName)
case SuiteCompleted(_, suiteName, _, _, _, _, _, _, _, _, _) => writeFile("target/SuiteCompleted-" + suiteName, suiteName)
case TestStarting(_, _, _, _, testName, _, _, _, _, _, _, _) => writeFile("target/TestStarting-" + testName, testName)
case TestSucceeded(_, _, _, _, testName, _, _, _, _, _, _, _, _, _) => writeFile("target/TestSucceeded-" + testName, testName)
case _ =>
}
}
}

View File

@ -0,0 +1,12 @@
package com.test
import org.scalatest.Spec
class TestSpec extends Spec {
def `TestSpec-test-1 ` {}
def `TestSpec-test-2 ` {}
def `TestSpec-test-3 ` {}
}

View File

@ -0,0 +1,13 @@
package com.test
import org.scalatest._
@DoNotDiscover
class TestSpec2 extends Spec {
def `TestSpec2-test-1 ` {}
def `TestSpec2-test-2 ` {}
def `TestSpec2-test-3 ` {}
}

View File

@ -0,0 +1,5 @@
# #5609: When explicitly requested via testOnly, @DoNotDiscover suite should run
> clean
> testOnly com.test.TestSpec2
$ exists target/SuiteStarting-TestSpec2
$ exists target/SuiteCompleted-TestSpec2