Skip to content

Commit f8c6372

Browse files
authored
Merge pull request #108 from kpodsiad/test-selector
Take into account `TaskDef`s with `TestSelector`s
2 parents 320b678 + a13b847 commit f8c6372

File tree

8 files changed

+173
-7
lines changed

8 files changed

+173
-7
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ target
1212
/\.manager/
1313
/\.idea/
1414
/\.idea_modules/
15+
.metals/
16+
.bloop/
17+
.bsp/
18+
.vscode/

src/main/java/com/novocode/junit/JUnitRunner.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.junit.runner.notification.RunListener;
44
import sbt.testing.Runner;
55
import sbt.testing.Task;
6+
import sbt.testing.Selector;
7+
import sbt.testing.TestSelector;
68
import sbt.testing.TaskDef;
79

810
import java.util.*;
@@ -77,15 +79,38 @@ else if(s.startsWith("-D") && s.contains("=")) {
7779
@Override
7880
public Task[] tasks(TaskDef[] taskDefs) {
7981
used = true;
80-
int length = taskDefs.length;
81-
Task[] tasks = new Task[length];
82-
for (int i = 0; i < length; i++) {
83-
TaskDef taskDef = taskDefs[i];
84-
tasks[i] = new JUnitTask(this, settings, taskDef);
85-
}
82+
Task[] tasks = Arrays
83+
.stream(taskDefs)
84+
.map(taskDef -> {
85+
RunSettings alteredSettings = alterRunSettings(this.settings, taskDef.selectors());
86+
return new JUnitTask(this, alteredSettings, taskDef);
87+
})
88+
.toArray(Task[]::new);
8689
return tasks;
8790
}
8891

92+
/**
93+
* Alter default RunSettings depending on the passed selectors.
94+
* If selectors contains only elements of type TestSelector, then default settings are altered to include only test
95+
* names from these selectors. This allows to run particular test cases within given test class.
96+
* testFilter is treated as a regular expression, hence joining is done via '|'.
97+
*/
98+
private RunSettings alterRunSettings(RunSettings defaultSettings, Selector[] selectors) {
99+
boolean onlyTestSelectors = Arrays.stream(selectors).allMatch(selector -> selector instanceof TestSelector);
100+
if (onlyTestSelectors) {
101+
String testFilter = Arrays
102+
.stream(selectors)
103+
.map(selector -> ((TestSelector) selector).testName())
104+
.collect(Collectors.joining("|"));
105+
// if already provided testFilter is not empty add to it | (regex or operator)
106+
String currentFilter = defaultSettings.testFilter.length() > 0 ? defaultSettings.testFilter + "|" : "";
107+
String newFilter = currentFilter + testFilter;
108+
return defaultSettings.withTestFilter(newFilter);
109+
}
110+
111+
return defaultSettings;
112+
}
113+
89114
private RunListener createRunListener(String runListenerClassName) {
90115
if(runListenerClassName != null) {
91116
try {

src/main/java/com/novocode/junit/RunSettings.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ class RunSettings {
5050
this.testFilter = testFilter;
5151
}
5252

53+
public RunSettings withTestFilter(String newTestFilter) {
54+
String ignoreRunners = String.join(",", this.ignoreRunners);
55+
return new RunSettings(
56+
this.color, this.decodeScalaNames, this.quiet, this.verbosity, this.summary, this.logAssert,
57+
ignoreRunners, this.logExceptionClass, this.sysprops, this.globPatterns, this.includeCategories,
58+
this.excludeCategories, newTestFilter
59+
);
60+
}
61+
5362
String decodeName(String name) {
5463
return decodeScalaNames ? decodeScalaName(name) : name;
5564
}
@@ -108,7 +117,7 @@ String buildErrorMessage(Throwable t) {
108117

109118
private String buildColoredName(Description desc, String c1, String c2, String c3) {
110119
StringBuilder b = new StringBuilder();
111-
120+
112121
String cn = decodeName(desc.getClassName());
113122
int pos1 = cn.indexOf('$');
114123
int pos2 = pos1 == -1 ? cn.lastIndexOf('.') : cn.lastIndexOf('.', pos1);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name := "test-project"
2+
3+
scalaVersion := "2.13.7"
4+
5+
libraryDependencies += "com.github.sbt" % "junit-interface" % sys.props("plugin.version") % "test"
6+
libraryDependencies += "org.scala-sbt" % "test-agent" % "1.5.5" % Test
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=1.6.1
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import com.novocode.junit.JUnitFramework
2+
import com.novocode.junit.JUnitFingerprint
3+
4+
import org.junit.Test
5+
import org.junit.Assert._
6+
7+
import sbt.testing._
8+
import scala.collection.mutable.ArrayBuffer
9+
10+
/**
11+
* Check if TestSelector's are correctly handled by JUnitRunner.
12+
* Execute prepared TaskDef's using manually created instances of sbt.testing.{Framework and Runner}.
13+
*/
14+
class CheckTestSelector {
15+
val framework = new JUnitFramework();
16+
val runner = framework.runner(
17+
Array.empty[String],
18+
Array.empty[String],
19+
this.getClass().getClassLoader()
20+
);
21+
22+
private def getEventHandler(): (ArrayBuffer[String], EventHandler) = {
23+
val executedItems = new scala.collection.mutable.ArrayBuffer[String]
24+
val eventHandler = new EventHandler {
25+
override def handle(event: Event) =
26+
if (event.status() == Status.Success) {
27+
executedItems.addOne(event.fullyQualifiedName())
28+
}
29+
}
30+
(executedItems, eventHandler)
31+
}
32+
33+
private def getTaskDefs(selectors: Array[Selector]): Array[TaskDef] = {
34+
Array(
35+
new TaskDef("a.b.MyTestSuite", new JUnitFingerprint(), false, selectors)
36+
)
37+
}
38+
39+
@Test
40+
def runAllViaSuiteSelector() {
41+
val selectors = Array[Selector](
42+
new SuiteSelector
43+
)
44+
val taskDefs = Array(
45+
new TaskDef("a.b.MyTestSuite", new JUnitFingerprint(), false, selectors)
46+
)
47+
48+
val tasks = runner.tasks(taskDefs)
49+
assertEquals(tasks.size, 1)
50+
val task = tasks(0)
51+
52+
val (executedItems, eventHandler) = getEventHandler()
53+
54+
task.execute(eventHandler, Nil.toArray)
55+
assertArrayEquals(
56+
Array[Object]("a.b.MyTestSuite.testBar", "a.b.MyTestSuite.testFoo"),
57+
executedItems.toArray[Object]
58+
)
59+
}
60+
61+
@Test
62+
def runAllViaTestSelectors() {
63+
val selectors = Array[Selector](
64+
new TestSelector("testFoo"),
65+
new TestSelector("testBar")
66+
)
67+
val taskDefs = getTaskDefs(selectors)
68+
69+
val tasks = runner.tasks(taskDefs)
70+
assertEquals(tasks.size, 1)
71+
val task = tasks(0)
72+
73+
val (executedItems, eventHandler) = getEventHandler()
74+
75+
task.execute(eventHandler, Nil.toArray)
76+
assertArrayEquals(
77+
Array[Object]("a.b.MyTestSuite.testBar", "a.b.MyTestSuite.testFoo"),
78+
executedItems.toArray[Object]
79+
)
80+
}
81+
82+
@Test
83+
def runOnlyOne() {
84+
val selectors = Array[Selector](
85+
new TestSelector("testFoo")
86+
)
87+
val taskDefs = getTaskDefs(selectors)
88+
89+
val tasks = runner.tasks(taskDefs)
90+
assertEquals(tasks.size, 1)
91+
val task = tasks(0)
92+
93+
val (executedItems, eventHandler) = getEventHandler()
94+
95+
task.execute(eventHandler, Nil.toArray)
96+
assertArrayEquals(
97+
Array[Object]("a.b.MyTestSuite.testFoo"),
98+
executedItems.toArray[Object]
99+
)
100+
101+
}
102+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package a.b
2+
3+
import org.junit.Test
4+
import org.junit.Assert.assertEquals
5+
6+
class MyTestSuite {
7+
8+
@Test
9+
def testFoo(): Unit = {
10+
assertEquals("Test should pass", true, true)
11+
}
12+
13+
@Test
14+
def testBar(): Unit = {
15+
assertEquals("Test should pass", true, true)
16+
}
17+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# make sure the unit test passes
2+
> test

0 commit comments

Comments
 (0)