Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take into account TaskDefs with TestSelectors #108

Merged
merged 2 commits into from
Dec 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ target
/\.manager/
/\.idea/
/\.idea_modules/
.metals/
.bloop/
.bsp/
.vscode/
37 changes: 31 additions & 6 deletions src/main/java/com/novocode/junit/JUnitRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.junit.runner.notification.RunListener;
import sbt.testing.Runner;
import sbt.testing.Task;
import sbt.testing.Selector;
import sbt.testing.TestSelector;
import sbt.testing.TaskDef;

import java.util.*;
Expand Down Expand Up @@ -77,15 +79,38 @@ else if(s.startsWith("-D") && s.contains("=")) {
@Override
public Task[] tasks(TaskDef[] taskDefs) {
used = true;
int length = taskDefs.length;
Task[] tasks = new Task[length];
for (int i = 0; i < length; i++) {
TaskDef taskDef = taskDefs[i];
tasks[i] = new JUnitTask(this, settings, taskDef);
}
Task[] tasks = Arrays
.stream(taskDefs)
.map(taskDef -> {
RunSettings alteredSettings = alterRunSettings(this.settings, taskDef.selectors());
return new JUnitTask(this, alteredSettings, taskDef);
})
.toArray(Task[]::new);
return tasks;
}

/**
* 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) {
boolean onlyTestSelectors = Arrays.stream(selectors).allMatch(selector -> selector instanceof TestSelector);
if (onlyTestSelectors) {
String testFilter = Arrays
.stream(selectors)
.map(selector -> ((TestSelector) selector).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;
}

private RunListener createRunListener(String runListenerClassName) {
if(runListenerClassName != null) {
try {
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/com/novocode/junit/RunSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ class RunSettings {
this.testFilter = testFilter;
}

public RunSettings withTestFilter(String newTestFilter) {
String ignoreRunners = String.join(",", this.ignoreRunners);
return new RunSettings(
this.color, this.decodeScalaNames, this.quiet, this.verbosity, this.summary, this.logAssert,
ignoreRunners, this.logExceptionClass, this.sysprops, this.globPatterns, this.includeCategories,
this.excludeCategories, newTestFilter
);
}

String decodeName(String name) {
return decodeScalaNames ? decodeScalaName(name) : name;
}
Expand Down Expand Up @@ -108,7 +117,7 @@ String buildErrorMessage(Throwable t) {

private String buildColoredName(Description desc, String c1, String c2, String c3) {
StringBuilder b = new StringBuilder();

String cn = decodeName(desc.getClassName());
int pos1 = cn.indexOf('$');
int pos2 = pos1 == -1 ? cn.lastIndexOf('.') : cn.lastIndexOf('.', pos1);
Expand Down
6 changes: 6 additions & 0 deletions src/sbt-test/simple/check-test-selector/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name := "test-project"

scalaVersion := "2.13.7"

libraryDependencies += "com.github.sbt" % "junit-interface" % sys.props("plugin.version") % "test"
libraryDependencies += "org.scala-sbt" % "test-agent" % "1.5.5" % Test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.6.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import com.novocode.junit.JUnitFramework
import com.novocode.junit.JUnitFingerprint

import org.junit.Test
import org.junit.Assert._

import sbt.testing._
import scala.collection.mutable.ArrayBuffer

/**
* Check if TestSelector's are correctly handled by JUnitRunner.
* Execute prepared TaskDef's using manually created instances of sbt.testing.{Framework and Runner}.
*/
class CheckTestSelector {
val framework = new JUnitFramework();
val runner = framework.runner(
Array.empty[String],
Array.empty[String],
this.getClass().getClassLoader()
);

private def getEventHandler(): (ArrayBuffer[String], EventHandler) = {
val executedItems = new scala.collection.mutable.ArrayBuffer[String]
val eventHandler = new EventHandler {
override def handle(event: Event) =
if (event.status() == Status.Success) {
executedItems.addOne(event.fullyQualifiedName())
}
}
(executedItems, eventHandler)
}

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

@Test
def runAllViaSuiteSelector() {
val selectors = Array[Selector](
new SuiteSelector
)
val taskDefs = Array(
new TaskDef("a.b.MyTestSuite", new JUnitFingerprint(), false, selectors)
)

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

val (executedItems, eventHandler) = getEventHandler()

task.execute(eventHandler, Nil.toArray)
assertArrayEquals(
Array[Object]("a.b.MyTestSuite.testBar", "a.b.MyTestSuite.testFoo"),
executedItems.toArray[Object]
)
}

@Test
def 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)
assertArrayEquals(
Array[Object]("a.b.MyTestSuite.testBar", "a.b.MyTestSuite.testFoo"),
executedItems.toArray[Object]
)
}

@Test
def 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)
assertArrayEquals(
Array[Object]("a.b.MyTestSuite.testFoo"),
executedItems.toArray[Object]
)

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package a.b

import org.junit.Test
import org.junit.Assert.assertEquals

class MyTestSuite {

@Test
def testFoo(): Unit = {
assertEquals("Test should pass", true, true)
}

@Test
def testBar(): Unit = {
assertEquals("Test should pass", true, true)
}
}
2 changes: 2 additions & 0 deletions src/sbt-test/simple/check-test-selector/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# make sure the unit test passes
> test