Skip to content

Commit

Permalink
feat: take TestSelector into account (#501)
Browse files Browse the repository at this point in the history
More information can be found at sbt/junit-interface#108
  • Loading branch information
kpodsiad authored Mar 21, 2022
1 parent aa30ff9 commit 4fae043
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@

import sbt.testing.Runner;
import sbt.testing.Task;
import sbt.testing.Selector;
import sbt.testing.TestSelector;
import sbt.testing.TaskDef;

import java.util.stream.Collectors;
import java.util.stream.Stream;

final class JUnitRunner implements Runner {
private final String[] args;
private final String[] remoteArgs;
Expand Down Expand Up @@ -127,7 +132,8 @@ public Task[] tasks(TaskDef[] taskDefs) {
for (int i = 0; i < length; i++) {
TaskDef taskDef = taskDefs[i];
if (shouldRun(computer, taskDef)) {
tasks.add(new JUnitTask(this, settings, taskDef, computer));
RunSettings alteredSettings = alterRunSettings(this.settings, taskDef.selectors());
tasks.add(new JUnitTask(this, alteredSettings, taskDef, computer));
}
}
return tasks.toArray(new Task[0]);
Expand All @@ -153,6 +159,35 @@ private RunListener createRunListener(String runListenerClassName) {
} else return null;
}

/**
* Alter default RunSettings depending on the passed selectors. If selectors contains only
* elements of type TestSelector, then default settings are altered to include only test names
* from these selectors. This allows to run particular test cases within given test class.
* testFilter is treated as a regular expression, hence joining is done via '|'.
*/
private RunSettings alterRunSettings(RunSettings defaultSettings, Selector[] selectors) {
List<TestSelector> testSelectors =
Arrays.stream(selectors)
.flatMap(
selector -> {
return selector instanceof TestSelector
? Stream.of((TestSelector) selector)
: Stream.empty();
})
.collect(Collectors.toList());
if (testSelectors.size() == selectors.length) {
String testFilter =
testSelectors.stream().map(TestSelector::testName).collect(Collectors.joining("|"));
// if already provided testFilter is not empty add to it | (regex or operator)
String currentFilter =
defaultSettings.testFilter.length() > 0 ? defaultSettings.testFilter + "|" : "";
String newFilter = currentFilter + testFilter;
return defaultSettings.withTestFilter(newFilter);
}

return defaultSettings;
}

@Override
public String done() {
// Can't simply return the summary due to https://github.com/sbt/sbt/issues/3510
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,28 @@ class RunSettings implements Settings {
this.trimStackTraces = trimStackTraces;
}

public RunSettings withTestFilter(String newTestFilter) {
String ignoreRunners = String.join(",", this.ignoreRunners);
return new RunSettings(
this.color,
this.decodeScalaNames,
this.verbose,
this.useSbtLoggers,
this.useBufferedLoggers,
this.trimStackTraces,
this.summary,
this.logAssert,
ignoreRunners,
this.logExceptionClass,
this.sysprops,
this.globPatterns,
this.includeCategories,
this.excludeCategories,
this.includeTags,
this.excludeTags,
newTestFilter);
}

String decodeName(String name) {
return decodeScalaNames ? decodeScalaName(name) : name;
}
Expand Down
122 changes: 122 additions & 0 deletions tests/jvm/src/test/scala/munit/TestSelectorSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package munit

import sbt.testing.Event
import sbt.testing.EventHandler
import sbt.testing.Selector
import sbt.testing.Status
import sbt.testing.SuiteSelector
import sbt.testing.TaskDef
import sbt.testing.TestSelector
import scala.collection.mutable
import sbt.testing.Runner

/**
* Dummy test suite which is needed by TestSelectorSuite
*/
class MyTestSuite extends FunSuite {

test("testFoo") {
assert(true, "Test should pass")
}

test("testBar") {
assert(true, "Test should pass")
}
}

/**
* Check if TestSelector's are correctly handled by Munit.
* Execute prepared TaskDef's using manually created instances of sbt.testing.{Framework and Runner}.
*/
class TestSelectorSuite extends FunSuite {
val framework = new Framework();
val runner: Runner = framework.runner(
Array.empty,
Array.empty,
this.getClass().getClassLoader()
);

val fingerprint = framework.munitFingerprint

/**
* Reference to the collection which will contain fully qualified names of executed tests.
* Only after finished execution it's safe to convert this mutable collection to immutable one.
*/
private def getEventHandler(): (mutable.ListBuffer[String], EventHandler) = {
val executedItems = new mutable.ListBuffer[String]
val eventHandler = new EventHandler {
override def handle(event: Event) =
if (event.status() == Status.Success) {
executedItems += event.fullyQualifiedName()
}
}
(executedItems, eventHandler)
}

private def getTaskDefs(selectors: Array[Selector]): Array[TaskDef] = {
Array(
new TaskDef("munit.MyTestSuite", fingerprint, false, selectors)
)
}

test("runAllViaSuiteSelector") {
val selectors = Array[Selector](
new SuiteSelector
)
val taskDefs = Array(
new TaskDef("munit.MyTestSuite", fingerprint, false, selectors)
)

val tasks = runner.tasks(taskDefs)
assertEquals(tasks.size, 1)
val task = tasks(0)

val (executedItems, eventHandler) = getEventHandler()

task.execute(eventHandler, Nil.toArray)
assertEquals(
executedItems.toSet,
Set("munit.MyTestSuite.testBar", "munit.MyTestSuite.testFoo")
)
}

test("runAllViaTestSelectors") {
val selectors = Array[Selector](
new TestSelector("testFoo"),
new TestSelector("testBar")
)
val taskDefs = getTaskDefs(selectors)

val tasks = runner.tasks(taskDefs)
assertEquals(tasks.size, 1)
val task = tasks(0)

val (executedItems, eventHandler) = getEventHandler()

task.execute(eventHandler, Nil.toArray)
assertEquals(
executedItems.toSet,
Set("munit.MyTestSuite.testBar", "munit.MyTestSuite.testFoo")
)
}

test("runOnlyOne") {
val selectors = Array[Selector](
new TestSelector("testFoo")
)
val taskDefs = getTaskDefs(selectors)

val tasks = runner.tasks(taskDefs)
assertEquals(tasks.size, 1)
val task = tasks(0)

val (executedItems, eventHandler) = getEventHandler()

task.execute(eventHandler, Nil.toArray)
assertEquals(
executedItems.toSet,
Set("munit.MyTestSuite.testFoo")
)

}
}

0 comments on commit 4fae043

Please sign in to comment.