From 68269b893d2afe4759d7b8a984342adfc8e9a1c3 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 5 Nov 2024 09:43:26 +0100 Subject: [PATCH] Filter out anonymous classes during test discovery (#3911) Mitigates https://github.com/com-lihaoyi/mill/issues/3910 by hackily filtering out all anonymous classes, but non-anonymous non-test classes still cause the problem Added a unit test to check this specific misbehavior --- .../main/kotest/src/FooTest.kt | 15 +++++++++++++ .../src/mill/kotlinlib/HelloWorldTests.scala | 22 +++++++++++++++++++ .../src/mill/testrunner/TestRunnerUtils.scala | 12 +++++----- 3 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 kotlinlib/test/resources/hello-world-kotlin/main/kotest/src/FooTest.kt diff --git a/kotlinlib/test/resources/hello-world-kotlin/main/kotest/src/FooTest.kt b/kotlinlib/test/resources/hello-world-kotlin/main/kotest/src/FooTest.kt new file mode 100644 index 00000000000..e72b2d53778 --- /dev/null +++ b/kotlinlib/test/resources/hello-world-kotlin/main/kotest/src/FooTest.kt @@ -0,0 +1,15 @@ +package hello.tests + +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.shouldBe +import hello.getHelloString + +class FooTest : FunSpec({ + test("testFailure") { + getHelloString() shouldBe "Hello, world!" + } + + test("testSuccess") { + getHelloString() shouldBe "WRONG!" + } +}) diff --git a/kotlinlib/test/src/mill/kotlinlib/HelloWorldTests.scala b/kotlinlib/test/src/mill/kotlinlib/HelloWorldTests.scala index 70fdba70341..01989080553 100644 --- a/kotlinlib/test/src/mill/kotlinlib/HelloWorldTests.scala +++ b/kotlinlib/test/src/mill/kotlinlib/HelloWorldTests.scala @@ -24,6 +24,11 @@ object HelloWorldTests extends TestSuite { ivy"org.jetbrains.kotlin:kotlin-test-junit:${this.kotlinVersion()}" ) } + object kotest extends KotlinTests with TestModule.Junit5 { + override def ivyDeps = super.ivyDeps() ++ Agg( + ivy"io.kotest:kotest-runner-junit5-jvm:5.9.1" + ) + } } object main extends Cross[MainCross](kotlinVersions) } @@ -68,6 +73,23 @@ object HelloWorldTests extends TestSuite { ) }) } + test("kotest") { + val eval = testEval() + + HelloWorldKotlin.main.crossModules.foreach(m => { + val Right(discovered) = eval.apply(m.kotest.discoveredTestClasses) + assert(discovered.value == Seq("hello.tests.FooTest")) + + val Left(Result.Failure(_, Some(v1))) = eval.apply(m.kotest.test()) + + assert( + v1._2(0).fullyQualifiedName == "hello.tests.FooTest", + v1._2(0).status == "Success", + v1._2(1).fullyQualifiedName == "hello.tests.FooTest", + v1._2(1).status == "Failure" + ) + }) + } test("failures") { val eval = testEval() diff --git a/testrunner/src/mill/testrunner/TestRunnerUtils.scala b/testrunner/src/mill/testrunner/TestRunnerUtils.scala index 954bbbe43fa..563b1e480c3 100644 --- a/testrunner/src/mill/testrunner/TestRunnerUtils.scala +++ b/testrunner/src/mill/testrunner/TestRunnerUtils.scala @@ -70,6 +70,12 @@ import scala.jdk.CollectionConverters.IteratorHasAsScala .flatten ) } + // I think this is a bug in sbt-junit-interface. AFAICT, JUnit is not + // meant to pick up non-static inner classes as test suites, and doing + // so makes the jimfs test suite fail + // + // https://stackoverflow.com/a/17468590 + .filter { case (c, f) => !c.isMemberClass && !c.isAnonymousClass } testClasses } @@ -109,12 +115,6 @@ import scala.jdk.CollectionConverters.IteratorHasAsScala val runner = framework.runner(args.toArray, Array[String](), cl) val testClasses = discoverTests(cl, framework, testClassfilePath) - // I think this is a bug in sbt-junit-interface. AFAICT, JUnit is not - // meant to pick up non-static inner classes as test suites, and doing - // so makes the jimfs test suite fail - // - // https://stackoverflow.com/a/17468590 - .filter { case (c, f) => !c.isMemberClass } val tasks = runner.tasks( for ((cls, fingerprint) <- testClasses.iterator.toArray if classFilter(cls))