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

JUnit testing support Bug fixes and Enhancements - Step 1 #4303

Merged
merged 22 commits into from
Mar 10, 2017
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
02ae5f2
Provide JUnit test real-time output in a `Tests` output view.
davidfestal Feb 22, 2017
cc4469a
- Use Javassit to correctly create the test listeners for JUnit
davidfestal Feb 24, 2017
a2316bf
Try using the ClasspathService instead of Maven ...
davidfestal Feb 28, 2017
6cdbd06
Only add the Command output at test session start.
davidfestal Mar 1, 2017
c2a7241
Set the current working directory to the project root during test
davidfestal Mar 1, 2017
b36c5ec
Use `ClasspathService` instead of running the maven dependencies plugin
davidfestal Mar 1, 2017
c7a7fc8
Abstract the real test run in a single class used by all action classes
davidfestal Mar 1, 2017
0f430e4
Fix format
Mar 3, 2017
239c490
Call `LOG` instead of ` System.println`.
Mar 3, 2017
8780bfb
Sort POMs
Mar 3, 2017
3eda7ef
Further fix format
davidfestal Mar 3, 2017
022a430
Some fields should have been made `final`
davidfestal Mar 3, 2017
22bab77
Avoid string concatenation in log messages
davidfestal Mar 3, 2017
8c718b2
Fixed a missing dependency
davidfestal Mar 3, 2017
131bf87
Remove the explicit version
davidfestal Mar 3, 2017
4f0c8e3
remove extra new line
davidfestal Mar 3, 2017
f87c3c7
Also pass the workspace-relative project path to the classpath provider
davidfestal Mar 6, 2017
8c00de8
Test for the maven classpath provider
davidfestal Mar 7, 2017
d6900e6
`test-compile` the project using maven before executing the tests...
davidfestal Mar 7, 2017
ba8a293
Refactor a bit to ease the build of the tests
davidfestal Mar 9, 2017
5a698ac
Tests for the ` TestServiceClient`
davidfestal Mar 9, 2017
0bf39a0
Add new line at the end of the file as requested by @skabashnyuk
davidfestal Mar 9, 2017
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,32 @@
<artifactId>guice-multibindings</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
<groupId>org.eclipse.birt.runtime</groupId>
<artifactId>org.eclipse.equinox.common</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.lib</groupId>
<artifactId>org-eclipse-jdt-core-repack</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-java-ext-lang-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-java-ext-lang-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-classpath-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>org.eclipse.core.resources</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,51 @@
*******************************************************************************/
package org.eclipse.che.plugin.testing.classpath.maven.server;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import org.eclipse.che.api.core.util.CommandLine;
import org.eclipse.che.api.core.util.LineConsumer;
import org.eclipse.che.api.core.util.ProcessUtil;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.eclipse.che.plugin.java.server.rest.ClasspathService;
import org.eclipse.che.plugin.testing.classpath.server.TestClasspathProvider;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaModelException;

import com.google.inject.Inject;

