Skip to content

Commit

Permalink
Add the ability to select the test type to run
Browse files Browse the repository at this point in the history
Also makes sure unit tests run before @QuarkusTest
based tests, and fixes a dev mode startup time
regression.
  • Loading branch information
stuartwdouglas committed Apr 29, 2021
1 parent 45b205c commit bea6ffb
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 51 deletions.
Expand Up @@ -18,8 +18,10 @@ public class AeshConsole extends QuarkusConsole {
private String promptMessage;
private int totalStatusLines = 0;
private int lastWriteCursorX;
private final boolean inputSupport;

public AeshConsole(Connection connection) {
public AeshConsole(Connection connection, boolean inputSupport) {
this.inputSupport = inputSupport;
INSTANCE = this;
this.connection = connection;
connection.openNonBlocking();
Expand Down Expand Up @@ -62,6 +64,9 @@ public AeshInputHolder createHolder(InputHandler inputHandler) {
}

private synchronized AeshConsole setPromptMessage(String promptMessage) {
if (!inputSupport) {
return this;
}
StringBuilder buffer = new StringBuilder();
clearStatusMessages(buffer);
int newLines = countLines(statusMessage) + countLines(promptMessage);
Expand Down Expand Up @@ -95,29 +100,31 @@ private synchronized void end(Connection conn) {

private void setup(Connection conn) {
size = conn.size();
// Ctrl-C ends the game
conn.setSignalHandler(event -> {
switch (event) {
case INT:
//todo: why does async exit not work here
//Quarkus.asyncExit();
//end(conn);
new Thread(new Runnable() {
@Override
public void run() {
System.exit(0);
}
}).start();
break;
}
});
// Keyboard handling
conn.setStdinHandler(keys -> {
InputHolder handler = inputHandlers.peek();
if (handler != null) {
handler.handler.handleInput(keys);
}
});
if (inputSupport) {
conn.setSignalHandler(event -> {
switch (event) {
// Ctrl-C shutdown
case INT:
//todo: why does async exit not work here
//Quarkus.asyncExit();
//end(conn);
new Thread(new Runnable() {
@Override
public void run() {
System.exit(0);
}
}).start();
break;
}
});
conn.setStdinHandler(keys -> {
InputHolder handler = inputHandlers.peek();
if (handler != null) {
handler.handler.handleInput(keys);
}
});
}

conn.setCloseHandler(close -> end(conn));
conn.setSizeHandler(size -> setup(conn));
Expand All @@ -126,7 +133,11 @@ public void run() {
//conn.write(ANSI.ALTERNATE_BUFFER);
//conn.write(ANSI.CURSOR_HIDE);

attributes = conn.enterRawMode();
if (inputSupport) {
attributes = conn.enterRawMode();
} else {
attributes = conn.getAttributes();
}

StringBuilder sb = new StringBuilder();
printStatusAndPrompt(sb);
Expand Down
Expand Up @@ -6,7 +6,7 @@
import org.aesh.readline.tty.terminal.TerminalConnection;
import org.aesh.terminal.Connection;

import io.quarkus.deployment.TestConfig;
import io.quarkus.deployment.dev.testing.TestConfig;
import io.quarkus.dev.console.BasicConsole;
import io.quarkus.dev.console.QuarkusConsole;

Expand All @@ -18,22 +18,23 @@ public static synchronized void installConsole(TestConfig config) {
}
QuarkusConsole.installed = true;
if (config.basicConsole) {
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, true, System.out);
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, !config.disableConsoleInput, System.out);
} else {
try {
new TerminalConnection(new Consumer<Connection>() {
@Override
public void accept(Connection connection) {
if (connection.supportsAnsi()) {
QuarkusConsole.INSTANCE = new AeshConsole(connection);
QuarkusConsole.INSTANCE = new AeshConsole(connection, !config.disableConsoleInput);
} else {
connection.close();
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, true, System.out);
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, !config.disableConsoleInput,
System.out);
}
}
});
} catch (IOException e) {
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, true, System.out);
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, !config.disableConsoleInput, System.out);
}
}
RedirectPrintStream ps = new RedirectPrintStream();
Expand Down
Expand Up @@ -107,6 +107,7 @@ public class JunitTestRunner {
private final Pattern exclude;
private final boolean displayInConsole;
private final boolean failingTestsOnly;
private final TestType testType;

private volatile boolean testsRunning = false;
private volatile boolean aborted;
Expand All @@ -127,6 +128,7 @@ public JunitTestRunner(Builder builder) {
this.exclude = builder.exclude;
this.displayInConsole = builder.displayInConsole;
this.failingTestsOnly = builder.failingTestsOnly;
this.testType = builder.testType;
}

public void runTests() {
Expand Down Expand Up @@ -201,6 +203,9 @@ public void quarkusStarting() {

@Override
public void executionStarted(TestIdentifier testIdentifier) {
if (aborted) {
return;
}
String className = "";
Class<?> clazz = null;
if (testIdentifier.getSource().isPresent()) {
Expand Down Expand Up @@ -476,15 +481,16 @@ private DiscoveryResult discoverTestClasses(DevModeContext devModeContext) {
unitTestClasses.add(name);
}

List<Class<?>> qtClasses = new ArrayList<>();
List<Class<?>> itClasses = new ArrayList<>();
List<Class<?>> utClasses = new ArrayList<>();
for (String i : quarkusTestClasses) {
try {
qtClasses.add(Thread.currentThread().getContextClassLoader().loadClass(i));
itClasses.add(Thread.currentThread().getContextClassLoader().loadClass(i));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
qtClasses.sort(Comparator.comparing(new Function<Class<?>, String>() {
itClasses.sort(Comparator.comparing(new Function<Class<?>, String>() {
@Override
public String apply(Class<?> aClass) {
ClassInfo def = index.getClassByName(DotName.createSimple(aClass.getName()));
Expand Down Expand Up @@ -521,14 +527,26 @@ public String apply(Class<?> aClass) {
transformedClasses);
for (String i : unitTestClasses) {
try {
qtClasses.add(cl.loadClass(i));
utClasses.add(cl.loadClass(i));
} catch (ClassNotFoundException exception) {
throw new RuntimeException(exception);
}
}

}
return new DiscoveryResult(cl, qtClasses);
if (testType == TestType.ALL) {
//run unit style tests first
//before the quarkus tests have started
//which stops quarkus interfering with WireMock
List<Class<?>> ret = new ArrayList<>(utClasses.size() + itClasses.size());
ret.addAll(utClasses);
ret.addAll(itClasses);
return new DiscoveryResult(cl, ret);
} else if (testType == TestType.UNIT) {
return new DiscoveryResult(cl, utClasses);
} else {
return new DiscoveryResult(cl, itClasses);
}
}

private static Set<DotName> collectTestAnnotations(Index index) {
Expand Down Expand Up @@ -607,6 +625,7 @@ public boolean test(String logRecord) {
}

static class Builder {
private TestType testType = TestType.ALL;
private TestState testState;
private long runId = -1;
private DevModeContext devModeContext;
Expand All @@ -627,6 +646,11 @@ public Builder setRunId(long runId) {
return this;
}

public Builder setTestType(TestType testType) {
this.testType = testType;
return this;
}

public Builder setDevModeContext(DevModeContext devModeContext) {
this.devModeContext = devModeContext;
return this;
Expand Down
@@ -1,4 +1,4 @@
package io.quarkus.deployment;
package io.quarkus.deployment.dev.testing;

import java.time.Duration;
import java.util.List;
Expand Down Expand Up @@ -94,6 +94,13 @@ public class TestConfig {
@ConfigItem(defaultValue = "true")
public boolean console;

/**
* Disables the ability to enter input on the console.
*
*/
@ConfigItem(defaultValue = "false")
public boolean disableConsoleInput;

/**
* Changes tests to use the 'flat' ClassPath used in Quarkus 1.x versions.
*
Expand Down Expand Up @@ -134,6 +141,17 @@ public class TestConfig {
@ConfigItem(defaultValue = "10m")
Duration hangDetectionTimeout;

/**
* The type of test to run, this can be either:
*
* quarkus-test: Only runs {@code @QuarkusTest} annotated test classes
* unit: Only runs classes that are not annotated with {@code @QuarkusTest}
* all: Runs both, running the unit tests first
*
*/
@ConfigItem(defaultValue = "all")
TestType type;

@ConfigGroup
public static class Profile {

Expand All @@ -157,6 +175,5 @@ public enum Mode {
PAUSED,
ENABLED,
DISABLED

}
}
Expand Up @@ -25,6 +25,7 @@
import io.quarkus.bootstrap.app.CuratedApplication;
import io.quarkus.deployment.dev.ClassScanResult;
import io.quarkus.deployment.dev.DevModeContext;
import io.quarkus.runtime.configuration.HyphenateEnumConverter;

public class TestRunner {

Expand Down Expand Up @@ -55,6 +56,7 @@ public class TestRunner {
String appPropertiesExcludeTags;
String appPropertiesIncludePattern;
String appPropertiesExcludePattern;
String appPropertiesTestType;

public TestRunner(TestSupport testSupport, DevModeContext devModeContext, CuratedApplication testApplication) {
this.testSupport = testSupport;
Expand Down Expand Up @@ -85,9 +87,6 @@ private void runTests(ClassScanResult classScanResult, boolean reRunFailures) {
if (compileProblem != null) {
return;
}
if (testApplication == null) {
return;
}
if (disabled) {
return;
}
Expand Down Expand Up @@ -137,7 +136,7 @@ public void run() {
current = queuedChanges;
queuedChanges = null;
}
testsRunning = run;
testsRunning = false;
}
if (run) {
runTests(current);
Expand Down Expand Up @@ -208,6 +207,7 @@ private void runInternal(ClassScanResult classScanResult, boolean reRunFailures)
.setExcludeTags(testSupport.excludeTags)
.setInclude(testSupport.include)
.setExclude(testSupport.exclude)
.setTestType(testSupport.testType)
.setFailingTestsOnly(testSupport.failingTestsOnly);
if (reRunFailures) {
Set<UniqueId> ids = new HashSet<>();
Expand Down Expand Up @@ -278,6 +278,7 @@ private void handleApplicationPropertiesChange() {
String excludeTags = p.getProperty("quarkus.test.exclude-tags");
String includePattern = p.getProperty("quarkus.test.include-pattern");
String excludePattern = p.getProperty("quarkus.test.exclude-pattern");
String testType = p.getProperty("quarkus.test.type");
if (!firstRun) {
if (!Objects.equals(includeTags, appPropertiesIncludeTags)) {
if (includeTags == null) {
Expand Down Expand Up @@ -309,11 +310,19 @@ private void handleApplicationPropertiesChange() {
testSupport.exclude = Pattern.compile(excludePattern);
}
}
if (!Objects.equals(testType, appPropertiesTestType)) {
if (testType == null) {
testSupport.testType = TestType.ALL;
} else {
testSupport.testType = new HyphenateEnumConverter<>(TestType.class).convert(testType);
}
}
}
appPropertiesIncludeTags = includeTags;
appPropertiesExcludeTags = excludeTags;
appPropertiesIncludePattern = includePattern;
appPropertiesExcludePattern = excludePattern;
appPropertiesTestType = testType;
break;
}
}
Expand Down
Expand Up @@ -39,6 +39,7 @@ public class TestSupport implements TestController {
volatile boolean displayTestOutput;
volatile Boolean explicitDisplayTestOutput;
volatile boolean failingTestsOnly;
volatile TestType testType = TestType.ALL;

public TestSupport(CuratedApplication curatedApplication, List<CompilationProvider> compilationProviders,
DevModeContext context) {
Expand Down Expand Up @@ -143,7 +144,6 @@ public synchronized void stop() {
}
}
if (testRunner != null) {

testRunner.disable();
}
}
Expand Down Expand Up @@ -217,6 +217,11 @@ public TestSupport setConfiguredDisplayTestOutput(boolean displayTestOutput) {
return this;
}

public TestSupport setTestType(TestType testType) {
this.testType = testType;
return this;
}

@Override
public TestState currentState() {
return testState;
Expand Down

0 comments on commit bea6ffb

Please sign in to comment.