diff --git a/tests/pom.xml b/tests/pom.xml
index 8518a31dd..28955d1bd 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -86,9 +86,14 @@
en, en_US, en_GB, ru, ru_RU
${teavm.test.incremental}
- http://127.0.0.1:4444/wd/hub
+
+ run-javascript-tests
+
+ test
+
+
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java b/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java
index 9f0903ddd..b65841aa6 100644
--- a/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java
@@ -364,7 +364,8 @@ public class TeaVMTestTool implements BaseTeaVMTool {
testClass.getMethods().add(testMethod);
String debugTable = debugInformationGenerated ? testMethod.getFileName() + ".teavmdbg" : null;
- cases.add(new TestCase(ref, testMethod.getFileName(), debugTable, testMethod.getExpectedExceptions()));
+ cases.add(new TestCase(ref.toString(), testMethod.getFileName(), debugTable,
+ testMethod.getExpectedExceptions()));
++testCount;
}
}
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java
index a534649b4..5c0ae9e1b 100644
--- a/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java
@@ -21,21 +21,20 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class TestCase {
- private MethodReference testMethod;
+ private String testMethod;
private String testScript;
private String debugTable;
private List expectedExceptions = new ArrayList<>();
@JsonCreator
public TestCase(
- @JsonProperty("testMethod") MethodReference testMethod,
+ @JsonProperty("testMethod") String testMethod,
@JsonProperty("script") String testScript,
@JsonProperty("debugTable") String debugTable,
@JsonProperty("expectedExceptions") List expectedExceptions) {
@@ -46,7 +45,7 @@ public class TestCase {
}
@JsonGetter
- public MethodReference getTestMethod() {
+ public String getTestMethod() {
return testMethod;
}
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java
index e5eefd289..32ce4b364 100644
--- a/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java
@@ -16,6 +16,7 @@
package org.teavm.tooling.testing;
import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,15 +33,17 @@ public class TestPlan {
@JsonCreator
public TestPlan(
@JsonProperty("runtimeScript") String runtimeScript,
- @JsonProperty("groupList") List groups) {
+ @JsonProperty("groups") List groups) {
this.runtimeScript = runtimeScript;
this.groups = Collections.unmodifiableList(new ArrayList<>(groups));
}
+ @JsonGetter
public String getRuntimeScript() {
return runtimeScript;
}
+ @JsonGetter
public List getGroups() {
return groups;
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
index a5c702111..de0617ebd 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
@@ -15,12 +15,15 @@
*/
package org.teavm.maven;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
-import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
@@ -42,6 +45,7 @@ import org.teavm.testing.JUnitTestAdapter;
import org.teavm.testing.TestAdapter;
import org.teavm.tooling.TeaVMToolException;
import org.teavm.tooling.testing.TeaVMTestTool;
+import org.teavm.tooling.testing.TestPlan;
/**
*
@@ -84,11 +88,6 @@ public class BuildJavascriptTestMojo extends AbstractJavascriptMojo {
@Parameter
private boolean incremental;
- @Parameter
- private URL seleniumURL;
-
- private SeleniumTestRunner seleniumRunner;
-
private TeaVMTestTool tool = new TeaVMTestTool();
@Override
@@ -111,29 +110,19 @@ public class BuildJavascriptTestMojo extends AbstractJavascriptMojo {
if (additionalScripts != null) {
tool.getAdditionalScripts().addAll(Arrays.asList(additionalScripts));
}
- tool.generate();
+ writePlan(tool.generate());
} catch (TeaVMToolException e) {
throw new MojoFailureException("Error occured generating JavaScript files", e);
}
}
- private void processReport(List report) throws MojoExecutionException {
- if (report.isEmpty()) {
- getLog().info("No tests ran");
- return;
- }
-
- int failedTests = 0;
- for (TestResult result : report) {
- if (result.getStatus() != TestStatus.PASSED) {
- failedTests++;
- }
- }
-
- if (failedTests > 0) {
- throw new MojoExecutionException(failedTests + " of " + report.size() + " test(s) failed");
- } else {
- getLog().info("All of " + report.size() + " tests successfully passed");
+ private void writePlan(TestPlan plan) throws MojoExecutionException {
+ File file = new File(targetDirectory, "plan.json");
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.writeValue(writer, plan);
+ } catch (IOException e) {
+ throw new MojoExecutionException("Error writing test plan", e);
}
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
index 9b6f3df63..f89a3d176 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
@@ -15,17 +15,71 @@
*/
package org.teavm.maven;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.List;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
+import org.teavm.tooling.testing.TestPlan;
/**
*
* @author Alexey Andreev
*/
-@Mojo(name = "run-tests", defaultPhase = LifecyclePhase.TEST)
-public class RunTestsMojo {
- @Parameter(defaultValue = "${project.build.directory}/javascript-tests")
- private File targetDirectory;
+@Mojo(name = "test", defaultPhase = LifecyclePhase.TEST)
+public class RunTestsMojo extends AbstractMojo {
+ @Parameter(defaultValue = "${project.build.directory}/javascript-test")
+ private File testDirectory;
+
+ @Parameter
+ private URL seleniumURL;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ SeleniumTestRunner runner = new SeleniumTestRunner();
+ runner.setLog(getLog());
+ runner.setDirectory(testDirectory);
+ runner.setUrl(seleniumURL);
+
+ TestPlan plan;
+ ObjectMapper mapper = new ObjectMapper();
+ File file = new File(testDirectory, "plan.json");
+ try (Reader reader = new InputStreamReader(new FileInputStream(file), "UTF-8")) {
+ plan = mapper.readValue(reader, TestPlan.class);
+ } catch (IOException e) {
+ throw new MojoExecutionException("Error reading test plan", e);
+ }
+
+ runner.run(plan);
+ processReport(runner.getReport());
+ }
+
+ private void processReport(List report) throws MojoExecutionException {
+ if (report.isEmpty()) {
+ getLog().info("No tests ran");
+ return;
+ }
+
+ int failedTests = 0;
+ for (TestResult result : report) {
+ if (result.getStatus() != TestStatus.PASSED) {
+ failedTests++;
+ }
+ }
+
+ if (failedTests > 0) {
+ throw new MojoExecutionException(failedTests + " of " + report.size() + " test(s) failed");
+ } else {
+ getLog().info("All of " + report.size() + " tests successfully passed");
+ }
+ }
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java b/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java
index b42118682..836cfd405 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java
@@ -35,6 +35,7 @@ import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver;
+import org.teavm.model.MethodReference;
import org.teavm.tooling.testing.TestCase;
import org.teavm.tooling.testing.TestGroup;
import org.teavm.tooling.testing.TestPlan;
@@ -48,7 +49,7 @@ public class SeleniumTestRunner {
private int numThreads = 1;
private ThreadLocal webDriver = new ThreadLocal<>();
private BlockingQueue seleniumTaskQueue = new LinkedBlockingQueue<>();
- private CountDownLatch latch = new CountDownLatch(1);
+ private CountDownLatch latch;
private volatile boolean seleniumStopped = false;
private Log log;
private List report = new CopyOnWriteArrayList<>();
@@ -95,15 +96,16 @@ public class SeleniumTestRunner {
}
private void initSelenium() {
+ latch = new CountDownLatch(numThreads);
for (int i = 0; i < numThreads; ++i) {
new Thread(() -> {
ChromeDriver driver = new ChromeDriver();
webDriver.set(driver);
localReport.set(new ArrayList<>());
- while (!seleniumStopped) {
+ while (!seleniumStopped || !seleniumTaskQueue.isEmpty()) {
Runnable task;
try {
- task = seleniumTaskQueue.poll(1, TimeUnit.SECONDS);
+ task = seleniumTaskQueue.poll(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
break;
}
@@ -113,22 +115,19 @@ public class SeleniumTestRunner {
}
report.addAll(localReport.get());
localReport.remove();
+ webDriver.get().close();
webDriver.remove();
+ latch.countDown();
}).start();
}
}
private void addSeleniumTask(Runnable runnable) {
- if (url != null) {
- seleniumTaskQueue.add(runnable);
- }
+ seleniumTaskQueue.add(runnable);
}
private void stopSelenium() {
- addSeleniumTask(() -> {
- seleniumStopped = true;
- latch.countDown();
- });
+ seleniumStopped = true;
}
private void waitForCompletion() {
@@ -145,7 +144,7 @@ public class SeleniumTestRunner {
private void runImpl(String runtimeScript, TestCase testCase) {
webDriver.get().manage().timeouts().setScriptTimeout(2, TimeUnit.SECONDS);
- JavascriptExecutor js = (JavascriptExecutor) webDriver;
+ JavascriptExecutor js = (JavascriptExecutor) webDriver.get();
try {
String result = (String) js.executeAsyncScript(
readResource("teavm-selenium.js"),
@@ -155,15 +154,16 @@ public class SeleniumTestRunner {
ObjectMapper mapper = new ObjectMapper();
ObjectNode resultObject = (ObjectNode) mapper.readTree(result);
String status = resultObject.get("status").asText();
+ MethodReference ref = MethodReference.parse(testCase.getTestMethod());
switch (status) {
case "ok":
log.info("Test passed: " + testCase.getTestMethod());
- localReport.get().add(TestResult.passed(testCase.getTestMethod()));
+ localReport.get().add(TestResult.passed(ref));
break;
case "exception": {
String stack = resultObject.get("stack").asText();
log.info("Test failed: " + testCase.getTestMethod());
- localReport.get().add(TestResult.error(testCase.getTestMethod(), stack));
+ localReport.get().add(TestResult.error(ref, stack));
break;
}
}