/**
* Maven implementation for the test classpath provider.
*
* @author Mirage Abeysekara
* @author David Festal
*
*/
public class MavenTestClasspathProvider implements TestClasspathProvider {

/**
private ClasspathService classpathService;

@Inject
public MavenTestClasspathProvider(ClasspathService classpathService) {
this.classpathService = classpathService;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidfestal I still see here a tab character ?

}

/**
* {@inheritDoc}
*/
@Override
public ClassLoader getClassLoader(String projectPath, boolean updateClasspath) throws Exception {
List<URL> classUrls;
try {
if (updateClasspath) {
buildClasspath(projectPath);
}
classUrls = getProjectClasspath(projectPath);
} catch (IOException | InterruptedException e) {
throw new Exception("Failed to build Maven classpath.", e);
return new URLClassLoader(getProjectClasspath(projectPath).toArray(URL[]::new), null);
} catch (JavaModelException e) {
throw new Exception("Failed to build the classpath for testing project: " + projectPath, e);
}
return new URLClassLoader(classUrls.toArray(new URL[classUrls.size()]), null);
}

/**
Expand All @@ -57,35 +65,56 @@ public String getProjectType() {
return "maven";
}

private boolean buildClasspath(String projectPath) throws IOException, InterruptedException {
final CommandLine commandLineClassPath = new CommandLine("mvn", "clean", "dependency:build-classpath",
"-Dmdep.outputFile=target/test.classpath.maven");
Process processBuildClassPath = new ProcessBuilder().redirectErrorStream(true).directory(new File(projectPath))
.command(commandLineClassPath.toShellCommand()).start();
ProcessUtil.process(processBuildClassPath, LineConsumer.DEV_NULL, LineConsumer.DEV_NULL);
processBuildClassPath.waitFor();
final CommandLine commandLineTestCompile = new CommandLine("mvn", "test-compile");
Process processTestCompile = new ProcessBuilder().redirectErrorStream(true).directory(new File(projectPath))
.command(commandLineTestCompile.toShellCommand()).start();
ProcessUtil.process(processTestCompile, LineConsumer.DEV_NULL, LineConsumer.DEV_NULL);
return processTestCompile.waitFor() == 0;

private Stream<ClasspathEntryDto> toResolvedClassPath(Stream<ClasspathEntryDto> rawClasspath) {
return rawClasspath.flatMap(dto -> {
if (dto.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
return toResolvedClassPath(dto.getExpandedEntries().stream());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and there. so I'm not sure it's up-to-date ?

} else {
return Stream.of(dto);
}
});
}

private List<URL> getProjectClasspath(String projectPath) throws IOException {
List<URL> classUrls = new ArrayList<>();
File cpFile = Paths.get(projectPath, "target", "test.classpath.maven").toFile();
FileReader fileReader = new FileReader(cpFile);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = bufferedReader.readLine();
String[] paths = line.split(":");
for (String path : paths) {
classUrls.add(new File(path).toURI().toURL());
}
bufferedReader.close();
fileReader.close();
classUrls.add(Paths.get(projectPath, "target", "classes").toUri().toURL());
classUrls.add(Paths.get(projectPath, "target", "test-classes").toUri().toURL());
return classUrls;

private Stream<URL> getProjectClasspath(String projectPath) throws JavaModelException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to have unit tests for that part ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will be, surely, but is it required now, or could I push the tests in a next pull request ?

String relativeProject = projectPath.substring(ResourcesPlugin.getPathToWorkspace().length());
IContainer root = ResourcesPlugin.getWorkspace().getRoot();
return toResolvedClassPath(classpathService.getClasspath(relativeProject).stream())
.map(dto -> {
try {
String dtoPath = dto.getPath();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems there is usage of tab characters and indent is not correct

IResource res = root.findMember(new Path(dtoPath));
File path;
switch(dto.getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY:
if (res == null) {
path = new File(dtoPath);
} else {
path = new File(root.getLocation().toFile(), dtoPath);
}
break;
case IClasspathEntry.CPE_SOURCE:
IPath projectRelativePath = new Path(dtoPath).removeFirstSegments(1);
String projectRelativePathStr = projectRelativePath.toString();
switch(projectRelativePathStr) {
case "src/main/java":
path = Paths.get(projectPath, "target", "classes").toFile();
break;
case "src/test/java":
path = Paths.get(projectPath, "target", "test-classes").toFile();
break;
default:
path = new File(root.getLocation().toFile(), dtoPath);
}
break;
default:
path = new File(dtoPath);
}
return path.toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
})
.filter(url -> url != null)
.distinct();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,14 @@
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide.action;

import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.PROGRESS;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.SUCCESS;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.api.testing.shared.TestResult;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.ext.java.client.action.JavaEditorAction;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.view.TestResultPresenter;
Expand All @@ -40,12 +29,15 @@
/**
*
* @author Mirage Abeysekara
* @author David Festal
*/
public class RunAllTestAction extends JavaEditorAction {
public class RunAllTestAction extends JavaEditorAction
implements RunTestActionDelegate.Source {

private final NotificationManager notificationManager;
private TestResultPresenter presenter;
private final TestServiceClient service;
private RunTestActionDelegate delegate;

@Inject
public RunAllTestAction(JUnitTestResources resources,
Expand All @@ -61,38 +53,32 @@ public RunAllTestAction(JUnitTestResources resources,
this.editorAgent = editorAgent;
this.presenter = presenter;
this.service = service;
this.delegate = new RunTestActionDelegate(this);
}

@Override
public void actionPerformed(ActionEvent e) {
final StatusNotification notification = new StatusNotification("Running Tests...", PROGRESS, FLOAT_MODE);
notificationManager.notify(notification);
final Project project = appContext.getRootProject();
Map<String, String> parameters = new HashMap<>();
parameters.put("updateClasspath", "true");
Promise<TestResult> testResultPromise = service.getTestResult(project.getPath(), "junit", parameters);
testResultPromise.then(new Operation<TestResult>() {
@Override
public void apply(TestResult result) throws OperationException {
notification.setStatus(SUCCESS);
if (result.isSuccess()) {
notification.setTitle("Test runner executed successfully");
notification.setContent("All tests are passed");
} else {
notification.setTitle("Test runner executed successfully with test failures.");
notification.setContent(result.getFailureCount() + " test(s) failed.\n");
}
presenter.handleResponse(result);
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError exception) throws OperationException {
final String errorMessage = (exception.getMessage() != null) ? exception.getMessage()
: "Failed to run test cases";
notification.setContent(errorMessage);
notification.setStatus(FAIL);
}
});
delegate.doRunTests(e, parameters);
}

@Override
public NotificationManager getNotificationManager() {
return notificationManager;
}

@Override
public AppContext getAppContext() {
return appContext;
}

@Override
public TestServiceClient getService() {
return service;
}

@Override
public TestResultPresenter getPresenter() {
return presenter;
}
}
Loading