Merge branch 'master' into spi

6.19.x
Artem Zatsarynnyi 2017-08-02 10:05:43 +03:00
commit c9d0c12923
69 changed files with 2219 additions and 576 deletions

View File

@ -0,0 +1,62 @@
#!/usr/bin/env bats
# Copyright (c) 2012-2017 Red Hat, Inc
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Mario
#
# How to run this script:
# cd <root of che local git repository>
# export CHE_BASE_DIR=$(pwd)
# export LAUNCHER_SCRIPT_TO_TEST=wsagent/agent/src/main/resources/org.eclipse.che.ws-agent.script.sh
# export BATS_TEST_SCRIPT=agents/che-core-api-agent/src/test/resources/agents-launchers-tests-arbitraryuser.bats
# export DOCKER_IMAGE=rhche/centos_jdk8
# docker run -ti --rm -e CHE_BASE_DIR -e LAUNCHER_SCRIPT_TO_TEST -e DOCKER_IMAGE \
# -v ${CHE_BASE_DIR}/${BATS_TEST_SCRIPT}:/scripts/launcher_tests.bats \
# -v ${CHE_BASE_DIR}/dockerfiles:/dockerfiles \
# -v /var/run/docker.sock:/var/run/docker.sock \
# eclipse/che-bats bats /scripts/launcher_tests.bats
#
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
. /dockerfiles/cli/tests/test_base.sh
CONTAINER_NAME="test"
script_host_path=${CHE_BASE_DIR}/${LAUNCHER_SCRIPT_TO_TEST}
root_msg="I am root"
not_root_msg="I am a not root"
sudoer_msg="I am a sudoer"
not_sudoer_msg="I am a not a sudoer"
test_snippet="source <(grep -iE -A3 'is_current_user_root\(\)|is_current_user_sudoer\(\)|set_sudo_command\(\)' /launch.sh | grep -v -- "^--$"); is_current_user_root && echo -n '${root_msg} ' || echo -n '${not_root_msg} '; is_current_user_sudoer && echo '${sudoer_msg}' || echo -n '${not_sudoer_msg} '; set_sudo_command; echo SUDO=\${SUDO}"
user="100000"
# Kill running che server instance if there is any to be able to run tests
setup() {
kill_running_named_container ${CONTAINER_NAME}
remove_named_container ${CONTAINER_NAME}
docker run --security-opt no-new-privileges --user=${user} --name="${CONTAINER_NAME}" -d -v ${script_host_path}:/launch.sh "${DOCKER_IMAGE}"
}
teardown() {
kill_running_named_container "${CONTAINER_NAME}"
remove_named_container ${CONTAINER_NAME}
}
@test "should deduce that's not a sudoer nor root when ${LAUNCHER_SCRIPT_TO_TEST} is run as an arbitrary user" {
#GIVEN
expected_msg="${not_root_msg} ${not_sudoer_msg} SUDO="
#WHEN
run docker exec --user=${user} "${CONTAINER_NAME}" bash -c "${test_snippet}"
#THEN
assert_success
assert_output ${expected_msg}
}

View File

@ -0,0 +1,76 @@
#!/usr/bin/env bats
# Copyright (c) 2012-2017 Red Hat, Inc
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Mario
#
# How to run this script:
# cd <root of che local git repository>
# export CHE_BASE_DIR=$(pwd)
# export LAUNCHER_SCRIPT_TO_TEST=wsagent/agent/src/main/resources/org.eclipse.che.ws-agent.script.sh
# export BATS_TEST_SCRIPT=agents/che-core-api-agent/src/test/resources/agents-launchers-tests.bats
# export DOCKER_IMAGE=eclipse/centos_jdk8
# docker run -ti --rm -e CHE_BASE_DIR -e LAUNCHER_SCRIPT_TO_TEST -e DOCKER_IMAGE \
# -v ${CHE_BASE_DIR}/${BATS_TEST_SCRIPT}:/scripts/launcher_tests.bats \
# -v ${CHE_BASE_DIR}/dockerfiles:/dockerfiles \
# -v /var/run/docker.sock:/var/run/docker.sock \
# eclipse/che-bats bats /scripts/launcher_tests.bats
#
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
. /dockerfiles/cli/tests/test_base.sh
CONTAINER_NAME="batssshscripttest"
script_host_path=${CHE_BASE_DIR}/${LAUNCHER_SCRIPT_TO_TEST}
root_msg="I am root"
not_root_msg="I am a not root"
sudoer_msg="I am a sudoer"
not_sudoer_msg="I am a not a sudoer"
#test_snippet="source <(grep -iE -A3 'is_current_user_root\(\)|is_current_user_sudoer\(\)' /launch.sh | grep -v -- "^--$"); is_current_user_root && echo -n '${root_msg} ' || echo -n '${not_root_msg} '; is_current_user_sudoer && echo '${sudoer_msg}' || echo '${not_sudoer_msg}'"
test_snippet="source <(grep -iE -A3 'is_current_user_root\(\)|is_current_user_sudoer\(\)|set_sudo_command\(\)' /launch.sh | grep -v -- "^--$"); is_current_user_root && echo -n '${root_msg} ' || echo -n '${not_root_msg} '; is_current_user_sudoer && echo -n '${sudoer_msg} ' || echo '${not_sudoer_msg}'; set_sudo_command; echo SUDO=\${SUDO}"
# Kill running che server instance if there is any to be able to run tests
setup() {
kill_running_named_container ${CONTAINER_NAME}
remove_named_container ${CONTAINER_NAME}
docker run --name="${CONTAINER_NAME}" -d -v ${script_host_path}:/launch.sh "${DOCKER_IMAGE}"
}
teardown() {
kill_running_named_container "${CONTAINER_NAME}"
remove_named_container ${CONTAINER_NAME}
}
@test "should deduce that's root and sudoer when ${LAUNCHER_SCRIPT_TO_TEST} is run as root" {
#GIVEN
user="root"
expected_msg="${root_msg} ${sudoer_msg} SUDO="
#WHEN
run docker exec --user=${user} "${CONTAINER_NAME}" bash -c "${test_snippet}"
#THEN
assert_success
# assert_output --partial ${expected_msg}
assert_output ${expected_msg}
}
@test "should deduce that's not root but sudoer when ${LAUNCHER_SCRIPT_TO_TEST} is run as user with UID 1000" {
#GIVEN
user="1000"
expected_msg="${not_root_msg} ${sudoer_msg} SUDO=sudo -E"
#WHEN
run docker exec --user=${user} "${CONTAINER_NAME}" bash -c "${test_snippet}"
#THEN
assert_success
# assert_output --partial ${expected_msg}
assert_output ${expected_msg}
}

View File

@ -0,0 +1,42 @@
#!/bin/bash
#
# Copyright (c) 2012-2017 Codenvy, S.A.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Codenvy, S.A. - initial API and implementation
#
#images=(bitnami/che-codeigniter:3.1.3-r6 bitnami/che-express:4.15.3-r2 bitnami/che-java-play:1.3.12-r3 bitnami/che-laravel:5.4.23-r1 bitnami/che-rails:5.1.2-r0 bitnami/che-swift:3.1.1-r0 bitnami/che-symfony:3.3.2-r0 eclipse/centos_jdk8 eclipse/cpp_gcc eclipse/debian_jdk8 eclipse/debian_jre eclipse/dotnet_core eclipse/hadoop-dev eclipse/kotlin eclipse/node eclipse/php eclipse/php:5.6 eclipse/php:gae eclipse/selenium eclipse/ubuntu_android eclipse/ubuntu_go eclipse/ubuntu_jdk8 eclipse/ubuntu_jre eclipse/ubuntu_python:2.7 eclipse/ubuntu_python:gae_python2.7 eclipse/ubuntu_python:latest eclipse/ubuntu_rails kaloyanraev/che-zendserver registry.centos.org/che-stacks/centos-go registry.centos.org/che-stacks/centos-nodejs registry.centos.org/che-stacks/spring-boot registry.centos.org/che-stacks/vertx registry.centos.org/che-stacks/wildfly-swarm tomitribe/ubuntu_tomee_173_jdk8 registry.centos.org/che-stacks/centos-git)
#arbitrary_images=(rhche/centos_jdk8 rhche/vertx rhche/ubuntu_jdk8 rhche/centos-nodejs rhche/spring-boot rhche/wildfly-swarm)
images=(eclipse/centos_jdk8)
arbitrary_images=(rhche/centos_jdk8)
run_bats_test() {
export CHE_BASE_DIR=$(pwd)
export BATS_TEST_SCRIPT=${1}
export LAUNCHER_SCRIPT_TO_TEST=${2}
export DOCKER_IMAGE=${3}
docker run -ti --rm -e CHE_BASE_DIR -e LAUNCHER_SCRIPT_TO_TEST -e DOCKER_IMAGE \
-v ${CHE_BASE_DIR}/${BATS_TEST_SCRIPT}:/scripts/launcher_tests.bats \
-v ${CHE_BASE_DIR}/dockerfiles:/dockerfiles \
-v /var/run/docker.sock:/var/run/docker.sock \
eclipse/che-bats bats /scripts/launcher_tests.bats
}
for image in "${images[@]}"; do
launcher_script_to_test="wsagent/agent/src/main/resources/org.eclipse.che.ws-agent.script.sh"
bats_test_script="agents/che-core-api-agent/src/test/resources/agents-launchers-tests.bats"
echo "RUNNING LAUNCHER BATS TESTS FOR IMAGE ${image}"
run_bats_test "${bats_test_script}" "${launcher_script_to_test}" "${image}"
done
for arbitrary_image in "${arbitrary_images[@]}"; do
launcher_script_to_test="wsagent/agent/src/main/resources/org.eclipse.che.ws-agent.script.sh"
bats_test_script="agents/che-core-api-agent/src/test/resources/agents-launchers-tests-arbitraryuser.bats"
echo "RUNNING LAUNCHER BATS TESTS FOR IMAGE ${arbitrary_image}"
run_bats_test "${bats_test_script}" "${launcher_script_to_test}" "${arbitrary_image}"
done

View File

@ -9,8 +9,21 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
CURL_INSTALLED=false
WGET_INSTALLED=false
@ -23,8 +36,6 @@ if [ ${CURL_INSTALLED} = false ] && [ ${WGET_INSTALLED} = false ]; then
CURL_INSTALLED=true
fi
test "$(id -u)" = 0 || SUDO="sudo -E"
CHE_DIR=$HOME/che
LOCAL_AGENT_BINARIES_URI='/mnt/che/exec-agent/exec-agent-${PREFIX}.tar.gz'
DOWNLOAD_AGENT_BINARIES_URI='${WORKSPACE_MASTER_URI}/agent-binaries/${PREFIX}/exec/exec-agent-${PREFIX}.tar.gz'

View File

@ -9,11 +9,22 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
test "$(id -u)" = 0 || SUDO="sudo -E"
AGENT_BINARIES_URI=https://codenvy.com/update/repository/public/download/org.eclipse.che.ls.csharp.binaries
CHE_DIR=$HOME/che

View File

@ -9,11 +9,22 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
test "$(id -u)" = 0 || SUDO="sudo -E"
AGENT_BINARIES_URI=https://codenvy.com/update/repository/public/download/org.eclipse.che.ls.json.binaries
CHE_DIR=$HOME/che

View File

@ -9,11 +9,22 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
test "$(id -u)" = 0 || SUDO="sudo -E"
AGENT_BINARIES_URI=https://codenvy.com/update/repository/public/download/org.eclipse.che.ls.php.binaries
CHE_DIR=$HOME/che

View File

@ -9,16 +9,26 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
unset PYTHON_DEPS
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
command -v python3.5 >/dev/null 2>&1 || { PYTHON_DEPS=${PYTHON_DEPS}" python3.5"; }
command -v pip3 >/dev/null 2>&1 || { PYTHON_DEPS=${PYTHON_DEPS}" pip3"; }
test "$(id -u)" = 0 || SUDO="sudo -E"
AGENT_BINARIES_URI=https://codenvy.com/update/repository/public/download/org.eclipse.che.ls.python.binaries
CHE_DIR=$HOME/che
LS_DIR=${CHE_DIR}/ls-python

View File

@ -9,11 +9,22 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
test "$(id -u)" = 0 || SUDO="sudo -E"
AGENT_BINARIES_URI=https://codenvy.com/update/repository/public/download/org.eclipse.che.ls.typescript.binaries
CHE_DIR=$HOME/che

View File

@ -9,9 +9,20 @@
# Codenvy, S.A. - initial API and implementation
#
unset SUDO
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
test "$(id -u)" = 0 || SUDO="sudo -E"
if [ -f /etc/centos-release ]; then
FILE="/etc/centos-release"

View File

@ -9,8 +9,20 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
CURL_INSTALLED=false
WGET_INSTALLED=false
@ -23,8 +35,6 @@ if [ ${CURL_INSTALLED} = false ] && [ ${WGET_INSTALLED} = false ]; then
CURL_INSTALLED=true
fi
test "$(id -u)" = 0 || SUDO="sudo -E"
CHE_DIR=$HOME/che
LOCAL_AGENT_BINARIES_URI='/mnt/che/terminal/websocket-terminal-${PREFIX}.tar.gz'
DOWNLOAD_AGENT_BINARIES_URI='${WORKSPACE_MASTER_URI}/agent-binaries/${PREFIX}/terminal/websocket-terminal-${PREFIX}.tar.gz'

View File

@ -9,9 +9,20 @@
# Codenvy, S.A. - initial API and implementation
#
unset SUDO
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
test "$(id -u)" = 0 || SUDO="sudo -E"
if [ -f /etc/centos-release ]; then
FILE="/etc/centos-release"

View File

@ -191,10 +191,18 @@
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-ide</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-junit-ide</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-phpunit-ide</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-testng-ide</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-web-ext-web</artifactId>

View File

@ -2422,6 +2422,7 @@
"machines": {
"dev-machine": {
"installers": [
"org.eclipse.che.exec",
"org.eclipse.che.terminal",
"org.eclipse.che.ws-agent",
"org.eclipse.che.ssh"

View File

@ -86,10 +86,6 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>

View File

@ -21,6 +21,10 @@
<artifactId>che-plugin-testing-classpath</artifactId>
<name>Che Plugin :: Java Testing :: Classpath</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>

View File

@ -12,6 +12,7 @@ package org.eclipse.che.plugin.java.testing;
import org.eclipse.che.api.testing.server.framework.TestRunner;
import org.eclipse.che.api.testing.shared.TestDetectionContext;
import org.eclipse.che.api.testing.shared.TestExecutionContext;
import org.eclipse.che.api.testing.shared.TestPosition;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.core.resources.IProject;
@ -37,6 +38,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import static java.util.Collections.emptyList;
/**
* Abstract java test runner.
* Can recognize test methods, find java project and compilation unit by path.
@ -48,10 +51,12 @@ public abstract class AbstractJavaTestRunner implements TestRunner {
protected static final String JAVA_EXECUTABLE = "java";
private int debugPort = -1;
private String workspacePath;
private String workspacePath;
private JavaTestFinder javaTestFinder;
public AbstractJavaTestRunner(String workspacePath) {
public AbstractJavaTestRunner(String workspacePath, JavaTestFinder javaTestFinder) {
this.workspacePath = workspacePath;
this.javaTestFinder = javaTestFinder;
}
@Override
@ -105,8 +110,18 @@ public abstract class AbstractJavaTestRunner implements TestRunner {
.withTestBodyLength(sourceRange.getLength());
}
/**
* Verify if the method is test method.
*
* @param method
* method declaration
* @param compilationUnit
* compilation unit of the method
* @return {@code true} if the method is test method otherwise returns {@code false}
*/
protected abstract boolean isTestMethod(IMethod method, ICompilationUnit compilationUnit);
/** Returns {@link IJavaProject} by path */
protected IJavaProject getJavaProject(String projectPath) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectPath);
return JavaModelManager.getJavaModelManager().getJavaModel().getJavaProject(project);
@ -131,7 +146,7 @@ public abstract class AbstractJavaTestRunner implements TestRunner {
return path;
}
protected ICompilationUnit findCompilationUnitByPath(IJavaProject javaProject, String filePath) {
private ICompilationUnit findCompilationUnitByPath(IJavaProject javaProject, String filePath) {
try {
IClasspathEntry[] resolvedClasspath = javaProject.getResolvedClasspath(false);
IPath packageRootPath = null;
@ -163,6 +178,44 @@ public abstract class AbstractJavaTestRunner implements TestRunner {
}
}
/**
* Creates test suite which should be ran.
*
* @param context
* information about test runner
* @param javaProject
* current project
* @param methodAnnotation
* java annotation which describes test method in the test framework
* @param classAnnotation
* java annotation which describes test class in the test framework
* @return list of full qualified names of test classes.
* If it is the declaration of a test method it should be: parent fqn + '#' + method name (a.b.c.ClassName#methodName)
*/
protected List<String> createTestSuite(TestExecutionContext context,
IJavaProject javaProject,
String methodAnnotation,
String classAnnotation) {
switch (context.getContextType()) {
case FILE:
return javaTestFinder.findTestClassDeclaration(findCompilationUnitByPath(javaProject, context.getFilePath()));
case FOLDER:
return javaTestFinder.findClassesInPackage(javaProject,
context.getFilePath(),
methodAnnotation,
classAnnotation);
case PROJECT:
return javaTestFinder.findClassesInProject(javaProject,
methodAnnotation,
classAnnotation);
case CURSOR_POSITION:
return javaTestFinder.findTestMethodDeclaration(findCompilationUnitByPath(javaProject, context.getFilePath()),
context.getCursorOffset());
}
return emptyList();
}
@Override
public int getDebugPort() {
return debugPort;

View File

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.java.testing;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchRequestor;
import java.util.Collection;
/**
* Request for searching test classes.
*/
public class AnnotationSearchRequestor extends SearchRequestor {
private final Collection<IType> fResult;
private final ITypeHierarchy fHierarchy;
AnnotationSearchRequestor(ITypeHierarchy hierarchy, Collection<IType> result) {
fHierarchy = hierarchy;
fResult = result;
}
@Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
if (match.getAccuracy() == SearchMatch.A_ACCURATE && !match.isInsideDocComment()) {
Object element = match.getElement();
if (element instanceof IType || element instanceof IMethod) {
IMember member = (IMember)element;
IType type = member.getElementType() == IJavaElement.TYPE ? (IType)member : member.getDeclaringType();
addTypeAndSubtypes(type);
}
}
}
private void addTypeAndSubtypes(IType type) {
if (fResult.add(type)) {
IType[] subclasses = fHierarchy.getSubclasses(type);
for (IType subclass : subclasses) {
addTypeAndSubtypes(subclass);
}
}
}
}

View File

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.java.testing;
import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
/**
* Describes annotations for JUnit4x an TestNG.
*/
public class JavaTestAnnotations {
public static final JavaTestAnnotations TESTNG_TEST = new JavaTestAnnotations("org.testng.annotations.Test");
public static final JavaTestAnnotations JUNIT4X_RUN_WITH = new JavaTestAnnotations("org.junit.runner.RunWith");
public static final JavaTestAnnotations JUNIT4X_TEST = new JavaTestAnnotations("org.junit.Test");
private final String fName;
private JavaTestAnnotations(String name) {
fName = name;
}
/**
* Returns name of the annotation.
*
* @return name of the annotation
*/
public String getName() {
return fName;
}
private boolean annotates(IAnnotationBinding[] annotations) {
for (IAnnotationBinding annotation : annotations) {
ITypeBinding annotationType = annotation.getAnnotationType();
if (annotationType != null && (annotationType.getQualifiedName().equals(fName))) {
return true;
}
}
return false;
}
/**
* Check if type annotated as test type.
*
* @param type
* type which should be checked
* @return {@code true} if type annotated as test otherwise returns {@code false}
*/
public boolean annotatesTypeOrSuperTypes(ITypeBinding type) {
while (type != null) {
if (annotates(type.getAnnotations())) {
return true;
}
type= type.getSuperclass();
}
return false;
}
/**
* Find method which annotated as test method.
*
* @param type
* type which contains methods
* @return {@code true} if least one has test annotation otherwise returns {@code false}
*/
public boolean annotatesAtLeastOneMethod(ITypeBinding type) {
while (type != null) {
IMethodBinding[] declaredMethods= type.getDeclaredMethods();
for (int i= 0; i < declaredMethods.length; i++) {
IMethodBinding curr= declaredMethods[i];
if (annotates(curr.getAnnotations())) {
return true;
}
}
type= type.getSuperclass();
}
return false;
}
}

View File

@ -0,0 +1,271 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.java.testing;
import com.google.inject.Singleton;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IRegion;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
/**
* Class which finds test classes and test methods for java test frameworks.
*/
@Singleton
public class JavaTestFinder {
private static final Logger LOG = LoggerFactory.getLogger(JavaTestFinder.class);
/**
* Finds test method related to the cursor position.
*
* @param compilationUnit
* compilation unit of class
* @param cursorOffset
* cursor position
* @return declaration of test method which should be ran. (Example: full.qualified.name.of.Class#methodName)
*/
public List<String> findTestMethodDeclaration(ICompilationUnit compilationUnit,
int cursorOffset) {
IType primaryType = compilationUnit.findPrimaryType();
String qualifiedName = primaryType.getFullyQualifiedName();
try {
IJavaElement element = compilationUnit.getElementAt(cursorOffset);
if (element instanceof IMethod) {
IMethod method = (IMethod)element;
qualifiedName = qualifiedName + '#' + method.getElementName();
}
} catch (JavaModelException e) {
LOG.debug("Can't read a method.", e);
}
return singletonList(qualifiedName);
}
/**
* Finds test class declaration.
*
* @param compilationUnit
* compilation unit of class
* @return declaration of test class which should be ran.
*/
public List<String> findTestClassDeclaration(ICompilationUnit compilationUnit) {
IType primaryType = compilationUnit.findPrimaryType();
return singletonList(primaryType.getFullyQualifiedName());
}
/**
* Finds test classes in package.
*
* @param javaProject
* java project
* @param packagePath
* package path
* @param testMethodAnnotation
* java annotation which describes test method in the test framework
* @param testClassAnnotation
* java annotation which describes test class in the test framework
* @return list of test classes which should be ran.
*/
public List<String> findClassesInPackage(IJavaProject javaProject,
String packagePath,
String testMethodAnnotation,
String testClassAnnotation) {
IPackageFragment packageFragment = null;
try {
packageFragment = javaProject.findPackageFragment(new Path(packagePath));
} catch (JavaModelException e) {
LOG.info("Can't find package.", e);
}
return packageFragment == null ? emptyList() : findClassesInContainer(packageFragment, testMethodAnnotation, testClassAnnotation);
}
/**
* Finds test classes in project.
*
* @param project
* java project
* @param testMethodAnnotation
* java annotation which describes test method in the test framework
* @param testClassAnnotation
* java annotation which describes test class in the test framework
* @return list of test classes which should be ran.
*/
public List<String> findClassesInProject(IJavaProject project, String testMethodAnnotation, String testClassAnnotation) {
return findClassesInContainer(project, testMethodAnnotation, testClassAnnotation);
}
/**
* Check if a method is test method.
*
* @param method
* method which should be checked
* @param compilationUnit
* parent of the method
* @param testAnnotation
* java annotation which describes test method in the test framework
* @return {@code true} if the method is test method
*/
public boolean isTest(IMethod method, ICompilationUnit compilationUnit, String testAnnotation) {
try {
IAnnotation[] annotations = method.getAnnotations();
IAnnotation test = null;
for (IAnnotation annotation : annotations) {
String annotationElementName = annotation.getElementName();
if ("Test".equals(annotationElementName)) {
test = annotation;
break;
}
if (testAnnotation.equals(annotationElementName)) {
return true;
}
}
return test != null && isImportOfTestAnnotationExist(compilationUnit, testAnnotation);
} catch (JavaModelException e) {
LOG.info("Can't read method's annotations.", e);
return false;
}
}
private boolean isImportOfTestAnnotationExist(ICompilationUnit compilationUnit, String testAnnotation) {
try {
IImportDeclaration[] imports = compilationUnit.getImports();
for (IImportDeclaration importDeclaration : imports) {
String elementName = importDeclaration.getElementName();
if (testAnnotation.equals(elementName)) {
return true;
}
if (importDeclaration.isOnDemand() &&
testAnnotation.startsWith(elementName.substring(0, elementName.length() - 3))) { //remove .*
return true;
}
}
} catch (JavaModelException e) {
LOG.info("Can't read class imports.", e);
return false;
}
return false;
}
private List<String> findClassesInContainer(IJavaElement container, String testMethodAnnotation, String testClassAnnotation) {
List<String> result = new LinkedList<>();
IRegion region = getRegion(container);
try {
ITypeHierarchy hierarchy = JavaCore.newTypeHierarchy(region, null, null);
IType[] allClasses = hierarchy.getAllClasses();
// search for all types with references to RunWith and Test and all subclasses
HashSet<IType> candidates = new HashSet<>(allClasses.length);
SearchRequestor requestor = new AnnotationSearchRequestor(hierarchy, candidates);
IJavaSearchScope scope = SearchEngine.createJavaSearchScope(allClasses, IJavaSearchScope.SOURCES);
int matchRule = SearchPattern.R_CASE_SENSITIVE;
SearchPattern testPattern = SearchPattern.createPattern(testMethodAnnotation,
IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
matchRule);
SearchPattern runWithPattern = isNullOrEmpty(testClassAnnotation)
? testPattern
: SearchPattern.createPattern(testClassAnnotation,
IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
matchRule);
SearchPattern annotationsPattern = SearchPattern.createOrPattern(runWithPattern, testPattern);
SearchParticipant[] searchParticipants = new SearchParticipant[]{SearchEngine.getDefaultSearchParticipant()};
new SearchEngine().search(annotationsPattern, searchParticipants, scope, requestor, null);
// find all classes in the region
for (IType candidate : candidates) {
if (isAccessibleClass(candidate) && !Flags.isAbstract(candidate.getFlags()) && region.contains(candidate)) {
result.add(candidate.getFullyQualifiedName());
}
}
} catch (
CoreException e)
{
LOG.info("Can't build project hierarchy.", e);
}
return result;
}
private IRegion getRegion(IJavaElement element) {
IRegion result = JavaCore.newRegion();
if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
//for projects only add the contained source folders
try {
IPackageFragmentRoot[] packageFragmentRoots = ((IJavaProject)element).getPackageFragmentRoots();
for (IPackageFragmentRoot packageFragmentRoot : packageFragmentRoots) {
if (!packageFragmentRoot.isArchive()) {
result.add(packageFragmentRoot);
}
}
} catch (JavaModelException e) {
LOG.info("Can't read source folders.", e);
}
} else {
result.add(element);
}
return result;
}
private static boolean isAccessibleClass(IType type) throws JavaModelException {
int flags = type.getFlags();
if (Flags.isInterface(flags)) {
return false;
}
IJavaElement parent = type.getParent();
while (true) {
if (parent instanceof ICompilationUnit || parent instanceof IClassFile) {
return true;
}
if (!(parent instanceof IType) || !Flags.isStatic(flags) || !Flags.isPublic(flags)) {
return false;
}
flags = ((IType)parent).getFlags();
parent = parent.getParent();
}
}
}

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-testing-junit</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.16.0-SNAPSHOT</version>
</parent>
<artifactId>che-plugin-testing-junit-ide</artifactId>
<name>Che Plugin :: Java Testing :: JUnit IDE</name>
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-gwt</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-ide-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-ide</artifactId>
</dependency>
<dependency>
<groupId>org.vectomatic</groupId>
<artifactId>lib-gwt-svg</artifactId>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt.inject</groupId>
<artifactId>gin</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide;
import com.google.inject.Inject;
import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionManager;
import org.eclipse.che.ide.api.action.DefaultActionGroup;
import org.eclipse.che.plugin.testing.ide.TestAction;
import org.eclipse.che.plugin.testing.junit.ide.action.DebugJUnitTestAction;
import org.eclipse.che.plugin.testing.junit.ide.action.RunJUnitTestAction;
/**
* Registrar of JUnit run/debug actions.
*/
public class JUnitTestAction implements TestAction {
public static final String TEST_ACTION_RUN = "TestJUnitActionRun";
public static final String TEST_ACTION_DEBUG = "TestJUnitActionDebug";
private final Action runTestAction;
private final Action debugTestAction;
@Inject
public JUnitTestAction(ActionManager actionManager,
RunJUnitTestAction runJUnitTestAction,
DebugJUnitTestAction debugJUnitTestAction) {
actionManager.registerAction(TEST_ACTION_RUN, runJUnitTestAction);
actionManager.registerAction(TEST_ACTION_DEBUG, debugJUnitTestAction);
this.runTestAction = runJUnitTestAction;
this.debugTestAction = debugJUnitTestAction;
}
@Override
public void addMainMenuItems(DefaultActionGroup testMainMenu) {
testMainMenu.add(runTestAction);
testMainMenu.add(debugTestAction);
}
@Override
public void addContextMenuItems(DefaultActionGroup testContextMenu) {
testContextMenu.add(runTestAction);
testContextMenu.add(debugTestAction);
}
}

View File

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide;
import com.google.gwt.i18n.client.Messages;
/**
* Localization constants. Interface to represent the constants defined in resource bundle:
* 'JUnitTestLocalizationConstant.properties'.
*/
public interface JUnitTestLocalizationConstant extends Messages {
@Key("action.run.title")
String actionRunTestTitle();
@Key("action.run.description")
String actionRunTestDescription();
@Key("action.debug.title")
String actionDebugTestTitle();
@Key("action.debug.description")
String actionDebugDescription();
}

View File

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide;
import com.google.gwt.resources.client.ClientBundle;
import org.vectomatic.dom.svg.ui.SVGResource;
/**
* Resource bundle for JUnit module.
*/
public interface JUnitTestResources extends ClientBundle {
@Source("org/eclipse/che/plugin/testing/junit/ide/svg/test.svg")
SVGResource testIcon();
}

View File

@ -0,0 +1,80 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide.action;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.action.RunDebugTestAbstractAction;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import org.eclipse.che.plugin.testing.junit.ide.JUnitTestLocalizationConstant;
import org.eclipse.che.plugin.testing.junit.ide.JUnitTestResources;
import javax.validation.constraints.NotNull;
import static java.util.Collections.singletonList;
import static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID;
/**
* The action for activation debugger for JUnit test.
*/
public class DebugJUnitTestAction extends RunDebugTestAbstractAction {
@Inject
public DebugJUnitTestAction(JUnitTestResources resources,
EventBus eventBus,
TestServiceClient client,
TestingHandler testingHandler,
DtoFactory dtoFactory,
NotificationManager notificationManager,
DebugConfigurationsManager debugConfigurationsManager,
AppContext appContext,
TestResultPresenter testResultPresenter,
JUnitTestLocalizationConstant localization) {
super(eventBus,
testResultPresenter,
testingHandler,
debugConfigurationsManager,
client,
dtoFactory,
appContext,
notificationManager,
singletonList(PROJECT_PERSPECTIVE_ID),
localization.actionDebugDescription(),
localization.actionDebugTestTitle(),
resources.testIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
Pair<String, String> frameworkAndTestName = Pair.of(JUNIT_FRAMEWORK_NAME, null);
actionPerformed(frameworkAndTestName, true);
}
@Override
public void updateInPerspective(@NotNull ActionEvent e) {
Presentation presentation = e.getPresentation();
presentation.setVisible(!isEditorInFocus);
if (!isEditorInFocus) {
analyzeProjectTreeSelection();
}
presentation.setEnabled(isEnable);
}
}

View File

@ -0,0 +1,80 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide.action;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.action.RunDebugTestAbstractAction;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import org.eclipse.che.plugin.testing.junit.ide.JUnitTestLocalizationConstant;
import org.eclipse.che.plugin.testing.junit.ide.JUnitTestResources;
import javax.validation.constraints.NotNull;
import static java.util.Collections.singletonList;
import static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID;
/**
* The action for running JUnit test.
*/
public class RunJUnitTestAction extends RunDebugTestAbstractAction {
@Inject
public RunJUnitTestAction(JUnitTestResources resources,
EventBus eventBus,
TestingHandler testingHandler,
TestResultPresenter testResultPresenter,
DebugConfigurationsManager debugConfigurationsManager,
TestServiceClient client,
AppContext appContext,
DtoFactory dtoFactory,
NotificationManager notificationManager,
JUnitTestLocalizationConstant localization) {
super(eventBus,
testResultPresenter,
testingHandler,
debugConfigurationsManager,
client,
dtoFactory,
appContext,
notificationManager,
singletonList(PROJECT_PERSPECTIVE_ID),
localization.actionRunTestDescription(),
localization.actionRunTestTitle(),
resources.testIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
Pair<String, String> frameworkAndTestName = Pair.of(JUNIT_FRAMEWORK_NAME, null);
actionPerformed(frameworkAndTestName, false);
}
@Override
public void updateInPerspective(@NotNull ActionEvent e) {
Presentation presentation = e.getPresentation();
presentation.setVisible(!isEditorInFocus);
if (!isEditorInFocus) {
analyzeProjectTreeSelection();
}
presentation.setEnabled(isEnable);
}
}

View File

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.junit.ide.inject;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.gwt.inject.client.multibindings.GinMultibinder;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.plugin.testing.ide.TestAction;
import org.eclipse.che.plugin.testing.junit.ide.JUnitTestAction;
/**
* Gin module for JUnit extension.
*/
@ExtensionGinModule
public class JUnitGinModule extends AbstractGinModule {
@Override
protected void configure() {
GinMultibinder.newSetBinder(binder(), TestAction.class).addBinding().to(JUnitTestAction.class);
}
}

View File

@ -0,0 +1,21 @@
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<module>
<inherits name="com.google.gwt.user.User"/>
<inherits name="org.eclipse.che.ide.Api"/>
<inherits name="com.google.gwt.inject.Inject"/>
<inherits name="org.eclipse.che.ide.ui.CodenvyUI"/>
<inherits name="org.eclipse.che.plugin.testing.TestingExtension"/>
<source path="ide"/>
</module>

View File

@ -0,0 +1,20 @@
#
# Copyright (c) 2012-2017 Codenvy, S.A.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Codenvy, S.A. - initial API and implementation
#
##### Actions #####
action.run.title = Run JUnit Test
action.run.description = Run JUnit tests
action.debug.title = Debug JUnit Test
action.debug.description = Debug JUnit tests

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
<path d="M29.884 25.14l-9.884-16.47v-6.671h1c0.55 0 1-0.45 1-1s-0.45-1-1-1h-10c-0.55 0-1 0.45-1 1s0.45 1 1 1h1v6.671l-9.884 16.47c-2.264 3.773-0.516 6.86 3.884 6.86h20c4.4 0 6.148-3.087 3.884-6.86zM7.532 20l6.468-10.779v-7.221h4v7.221l6.468 10.779h-16.935z"></path>
</svg>

After

Width:  |  Height:  |  Size: 960 B

View File

@ -60,13 +60,9 @@ public class TestingMessageHelper {
*
* @param out
* output stream
* @param description
* information about test cass
*/
public static void rootPresentation(PrintStream out, Description description) {
out.println(create(ROOT_NAME,
new Pair(NAME, "Default Suite"),
new Pair(LOCATION, "file://" + description.getClassName())));
public static void rootPresentation(PrintStream out) {
out.println(create(ROOT_NAME, new Pair(NAME, "Default Suite")));
}
/**
@ -150,7 +146,7 @@ public class TestingMessageHelper {
public static void testSuiteStarted(PrintStream out, Description description) {
out.println(create(TEST_SUITE_STARTED,
new Pair(NAME, escape(description.getClassName())),
new Pair(LOCATION, escape(description.getClassName()))));
new Pair(LOCATION, "java:test://" + escape(description.getClassName()))));
}
/**

View File

@ -13,10 +13,12 @@ package org.eclipse.che.junit.junit4;
import org.eclipse.che.junit.TestingMessageHelper;
import org.eclipse.che.junit.junit4.listeners.CheJUnitTestListener;
import org.eclipse.che.junit.junit4.listeners.JUnitExecutionListener;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.Result;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import java.util.List;
/**
* Custom JUnit4 runner that reports results visa {@link CheJUnitTestListener}.
@ -33,28 +35,37 @@ public class CheJUnitCoreRunner extends JUnitCore {
* (for example full.qualified.ClassName#methodName)
*/
public void run(String[] suites) {
Request request = TestRunnerUtil.buildRequest(suites);
if (request == null) {
createListener();
List<JUnit4TestReference> newSuites = TestRunnerUtil.createTestReferences(suites);
if (newSuites.isEmpty()) {
TestingMessageHelper.reporterAttached(System.out);
System.err.print("No test found to run.");
} else {
Runner runner = request.getRunner();
Description description = runner.getDescription();
if (cheJUnitTestListener != null) {
cheJUnitTestListener.suiteTreeStarted(description);
cheJUnitTestListener.suiteSendTree(description);
cheJUnitTestListener.suiteTreeEnded(description);
}
super.run(request);
return;
}
RunNotifier runNotifier = new RunNotifier();
runNotifier.addListener(new JUnitExecutionListener(cheJUnitTestListener));
cheJUnitTestListener.testRunStarted();
for (JUnit4TestReference jUnit4TestReference : newSuites) {
jUnit4TestReference.sendTree(cheJUnitTestListener);
}
Result result = new Result();
final RunListener listener = result.createListener();
runNotifier.addListener(listener);
for (JUnit4TestReference testReference : newSuites) {
testReference.run(runNotifier);
}
runNotifier.fireTestRunFinished(result);
}
/**
* Creates custom listener {@link CheJUnitTestListener} and adds it to
*/
public void createListener() {
private void createListener() {
cheJUnitTestListener = new CheJUnitTestListener();
this.addListener(new JUnitExecutionListener(cheJUnitTestListener));
}

View File

@ -23,12 +23,11 @@ public class CheJUnitLauncher {
* arrays of tests to be executed
*/
public static void main(String[] args) {
CheJUnitCoreRunner jUnitCore = new CheJUnitCoreRunner();
jUnitCore.createListener();
if (args.length == 0) {
TestingMessageHelper.reporterAttached(System.out);
System.err.print("No test found to run.");
} else {
CheJUnitCoreRunner jUnitCore = new CheJUnitCoreRunner();
jUnitCore.run(args);
}
}

View File

@ -0,0 +1,95 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.junit.junit4;
import org.eclipse.che.junit.junit4.listeners.CheJUnitTestListener;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
/**
* Describes request of the test runner.
*/
public class JUnit4TestReference {
private final Runner runner;
private final Description description;
public JUnit4TestReference(Runner runner, Description root) {
this.runner = runner;
description = root;
}
/** Returns count of the test methods. */
public int countTestCases() {
return countTestCases(description);
}
/** Returns a {@link Runner} for this Request */
public Runner getRunner() {
return runner;
}
/** @return a {@link Description} showing the tests to be run by the receiver. */
public Description getDescription() {
return description;
}
/**
* Run the tests for this runner.
*
* @param runNotifier
* will be notified of events while tests are being run--tests being
* started, finishing, and failing
*/
public void run(RunNotifier runNotifier) {
runner.run(runNotifier);
}
/** Sends tree structure of the current test. */
public void sendTree(CheJUnitTestListener listener) {
if(description.isTest())
listener.suiteTreeStarted(description);
listener.suiteSendTree(description);
listener.suiteTreeEnded(description);
}
@Override
public String toString() {
return description.toString();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof JUnit4TestReference))
return false;
JUnit4TestReference ref = (JUnit4TestReference)obj;
return (ref.description.equals(description));
}
@Override
public int hashCode() {
return description.hashCode();
}
private int countTestCases(Description description) {
if (description.isTest()) {
return 1;
} else {
int result = 0;
for (Description child : description.getChildren()) {
result += countTestCases(child);
}
return result;
}
}
}

View File

@ -11,66 +11,76 @@
package org.eclipse.che.junit.junit4;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import java.util.LinkedList;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
/**
* Utility class for building test executing request.
*/
public class TestRunnerUtil {
/**
* Creates a request which contains all tests to be executed.
* Build list of {@clink JUnit4TestReference}.
*
* @param args
* array of test classes or test method (if args.length == 1) to be executed
* @return an abstract description of tests to be run
* @param suites
* array of test classes or test method (if args.length == 1) to execute
* @return list of {@link JUnit4TestReference}
*/
public static Request buildRequest(String[] args) {
if (args.length == 0) {
return null;
}
if (args.length == 1) {
String suite = args[0];
public static List<JUnit4TestReference> createTestReferences(String[] suites) {
if (suites.length == 0) {
return emptyList();
} else if (suites.length == 1) {
String suite = suites[0];
int separatorIndex = suite.indexOf('#');
return separatorIndex == -1 ? getRequestForClass(suite) : getRequestForOneMethod(suite, separatorIndex);
}
return getRequestForClasses(args);
return getRequestForClasses(suites);
}
private static Request getRequestForOneMethod(String suite, int separatorIndex) {
private static List<JUnit4TestReference> getRequestForOneMethod(String suite, int separatorIndex) {
try {
Class suiteClass = Class.forName(suite.substring(0, separatorIndex));
String method = suite.substring(separatorIndex + 1);
return Request.method(suiteClass, method);
Request request = Request.method(suiteClass, method);
Runner runner = request.getRunner();
return singletonList(new JUnit4TestReference(runner, runner.getDescription()));
} catch (ClassNotFoundException e) {
System.err.print("No test found to run. Args is 0");
return null;
System.err.print("No test found to run.");
return emptyList();
}
}
private static Request getRequestForClass(String suite) {
private static List<JUnit4TestReference> getRequestForClass(String suite) {
try {
return Request.aClass(Class.forName(suite));
Request request = Request.aClass(Class.forName(suite));
Runner runner = request.getRunner();
return singletonList(new JUnit4TestReference(runner, runner.getDescription()));
} catch (ClassNotFoundException e) {
System.err.print("No test found to run. Args is 0");
return null;
System.err.print("No test found to run.");
return emptyList();
}
}
private static Request getRequestForClasses(String[] args) {
List<Class<?>> suites = new LinkedList<>();
private static List<JUnit4TestReference> getRequestForClasses(String[] args) {
List<JUnit4TestReference> suites = new LinkedList<>();
for (String classFqn : args) {
try {
Class<?> aClass = Class.forName(classFqn);
suites.add(aClass);
Request request = Request.aClass(aClass);
Runner runner = request.getRunner();
suites.add(new JUnit4TestReference(runner, runner.getDescription()));
} catch (ClassNotFoundException ignored) {
}
}
if (suites.isEmpty()) {
return null;
System.err.print("No test found to run.");
return emptyList();
}
return Request.classes(suites.toArray(new Class[suites.size()]));
return suites;
}
}

View File

@ -32,12 +32,9 @@ public class CheJUnitTestListener {
/**
* Called before any tests have been run.
*
* @param description
* describes the tests to be run
*/
public void testRunStarted(Description description) {
TestingMessageHelper.rootPresentation(out, description);
public void testRunStarted() {
TestingMessageHelper.rootPresentation(out);
}
/**
@ -129,9 +126,11 @@ public class CheJUnitTestListener {
if (description.isTest()) {
TestingMessageHelper.treeNode(out, description);
} else {
suiteTreeStarted(description);
for (Description child : description.getChildren()) {
suiteSendTree(child);
}
suiteTreeEnded(description);
}
}

View File

@ -31,7 +31,7 @@ public class JUnitExecutionListener extends RunListener {
@Override
public void testRunStarted(Description description) throws Exception {
delegate.testRunStarted(description);
delegate.testRunStarted();
}
@Override

View File

@ -20,19 +20,17 @@ import org.eclipse.che.commons.lang.execution.CommandLine;
import org.eclipse.che.commons.lang.execution.ExecutionException;
import org.eclipse.che.commons.lang.execution.JavaParameters;
import org.eclipse.che.commons.lang.execution.ProcessHandler;
import org.eclipse.che.junit.junit4.CheJUnitCoreRunner;
import org.eclipse.che.plugin.java.testing.AbstractJavaTestRunner;
import org.eclipse.che.plugin.java.testing.ClasspathUtil;
import org.eclipse.che.plugin.java.testing.JavaTestAnnotations;
import org.eclipse.che.plugin.java.testing.JavaTestFinder;
import org.eclipse.che.plugin.java.testing.ProjectClasspathProvider;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.che.junit.junit4.CheJUnitCoreRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -48,18 +46,20 @@ import java.util.Set;
public class JUnit4TestRunner extends AbstractJavaTestRunner {
private static final Logger LOG = LoggerFactory.getLogger(JUnit4TestRunner.class);
private static final String JUNIT_TEST_ANNOTATION = "org.junit.Test";
private static final String JUNIT_TEST_NAME = "junit";
private static final String MAIN_CLASS_NAME = "org.eclipse.che.junit.junit4.CheJUnitLauncher";
private static final String JUNIT_TEST_NAME = "junit";
private static final String MAIN_CLASS_NAME = "org.eclipse.che.junit.junit4.CheJUnitLauncher";
private String workspacePath;
private JavaTestFinder javaTestFinder;
private ProjectClasspathProvider classpathProvider;
@Inject
public JUnit4TestRunner(@Named("che.user.workspaces.storage") String workspacePath,
JavaTestFinder javaTestFinder,
ProjectClasspathProvider classpathProvider) {
super(workspacePath);
super(workspacePath, javaTestFinder);
this.workspacePath = workspacePath;
this.javaTestFinder = javaTestFinder;
this.classpathProvider = classpathProvider;
}
@ -82,15 +82,14 @@ public class JUnit4TestRunner extends AbstractJavaTestRunner {
public boolean isTestMethod(IMethod method, ICompilationUnit compilationUnit) {
try {
int flags = method.getFlags();
if (method.isConstructor() ||
!Flags.isPublic(flags) ||
Flags.isAbstract(flags) ||
Flags.isStatic(flags) ||
!"V".equals(method.getReturnType())) { // 'V' is void signature
return false;
}
// 'V' is void signature
return !(method.isConstructor() ||
!Flags.isPublic(flags) ||
Flags.isAbstract(flags) ||
Flags.isStatic(flags) ||
!"V".equals(method.getReturnType()))
&& javaTestFinder.isTest(method, compilationUnit, JavaTestAnnotations.JUNIT4X_TEST.getName());
return isTest(method, compilationUnit);
} catch (JavaModelException ignored) {
return false;
}
@ -108,8 +107,13 @@ public class JUnit4TestRunner extends AbstractJavaTestRunner {
classPath.add(ClasspathUtil.getJarPathForClass(CheJUnitCoreRunner.class));
parameters.getClassPath().addAll(classPath);
String suite = createTestSuite(context, javaProject);
parameters.getParametersList().add(suite);
List<String> suite = createTestSuite(context,
javaProject,
JavaTestAnnotations.JUNIT4X_TEST.getName(),
JavaTestAnnotations.JUNIT4X_RUN_WITH.getName());
for (String element : suite) {
parameters.getParametersList().add(element);
}
if (context.isDebugModeEnable()) {
generateDebuggerPort();
parameters.getVmParameters().add("-Xdebug");
@ -125,94 +129,6 @@ public class JUnit4TestRunner extends AbstractJavaTestRunner {
return null;
}
private String createTestSuite(TestExecutionContext context, IJavaProject javaProject) {
switch (context.getTestType()) {
case FILE:
return createClassRequest(javaProject, context.getFilePath());
case FOLDER:
return createPackageRequest(javaProject, context.getFilePath());
case PROJECT:
return createProjectRequest(javaProject);
case CURSOR_POSITION:
return createMethodRequest(javaProject, context.getFilePath(), context.getCursorOffset());
}
return null;
}
private String createMethodRequest(IJavaProject javaProject, String filePath, int cursorOffset) {
ICompilationUnit compilationUnit = findCompilationUnitByPath(javaProject, filePath);
IType primaryType = compilationUnit.findPrimaryType();
String qualifiedName = primaryType.getFullyQualifiedName();
try {
IJavaElement element = compilationUnit.getElementAt(cursorOffset);
if (element instanceof IMethod) {
IMethod method = (IMethod)element;
qualifiedName = qualifiedName + '#' + method.getElementName();
}
} catch (JavaModelException e) {
LOG.debug("Can't read a method.", e);
}
return qualifiedName;
}
private String createProjectRequest(IJavaProject javaProject) {
//TODO add suite to run all tests from the project
return null;
}
private String createPackageRequest(IJavaProject javaProject, String filePath) {
//TODO add suite to run all tests from the package
return null;
}
private String createClassRequest(IJavaProject javaProject, String filePath) {
ICompilationUnit compilationUnit = findCompilationUnitByPath(javaProject, filePath);
IType primaryType = compilationUnit.findPrimaryType();
return primaryType.getFullyQualifiedName();
}
private boolean isTest(IMethod method, ICompilationUnit compilationUnit) {
try {
IAnnotation[] annotations = method.getAnnotations();
IAnnotation test = null;
for (IAnnotation annotation : annotations) {
String annotationElementName = annotation.getElementName();
if ("Test".equals(annotationElementName)) {
test = annotation;
break;
}
if (JUNIT_TEST_ANNOTATION.equals(annotationElementName)) {
return true;
}
}
return test != null && isImportOfTestAnnotationExist(compilationUnit);
} catch (JavaModelException e) {
LOG.info("Can't read method's annotations.", e);
return false;
}
}
private boolean isImportOfTestAnnotationExist(ICompilationUnit compilationUnit) {
try {
IImportDeclaration[] imports = compilationUnit.getImports();
for (IImportDeclaration importDeclaration : imports) {
String elementName = importDeclaration.getElementName();
if (JUNIT_TEST_ANNOTATION.equals(elementName)) {
return true;
}
if (importDeclaration.isOnDemand() &&
JUNIT_TEST_ANNOTATION.startsWith(elementName.substring(0, elementName.length() - 3))) { //remove .*
return true;
}
}
} catch (JavaModelException e) {
LOG.info("Can't read class imports.", e);
return false;
}
return false;
}
@Override
@Deprecated
public TestResult execute(Map<String, String> testParameters) throws Exception {

View File

@ -22,6 +22,7 @@
<packaging>pom</packaging>
<name>Che Plugin :: Java Testing :: JUnit Parent</name>
<modules>
<module>che-plugin-testing-junit-ide</module>
<module>che-plugin-testing-junit-server</module>
<module>che-plugin-testing-junit-runtime</module>
</modules>

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-testing-testng</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.16.0-SNAPSHOT</version>
</parent>
<artifactId>che-plugin-testing-testng-ide</artifactId>
<name>Che Plugin :: Java Testing :: TestNG IDE</name>
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-gwt</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-ide-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-ide</artifactId>
</dependency>
<dependency>
<groupId>org.vectomatic</groupId>
<artifactId>lib-gwt-svg</artifactId>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt.inject</groupId>
<artifactId>gin</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.testng.ide;
import com.google.gwt.i18n.client.Messages;
/**
* Localization constants. Interface to represent the constants defined in resource bundle:
* 'TestNgTestLocalizationConstant.properties'.
*/
public interface TestNgLocalizationConstant extends Messages {
@Key("action.testNg.run.title")
String actionRunTestTitle();
@Key("action.testNg.run.description")
String actionRunTestDescription();
@Key("action.testNg.debug.title")
String actionDebugTestTitle();
@Key("action.testNg.debug.description")
String actionDebugDescription();
}

View File

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.testng.ide;
import com.google.gwt.resources.client.ClientBundle;
import org.vectomatic.dom.svg.ui.SVGResource;
/**
* Resource bundle for TestNg extension.
*/
public interface TestNgResources extends ClientBundle {
@Source("org/eclipse/che/plugin/testing/testng/ide/svg/test.svg")
SVGResource testIcon();
}

View File

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.testng.ide;
import com.google.inject.Inject;
import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionManager;
import org.eclipse.che.ide.api.action.DefaultActionGroup;
import org.eclipse.che.plugin.testing.ide.TestAction;
import org.eclipse.che.plugin.testing.testng.ide.action.DebugTestNgTestAction;
import org.eclipse.che.plugin.testing.testng.ide.action.RunTestNgTestAction;
/**
* Registrar for run/debug actions.
*/
public class TestNgTestAction implements TestAction {
public static final String TEST_ACTION_RUN = "TestNgActionRun";
public static final String TEST_ACTION_DEBUG = "TestNgActionDebug";
private final Action runTestAction;
private final Action debugTestAction;
@Inject
public TestNgTestAction(ActionManager actionManager,
RunTestNgTestAction runTestNgTestAction,
DebugTestNgTestAction debugTestNgTestAction) {
actionManager.registerAction(TEST_ACTION_RUN, runTestNgTestAction);
actionManager.registerAction(TEST_ACTION_DEBUG, debugTestNgTestAction);
this.runTestAction = runTestNgTestAction;
this.debugTestAction = debugTestNgTestAction;
}
@Override
public void addMainMenuItems(DefaultActionGroup testMainMenu) {
testMainMenu.add(runTestAction);
testMainMenu.add(debugTestAction);
}
@Override
public void addContextMenuItems(DefaultActionGroup testContextMenu) {
testContextMenu.add(runTestAction);
testContextMenu.add(debugTestAction);
}
}

View File

@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.testng.ide.action;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.action.RunDebugTestAbstractAction;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import org.eclipse.che.plugin.testing.testng.ide.TestNgLocalizationConstant;
import org.eclipse.che.plugin.testing.testng.ide.TestNgResources;
import javax.validation.constraints.NotNull;
import static java.util.Collections.singletonList;
import static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID;
/**
* Action for debugging TestNg test.
*/
public class DebugTestNgTestAction extends RunDebugTestAbstractAction {
@Inject
public DebugTestNgTestAction(TestNgResources resources,
EventBus eventBus,
TestServiceClient client,
TestingHandler testingHandler,
DtoFactory dtoFactory,
NotificationManager notificationManager,
DebugConfigurationsManager debugConfigurationsManager,
AppContext appContext,
TestResultPresenter testResultPresenter,
TestNgLocalizationConstant localization) {
super(eventBus,
testResultPresenter,
testingHandler,
debugConfigurationsManager,
client,
dtoFactory,
appContext,
notificationManager,
singletonList(PROJECT_PERSPECTIVE_ID),
localization.actionDebugDescription(),
localization.actionDebugTestTitle(),
resources.testIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
Pair<String, String> frameworkAndTestName = Pair.of(TESTNG_FRAMEWORK_NAME, null);
actionPerformed(frameworkAndTestName, true);
}
@Override
public void updateInPerspective(@NotNull ActionEvent e) {
Presentation presentation = e.getPresentation();
presentation.setVisible(!isEditorInFocus);
if (!isEditorInFocus) {
analyzeProjectTreeSelection();
}
presentation.setEnabled(isEnable);
}
}

View File

@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.testng.ide.action;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.action.RunDebugTestAbstractAction;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import org.eclipse.che.plugin.testing.testng.ide.TestNgLocalizationConstant;
import org.eclipse.che.plugin.testing.testng.ide.TestNgResources;
import javax.validation.constraints.NotNull;
import static java.util.Collections.singletonList;
import static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID;
/**
* Action for running TestNg test.
*/
public class RunTestNgTestAction extends RunDebugTestAbstractAction {
@Inject
public RunTestNgTestAction(TestNgResources resources,
EventBus eventBus,
DebugConfigurationsManager debugConfigurationsManager,
TestServiceClient client,
TestingHandler testingHandler,
DtoFactory dtoFactory,
NotificationManager notificationManager,
AppContext appContext,
TestResultPresenter testResultPresenter,
TestNgLocalizationConstant localization) {
super(eventBus,
testResultPresenter,
testingHandler,
debugConfigurationsManager,
client,
dtoFactory,
appContext,
notificationManager,
singletonList(PROJECT_PERSPECTIVE_ID),
localization.actionRunTestDescription(),
localization.actionRunTestTitle(),
resources.testIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
Pair<String, String> frameworkAndTestName = Pair.of(TESTNG_FRAMEWORK_NAME, null);
actionPerformed(frameworkAndTestName, false);
}
@Override
public void updateInPerspective(@NotNull ActionEvent e) {
Presentation presentation = e.getPresentation();
presentation.setVisible(!isEditorInFocus);
if (!isEditorInFocus) {
analyzeProjectTreeSelection();
}
presentation.setEnabled(isEnable);
}
}

View File

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.testng.ide.inject;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.gwt.inject.client.multibindings.GinMultibinder;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.plugin.testing.ide.TestAction;
import org.eclipse.che.plugin.testing.testng.ide.TestNgTestAction;
/**
* Gin module for TestNg extension.
*/
@ExtensionGinModule
public class TestNgGinModule extends AbstractGinModule {
@Override
protected void configure() {
GinMultibinder.newSetBinder(binder(), TestAction.class).addBinding().to(TestNgTestAction.class);
}
}

View File

@ -0,0 +1,21 @@
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<module>
<inherits name="com.google.gwt.user.User"/>
<inherits name="org.eclipse.che.ide.Api"/>
<inherits name="com.google.gwt.inject.Inject"/>
<inherits name="org.eclipse.che.ide.ui.CodenvyUI"/>
<inherits name="org.eclipse.che.plugin.testing.TestingExtension"/>
<source path="ide"/>
</module>

View File

@ -0,0 +1,20 @@
#
# Copyright (c) 2012-2017 Codenvy, S.A.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Codenvy, S.A. - initial API and implementation
#
##### Actions #####
action.testNg.run.title = Run TestNG Test
action.testNg.run.description = Run TestNG tests
action.testNg.debug.title = Debug TestNG Test
action.testNg.debug.description = Debug TestNG tests

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
<path d="M29.884 25.14l-9.884-16.47v-6.671h1c0.55 0 1-0.45 1-1s-0.45-1-1-1h-10c-0.55 0-1 0.45-1 1s0.45 1 1 1h1v6.671l-9.884 16.47c-2.264 3.773-0.516 6.86 3.884 6.86h20c4.4 0 6.148-3.087 3.884-6.86zM7.532 20l6.468-10.779v-7.221h4v7.221l6.468 10.779h-16.935z"></path>
</svg>

After

Width:  |  Height:  |  Size: 960 B

View File

@ -24,44 +24,48 @@ import org.eclipse.che.commons.lang.execution.JavaParameters;
import org.eclipse.che.commons.lang.execution.ProcessHandler;
import org.eclipse.che.plugin.java.testing.AbstractJavaTestRunner;
import org.eclipse.che.plugin.java.testing.ClasspathUtil;
import org.eclipse.che.plugin.java.testing.JavaTestAnnotations;
import org.eclipse.che.plugin.java.testing.JavaTestFinder;
import org.eclipse.che.plugin.java.testing.ProjectClasspathProvider;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
import javax.inject.Inject;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
/**
* TestNG implementation for the test runner service.
*/
public class TestNGRunner extends AbstractJavaTestRunner {
private static final String TESTNG_NAME = "testng";
private static final String TEST_ANNOTATION_FQN = Test.class.getName();
private static final Logger LOG = LoggerFactory.getLogger(TestNGRunner.class);
private static final String TESTNG_NAME = "testng";
private static final Logger LOG = LoggerFactory.getLogger(TestNGRunner.class);
private static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
private String workspacePath;
private JavaTestFinder javaTestFinder;
private final ProjectClasspathProvider classpathProvider;
private final TestNGSuiteUtil suiteUtil;
@Inject
public TestNGRunner(@Named("che.user.workspaces.storage") String workspacePath,
JavaTestFinder javaTestFinder,
ProjectClasspathProvider classpathProvider,
TestNGSuiteUtil suiteUtil) {
super(workspacePath);
super(workspacePath, javaTestFinder);
this.workspacePath = workspacePath;
this.javaTestFinder = javaTestFinder;
this.classpathProvider = classpathProvider;
this.suiteUtil = suiteUtil;
}
@ -134,54 +138,47 @@ public class TestNGRunner extends AbstractJavaTestRunner {
}
private File createSuite(TestExecutionContext context, IJavaProject javaProject) {
switch (context.getTestType()) {
List<String> testSuite = createTestSuite(context, javaProject, JavaTestAnnotations.TESTNG_TEST.getName(), "");
Map<String, List<String>> classes = buildTestNgSuite(testSuite, context);
return suiteUtil.writeSuite(System.getProperty(JAVA_IO_TMPDIR), javaProject.getElementName(), classes);
}
private Map<String, List<String>> buildTestNgSuite(List<String> tests, TestExecutionContext context) {
switch (context.getContextType()) {
case FILE:
return createClassSuite(javaProject, context.getFilePath());
case FOLDER:
return createPackageSuite(javaProject, context.getFilePath());
case PROJECT:
return createProjectSuite(javaProject);
return createContainerSuite(tests);
case CURSOR_POSITION:
return createMethodSuite(javaProject, context.getFilePath(), context.getCursorOffset());
return createMethodSuite(tests);
default:
return emptyMap();
}
}
private Map<String, List<String>> createMethodSuite(List<String> tests) {
if (tests.isEmpty()) {
return Collections.emptyMap();
}
return null;
String testMethodDeclaration = tests.get(0);
int separatorIndex = testMethodDeclaration.indexOf('#');
return Collections.singletonMap(testMethodDeclaration.substring(0, separatorIndex),
singletonList(testMethodDeclaration.substring(separatorIndex + 1)));
}
private File createMethodSuite(IJavaProject javaProject, String filePath, int cursorOffset) {
ICompilationUnit compilationUnit = findCompilationUnitByPath(javaProject, filePath);
IType primaryType = compilationUnit.findPrimaryType();
String qualifiedName = primaryType.getFullyQualifiedName();
List<String> methods = new ArrayList<>();
try {
IJavaElement element = compilationUnit.getElementAt(cursorOffset);
if (element instanceof IMethod) {
IMethod method = (IMethod)element;
methods.add(method.getElementName());
}
} catch (JavaModelException e) {
LOG.debug("Can't read a method.", e);
private Map<String, List<String>> createContainerSuite(List<String> tests) {
if (tests.isEmpty()) {
return emptyMap();
}
Map<String, List<String>> classes = Collections.singletonMap(qualifiedName, methods);
return suiteUtil.writeSuite(System.getProperty("java.io.tmpdir"), javaProject.getElementName(), classes);
}
private File createProjectSuite(IJavaProject javaProject) {
//TODO add suite to run all tests from project
return null;
}
private File createPackageSuite(IJavaProject javaProject, String packagePath) {
//TODO add suite to run all tests from package
return null;
}
private File createClassSuite(IJavaProject javaProject, String filePath) {
ICompilationUnit compilationUnit = findCompilationUnitByPath(javaProject, filePath);
IType primaryType = compilationUnit.findPrimaryType();
String qualifiedName = primaryType.getFullyQualifiedName();
Map<String, List<String>> classes = Collections.singletonMap(qualifiedName, null);
return suiteUtil.writeSuite(System.getProperty("java.io.tmpdir"), javaProject.getElementName(), classes);
Map<String, List<String>> classes = new HashMap<>(tests.size());
for (String testClass : tests) {
classes.put(testClass, null);
}
return classes;
}
/**
@ -194,45 +191,6 @@ public class TestNGRunner extends AbstractJavaTestRunner {
@Override
protected boolean isTestMethod(IMethod method, ICompilationUnit compilationUnit) {
try {
IAnnotation[] annotations = method.getAnnotations();
IAnnotation test = null;
for (IAnnotation annotation : annotations) {
if (annotation.getElementName().equals("Test")) {
test = annotation;
break;
}
if (annotation.getElementName().equals(TEST_ANNOTATION_FQN)) {
return true;
}
}
if (test == null) {
return false;
}
IImportDeclaration[] imports = compilationUnit.getImports();
for (IImportDeclaration importDeclaration : imports) {
if (importDeclaration.getElementName().equals(TEST_ANNOTATION_FQN)) {
return true;
}
}
for (IImportDeclaration importDeclaration : imports) {
if (importDeclaration.isOnDemand()) {
String elementName = importDeclaration.getElementName();
elementName = elementName.substring(0, elementName.length() - 3); //remove .*
if (TEST_ANNOTATION_FQN.startsWith(elementName)) {
return true;
}
}
}
return false;
} catch (JavaModelException e) {
LOG.info("Can't read method annotations.", e);
return false;
}
return javaTestFinder.isTest(method, compilationUnit, JavaTestAnnotations.TESTNG_TEST.getName());
}
}

View File

@ -22,6 +22,7 @@ import org.eclipse.che.api.testing.shared.TestExecutionContext;
import org.eclipse.che.jdt.core.launching.JREContainerInitializer;
import org.eclipse.che.jdt.core.resources.ResourceChangedEvent;
import org.eclipse.che.plugin.java.testing.ClasspathUtil;
import org.eclipse.che.plugin.java.testing.JavaTestFinder;
import org.eclipse.che.plugin.java.testing.ProjectClasspathProvider;
import org.eclipse.che.plugin.testing.testng.server.TestNGRunner;
import org.eclipse.che.plugin.testing.testng.server.TestNGSuiteUtil;
@ -43,6 +44,7 @@ public class TestNGRunnerTest extends BaseTest {
private MethodNameConfigurator startMethodNameConfigurator;
private ParamsConfigurator startParamsConfigurator;
private SendConfiguratorFromOne startSendConfiguratorFromOne;
private JavaTestFinder testNGTestFinder;
private RequestTransmitter transmitter;
private TestNGRunner runner;
@ -50,12 +52,13 @@ public class TestNGRunnerTest extends BaseTest {
@BeforeMethod
public void setUp() throws Exception {
startEndpointIdConfigurator = mock(EndpointIdConfigurator.class);
testNGTestFinder = mock(JavaTestFinder.class);
startMethodNameConfigurator = mock(MethodNameConfigurator.class);
startParamsConfigurator = mock(ParamsConfigurator.class);
startSendConfiguratorFromOne = mock(SendConfiguratorFromOne.class);
transmitter = mock(RequestTransmitter.class);
runner = new TestNGRunner("", new ProjectClasspathProvider(""), new TestNGSuiteUtil());
runner = new TestNGRunner("", testNGTestFinder, new ProjectClasspathProvider(""), new TestNGSuiteUtil());
}
@Test()
@ -85,7 +88,7 @@ public class TestNGRunnerTest extends BaseTest {
DtoServerImpls.TestExecutionContextImpl context = new DtoServerImpls.TestExecutionContextImpl();
context.setDebugModeEnable(false);
context.setTestType(TestExecutionContext.TestType.FILE);
context.setContextType(TestExecutionContext.ContextType.FILE);
context.setProjectPath("/Test");
context.setFilePath("/Test/src/tests/TestNGTest.java");
assertEquals("testng", runner.getName());

View File

@ -12,6 +12,7 @@ package org.ecipse.che.plugin.testing.testng.server;
import org.eclipse.che.api.testing.shared.TestDetectionContext;
import org.eclipse.che.api.testing.shared.TestPosition;
import org.eclipse.che.plugin.java.testing.JavaTestFinder;
import org.eclipse.che.plugin.testing.testng.server.TestNGRunner;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
@ -32,12 +33,14 @@ import static org.fest.assertions.Assertions.assertThat;
public class TestNGTestDiscoveryTest extends BaseTest {
private IJavaProject javaProject;
private JavaTestFinder testNGTestFinder;
private IPackageFragment packageFragment;
@BeforeMethod
public void setUp() throws Exception {
javaProject = createJavaProject("testDiscovery", "bin");
testNGTestFinder = new JavaTestFinder();
IPackageFragmentRoot packageFragmentRoot = addSourceContainer(javaProject, "src", "bin");
javaProject.setRawClasspath(getTestNgClassPath("/testDiscovery/src"), null);
@ -65,7 +68,7 @@ public class TestNGTestDiscoveryTest extends BaseTest {
ICompilationUnit compilationUnit = packageFragment.createCompilationUnit("T.java", buf.toString(), false, null);
compilationUnit.reconcile(0, true, DefaultWorkingCopyOwner.PRIMARY, null);
TestNGRunner runner = new TestNGRunner("", null, null);
TestNGRunner runner = new TestNGRunner("", testNGTestFinder, null, null);
List<TestPosition> testPositions =
runner.detectTests(new MockTestDetectionContext("/testDiscovery", "/testDiscovery/src/test/T.java", -1));
@ -94,7 +97,7 @@ public class TestNGTestDiscoveryTest extends BaseTest {
ICompilationUnit compilationUnit = packageFragment.createCompilationUnit("T.java", buf.toString(), false, null);
compilationUnit.reconcile(0, true, DefaultWorkingCopyOwner.PRIMARY, null);
TestNGRunner runner = new TestNGRunner("", null, null);
TestNGRunner runner = new TestNGRunner("", testNGTestFinder, null, null);
List<TestPosition> testPositions =
runner.detectTests(new MockTestDetectionContext("/testDiscovery", "/testDiscovery/src/test/T.java", -1));
@ -118,7 +121,7 @@ public class TestNGTestDiscoveryTest extends BaseTest {
ICompilationUnit compilationUnit = packageFragment.createCompilationUnit("T.java", buf.toString(), false, null);
compilationUnit.reconcile(0, true, DefaultWorkingCopyOwner.PRIMARY, null);
TestNGRunner runner = new TestNGRunner("", null, null);
TestNGRunner runner = new TestNGRunner("", testNGTestFinder, null, null);
List<TestPosition> testPositions =
runner.detectTests(new MockTestDetectionContext("/testDiscovery", "/testDiscovery/src/test/T.java", -1));
@ -143,7 +146,7 @@ public class TestNGTestDiscoveryTest extends BaseTest {
ICompilationUnit compilationUnit = packageFragment.createCompilationUnit("T.java", buf.toString(), false, null);
compilationUnit.reconcile(0, true, DefaultWorkingCopyOwner.PRIMARY, null);
TestNGRunner runner = new TestNGRunner("", null, null);
TestNGRunner runner = new TestNGRunner("", testNGTestFinder, null, null);
List<TestPosition> testPositions =
runner.detectTests(new MockTestDetectionContext("/testDiscovery", "/testDiscovery/src/test/T.java", -1));
@ -167,7 +170,7 @@ public class TestNGTestDiscoveryTest extends BaseTest {
ICompilationUnit compilationUnit = packageFragment.createCompilationUnit("T.java", buf.toString(), false, null);
compilationUnit.reconcile(0, true, DefaultWorkingCopyOwner.PRIMARY, null);
TestNGRunner runner = new TestNGRunner("", null, null);
TestNGRunner runner = new TestNGRunner("", testNGTestFinder, null, null);
List<TestPosition> testPositions =
runner.detectTests(new MockTestDetectionContext("/testDiscovery", "/testDiscovery/src/test/T.java", -1));

View File

@ -22,6 +22,7 @@
<packaging>pom</packaging>
<name>Che Plugin :: Java Testing :: TestNG Parent</name>
<modules>
<module>che-plugin-testing-testng-ide</module>
<module>che-plugin-testing-testng-runtime</module>
<module>che-plugin-testing-testng-server</module>
</modules>

View File

@ -64,10 +64,6 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-model</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-project-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-testing-shared</artifactId>

View File

@ -19,7 +19,6 @@ import org.eclipse.che.ide.api.action.DefaultActionGroup;
*
* @author Mirage Abeysekara
*/
@Deprecated
public interface TestAction {
/**

View File

@ -21,7 +21,6 @@ import org.vectomatic.dom.svg.ui.SVGResource;
public interface TestResources extends ClientBundle {
@Source("org/eclipse/che/plugin/testing/ide/svg/test.svg")
@Deprecated
SVGResource testIcon();
@Source("org/eclipse/che/plugin/testing/ide/svg/test_all.svg")

View File

@ -77,8 +77,7 @@ public class TestingExtension {
testAction.addContextMenuItems(testContextMenu);
testContextMenu.addSeparator();
}
testContextMenu.add(runTestAction);
testContextMenu.add(debugTestAction);
explorerMenu.addSeparator();
explorerMenu.add(testContextMenu);
explorerMenu.addSeparator();

View File

@ -13,63 +13,41 @@ package org.eclipse.che.plugin.testing.ide.action;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcPromise;
import org.eclipse.che.api.project.shared.dto.ProjectTypeDto;
import org.eclipse.che.api.testing.shared.TestExecutionContext;
import org.eclipse.che.api.testing.shared.TestLaunchResult;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfiguration;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification;
import org.eclipse.che.ide.api.project.type.ProjectTypeRegistry;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.plugin.testing.ide.TestResources;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.model.GeneralTestingEventsProcessor;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import static java.lang.Boolean.TRUE;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
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 static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID;
/** Action that allows to run tests from current editor. */
@Singleton
public class DebugTestAction extends RunDebugTestAbstractAction {
private final TestServiceClient client;
private final DebugConfigurationsManager debugConfigurationsManager;
private final ProjectTypeRegistry projectTypeRegistry;
private final AppContext appContext;
private final NotificationManager notificationManager;
private final TestingHandler testingHandler;
private final TestResultPresenter testResultPresenter;
private Pair<String, String> frameworkAndTestName;
@Inject
public DebugTestAction(EventBus eventBus,
TestServiceClient client,
DebugConfigurationsManager debugConfigurationsManager,
DtoFactory dtoFactory,
TestResources testResources,
ProjectTypeRegistry projectTypeRegistry,
AppContext appContext,
NotificationManager notificationManager,
TestingHandler testingHandler,
TestResultPresenter testResultPresenter) {
super(eventBus,
testResultPresenter,
testingHandler,
debugConfigurationsManager,
client,
dtoFactory,
appContext,
@ -78,71 +56,19 @@ public class DebugTestAction extends RunDebugTestAbstractAction {
"Debug Test",
"Debug Test",
testResources.debugIcon());
this.client = client;
this.debugConfigurationsManager = debugConfigurationsManager;
this.projectTypeRegistry = projectTypeRegistry;
this.appContext = appContext;
this.notificationManager = notificationManager;
this.testingHandler = testingHandler;
this.testResultPresenter = testResultPresenter;
}
@Override
public void actionPerformed(ActionEvent e) {
final StatusNotification notification = new StatusNotification("Debugging Tests...", PROGRESS, FLOAT_MODE);
notificationManager.notify(notification);
frameworkAndTestName = getTestingFrameworkAndTestName();
TestExecutionContext context = createTestExecutionContext(frameworkAndTestName);
context.withDebugModeEnable(TRUE);
GeneralTestingEventsProcessor eventsProcessor = new GeneralTestingEventsProcessor(frameworkAndTestName.first,
testResultPresenter.getRootState());
testingHandler.setProcessor(eventsProcessor);
eventsProcessor.addListener(testResultPresenter.getEventListener());
JsonRpcPromise<TestLaunchResult> testResultPromise = client.runTests(context);
testResultPromise.onSuccess(result -> onTestRanSuccessfully(result, eventsProcessor, notification))
.onFailure(exception -> onTestRanUnsuccessfully(exception, notification));
Pair<String, String> frameworkAndTestName = getTestingFrameworkAndTestName();
actionPerformed(frameworkAndTestName, true);
}
private void onTestRanSuccessfully(TestLaunchResult result,
GeneralTestingEventsProcessor eventsProcessor,
StatusNotification notification) {
notification.setStatus(SUCCESS);
if (result.isSuccess()) {
notification.setTitle("Test runner executed successfully.");
testResultPresenter.handleResponse();
Project rootProject = appContext.getRootProject();
String type = rootProject.getType();
ProjectTypeDto projectType = projectTypeRegistry.getProjectType(type);
if (projectType.getParents().contains("java")) {
runRemoteJavaDebugger(eventsProcessor, result.getDebugPort());
}
} else {
notification.setTitle("Test runner failed to execute.");
}
}
private void runRemoteJavaDebugger(GeneralTestingEventsProcessor eventsProcessor, int port) {
DebugConfiguration debugger = debugConfigurationsManager.createConfiguration("jdb",
frameworkAndTestName.first,
"localhost",
port,
emptyMap());
eventsProcessor.setDebuggerConfiguration(debugger, debugConfigurationsManager);
debugConfigurationsManager.apply(debugger);
}
private void onTestRanUnsuccessfully(JsonRpcError exception, StatusNotification notification) {
final String errorMessage = (exception.getMessage() != null) ? exception.getMessage()
: "Failed to run test cases";
notification.setContent(errorMessage);
notification.setStatus(FAIL);
@Override
public void updateInPerspective(@NotNull ActionEvent event) {
Presentation presentation = event.getPresentation();
presentation.setVisible(isEditorInFocus);
presentation.setEnabled(isEnable);
}
}

View File

@ -10,80 +10,117 @@
*******************************************************************************/
package org.eclipse.che.plugin.testing.ide.action;
import com.google.common.base.Optional;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcPromise;
import org.eclipse.che.api.testing.shared.TestDetectionContext;
import org.eclipse.che.api.testing.shared.TestExecutionContext;
import org.eclipse.che.api.testing.shared.TestLaunchResult;
import org.eclipse.che.api.testing.shared.TestPosition;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.api.action.AbstractPerspectiveAction;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfiguration;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
import org.eclipse.che.ide.api.parts.ActivePartChangedEvent;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification;
import org.eclipse.che.ide.api.parts.PartPresenter;
import org.eclipse.che.ide.api.resources.Container;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.editor.JavaReconsilerEvent;
import org.eclipse.che.ide.ext.java.client.resource.SourceFolderMarker;
import org.eclipse.che.ide.ext.java.client.util.JavaUtil;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.ide.util.loging.Log;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.model.GeneralTestingEventsProcessor;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import org.vectomatic.dom.svg.ui.SVGResource;
import javax.validation.constraints.NotNull;
import java.util.List;
import static org.eclipse.che.api.testing.shared.TestExecutionContext.TestType.CURSOR_POSITION;
import static java.util.Collections.emptyMap;
import static org.eclipse.che.api.testing.shared.TestExecutionContext.ContextType.CURSOR_POSITION;
import static org.eclipse.che.api.testing.shared.TestExecutionContext.ContextType.PROJECT;
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 static org.eclipse.che.ide.api.resources.Resource.FILE;
import static org.eclipse.che.ide.ext.java.client.util.JavaUtil.isJavaFile;
/** Abstract action that analyzes active editor and makes run/debug test actions active if some test methods are exist. */
public abstract class RunDebugTestAbstractAction extends AbstractPerspectiveAction {
TextEditor currentEditor;
public static final String JUNIT_FRAMEWORK_NAME = "junit";
public static final String TESTNG_FRAMEWORK_NAME = "testng";
private TestExecutionContext.TestType testType;
private List<TestPosition> testPosition;
private boolean hasTests;
private TestServiceClient client;
private DtoFactory dtoFactory;
private AppContext appContext;
private NotificationManager notificationManager;
private TextEditor currentEditor;
private List<TestPosition> testPosition;
private TestResultPresenter testResultPresenter;
private TestingHandler testingHandler;
private DebugConfigurationsManager debugConfigurationsManager;
private TestServiceClient client;
private DtoFactory dtoFactory;
private AppContext appContext;
private NotificationManager notificationManager;
private TestExecutionContext.ContextType contextType;
private String selectedNodePath;
RunDebugTestAbstractAction(EventBus eventBus,
TestServiceClient client,
DtoFactory dtoFactory,
AppContext appContext,
NotificationManager notificationManager,
@Nullable List<String> perspectives,
@NotNull String description,
@NotNull String text,
SVGResource icon) {
protected boolean isEnable;
protected boolean isEditorInFocus;
public RunDebugTestAbstractAction(EventBus eventBus,
TestResultPresenter testResultPresenter,
TestingHandler testingHandler,
DebugConfigurationsManager debugConfigurationsManager,
TestServiceClient client,
DtoFactory dtoFactory,
AppContext appContext,
NotificationManager notificationManager,
@Nullable List<String> perspectives,
@NotNull String description,
@NotNull String text,
SVGResource icon) {
super(perspectives, text, description, null, icon);
this.testResultPresenter = testResultPresenter;
this.testingHandler = testingHandler;
this.debugConfigurationsManager = debugConfigurationsManager;
this.client = client;
this.dtoFactory = dtoFactory;
this.appContext = appContext;
this.notificationManager = notificationManager;
hasTests = false;
isEnable = false;
eventBus.addHandler(JavaReconsilerEvent.TYPE, event -> detectTests(event.getEditor()));
eventBus.addHandler(ActivePartChangedEvent.TYPE, event -> {
if (event.getActivePart() instanceof TextEditor) {
testType = CURSOR_POSITION;
TextEditor activeEditor = (TextEditor)event.getActivePart();
PartPresenter activePart = event.getActivePart();
if (activePart instanceof TextEditor) {
isEditorInFocus = true;
contextType = CURSOR_POSITION;
TextEditor activeEditor = (TextEditor)activePart;
if (activeEditor.getEditorInput().getFile().getName().endsWith(".java")) {
detectTests(activeEditor);
} else {
hasTests = false;
isEnable = false;
}
} else {
isEditorInFocus = false;
}
});
}
@Override
public void updateInPerspective(@NotNull ActionEvent event) {
Presentation presentation = event.getPresentation();
presentation.setEnabled(hasTests);
}
public abstract void updateInPerspective(@NotNull ActionEvent event);
@Override
public abstract void actionPerformed(ActionEvent e);
@ -95,11 +132,11 @@ public abstract class RunDebugTestAbstractAction extends AbstractPerspectiveActi
context.setOffset(currentEditor.getCursorOffset());
context.setProjectPath(appContext.getRootProject().getPath());
client.detectTests(context).onSuccess(testDetectionResult -> {
hasTests = testDetectionResult.isTestFile();
isEnable = testDetectionResult.isTestFile();
testPosition = testDetectionResult.getTestPosition();
}).onFailure(jsonRpcError -> {
Log.error(getClass(), jsonRpcError);
hasTests = false;
isEnable = false;
notificationManager.notify("Can't detect test methods");
});
}
@ -111,14 +148,20 @@ public abstract class RunDebugTestAbstractAction extends AbstractPerspectiveActi
* name of the test framework
* @return test execution context
*/
protected TestExecutionContext createTestExecutionContext(Pair<String, String> frameworkAndTestName) {
protected TestExecutionContext createTestExecutionContext(Pair<String, String> frameworkAndTestName,
TestExecutionContext.ContextType contextType,
String selectedNodePath) {
final Project project = appContext.getRootProject();
TestExecutionContext context = dtoFactory.createDto(TestExecutionContext.class);
context.setProjectPath(project.getPath());
context.setTestType(testType);
context.setFilePath(currentEditor.getEditorInput().getFile().getLocation().toString());
context.setCursorOffset(currentEditor.getCursorOffset());
context.setContextType(contextType);
if (contextType == CURSOR_POSITION) {
context.setFilePath(currentEditor.getEditorInput().getFile().getLocation().toString());
context.setCursorOffset(currentEditor.getCursorOffset());
} else {
context.setFilePath(selectedNodePath);
}
context.setFrameworkName(frameworkAndTestName.first);
return context;
@ -139,4 +182,106 @@ public abstract class RunDebugTestAbstractAction extends AbstractPerspectiveActi
}
return Pair.of(testPosition.iterator().next().getFrameworkName(), null);
}
/**
* Runs an action.
*
* @param frameworkAndTestName
* contains name of the test framework and test methods
* @param isDebugMode
* is {@code true} if the action uses for debugging
*/
protected void actionPerformed(Pair<String, String> frameworkAndTestName, boolean isDebugMode) {
final StatusNotification notification = new StatusNotification("Running Tests...", PROGRESS, FLOAT_MODE);
notificationManager.notify(notification);
TestExecutionContext context = createTestExecutionContext(frameworkAndTestName, contextType, selectedNodePath);
context.withDebugModeEnable(isDebugMode);
GeneralTestingEventsProcessor eventsProcessor = new GeneralTestingEventsProcessor(frameworkAndTestName.first,
testResultPresenter.getRootState());
testingHandler.setProcessor(eventsProcessor);
eventsProcessor.addListener(testResultPresenter.getEventListener());
JsonRpcPromise<TestLaunchResult> testResultPromise = client.runTests(context);
testResultPromise.onSuccess(result -> onTestRanSuccessfully(result,
eventsProcessor,
notification,
frameworkAndTestName.first,
isDebugMode))
.onFailure(exception -> onTestRanFailed(exception, notification));
}
/**
* Analyzes project tree selection. Needs for detecting context type for the test runner.
*/
protected void analyzeProjectTreeSelection() {
Resource[] resources = appContext.getResources();
if (resources == null || resources.length > 1) {
isEnable = false;
return;
}
Resource resource = resources[0];
if (resource.isProject() && JavaUtil.isJavaProject((Project)resource)) {
contextType = PROJECT;
isEnable = true;
return;
}
Project project = resource.getProject();
if (!JavaUtil.isJavaProject(project)) {
isEnable = false;
return;
}
Optional<Resource> srcFolder = resource.getParentWithMarker(SourceFolderMarker.ID);
if (!srcFolder.isPresent() || resource.getLocation().equals(srcFolder.get().getLocation())) {
isEnable = false;
return;
}
if (resource.getResourceType() == FILE && isJavaFile(resource)) {
contextType = TestExecutionContext.ContextType.FILE;
} else if (resource instanceof Container) {
contextType = TestExecutionContext.ContextType.FOLDER;
}
selectedNodePath = resource.getLocation().toString();
isEnable = true;
}
private void onTestRanSuccessfully(TestLaunchResult result,
GeneralTestingEventsProcessor eventsProcessor,
StatusNotification notification,
String frameworkName,
boolean isDebugMode) {
notification.setStatus(SUCCESS);
if (result.isSuccess()) {
notification.setTitle("Test runner executed successfully.");
testResultPresenter.handleResponse();
if (isDebugMode) {
runRemoteJavaDebugger(eventsProcessor, frameworkName, result.getDebugPort());
}
} else {
notification.setTitle("Test runner failed to execute.");
}
}
private void onTestRanFailed(JsonRpcError exception, StatusNotification notification) {
final String errorMessage = (exception.getMessage() != null) ? exception.getMessage()
: "Failed to run test cases";
notification.setContent(errorMessage);
notification.setStatus(FAIL);
}
private void runRemoteJavaDebugger(GeneralTestingEventsProcessor eventsProcessor, String frameworkName, int port) {
DebugConfiguration debugger = debugConfigurationsManager.createConfiguration("jdb",
frameworkName,
"localhost",
port,
emptyMap());
eventsProcessor.setDebuggerConfiguration(debugger, debugConfigurationsManager);
debugConfigurationsManager.apply(debugger);
}
}

View File

@ -13,40 +13,27 @@ package org.eclipse.che.plugin.testing.ide.action;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcPromise;
import org.eclipse.che.api.testing.shared.TestExecutionContext;
import org.eclipse.che.api.testing.shared.TestLaunchResult;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.debug.DebugConfigurationsManager;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.Pair;
import org.eclipse.che.plugin.testing.ide.TestResources;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.handler.TestingHandler;
import org.eclipse.che.plugin.testing.ide.model.GeneralTestingEventsProcessor;
import org.eclipse.che.plugin.testing.ide.view2.TestResultPresenter;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import static java.lang.Boolean.FALSE;
import static java.util.Collections.singletonList;
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 static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID;
/** Action that allows to run tests from current editor. */
@Singleton
public class RunTestAction extends RunDebugTestAbstractAction {
private final TestServiceClient client;
private final NotificationManager notificationManager;
private final TestingHandler testingHandler;
private final TestResultPresenter testResultPresenter;
@Inject
public RunTestAction(EventBus eventBus,
TestServiceClient client,
@ -54,9 +41,13 @@ public class RunTestAction extends RunDebugTestAbstractAction {
TestResources testResources,
AppContext appContext,
NotificationManager notificationManager,
DebugConfigurationsManager debugConfigurationsManager,
TestingHandler testingHandler,
TestResultPresenter testResultPresenter) {
super(eventBus,
testResultPresenter,
testingHandler,
debugConfigurationsManager,
client,
dtoFactory,
appContext,
@ -65,45 +56,19 @@ public class RunTestAction extends RunDebugTestAbstractAction {
"Run Test",
"Run Test",
testResources.testIcon());
this.client = client;
this.notificationManager = notificationManager;
this.testingHandler = testingHandler;
this.testResultPresenter = testResultPresenter;
}
@Override
public void actionPerformed(ActionEvent e) {
final StatusNotification notification = new StatusNotification("Running Tests...", PROGRESS, FLOAT_MODE);
notificationManager.notify(notification);
Pair<String, String> frameworkAndTestName = getTestingFrameworkAndTestName();
TestExecutionContext context = createTestExecutionContext(frameworkAndTestName);
context.withDebugModeEnable(FALSE);
GeneralTestingEventsProcessor eventsProcessor = new GeneralTestingEventsProcessor(frameworkAndTestName.first,
testResultPresenter.getRootState());
testingHandler.setProcessor(eventsProcessor);
eventsProcessor.addListener(testResultPresenter.getEventListener());
JsonRpcPromise<TestLaunchResult> testResultPromise = client.runTests(context);
testResultPromise.onSuccess(result -> onTestRanSuccessfully(result, notification))
.onFailure(exception -> onTestRanUnsuccessfully(exception, notification));
actionPerformed(frameworkAndTestName, false);
}
private void onTestRanSuccessfully(TestLaunchResult result, StatusNotification notification) {
notification.setStatus(SUCCESS);
if (result.isSuccess()) {
notification.setTitle("Test runner executed successfully.");
testResultPresenter.handleResponse();
} else {
notification.setTitle("Test runner failed to execute.");
}
@Override
public void updateInPerspective(@NotNull ActionEvent event) {
Presentation presentation = event.getPresentation();
presentation.setVisible(isEditorInFocus);
presentation.setEnabled(isEnable);
}
private void onTestRanUnsuccessfully(JsonRpcError exception, StatusNotification notification) {
final String errorMessage = (exception.getMessage() != null) ? exception.getMessage()
: "Failed to run test cases";
notification.setContent(errorMessage);
notification.setStatus(FAIL);
}
}

View File

@ -1,85 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.testing.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.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.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.plugin.testing.ide.TestServiceClient;
import org.eclipse.che.plugin.testing.ide.view.TestResultPresenter;
/**
* @author Mirage Abeysekara
* @author David Festal
*/
public class RunTestActionDelegate {
private final Source source;
public interface Source {
NotificationManager getNotificationManager();
AppContext getAppContext();
TestServiceClient getService();
TestResultPresenter getPresenter();
String getTestingFramework();
}
public RunTestActionDelegate(Source source) {
this.source = source;
}
public void doRunTests(ActionEvent e, Map<String, String> parameters) {
final StatusNotification notification = new StatusNotification("Running Tests...", PROGRESS, FLOAT_MODE);
source.getNotificationManager().notify(notification);
final Project project = source.getAppContext().getRootProject();
parameters.put("updateClasspath", "true");
Promise<TestResult> testResultPromise = source.getService().getTestResult(project.getPath(), source.getTestingFramework(), parameters, notification);
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");
}
source.getPresenter().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);
}
});
}
}

View File

@ -43,8 +43,9 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
private final Set<TestState> currentChildren = new LinkedHashSet<>();
private final Map<String, TestState> testNameToTestState = new HashMap<>();
private final List<Runnable> buildTreeEvents = new ArrayList<>();
private boolean gettingChildren = true;
private boolean gettingChildren = true;
private TestState lastTreeState;
private boolean treeBuildBeforeStart = false;
private TestLocator testLocator = null;
@ -54,6 +55,7 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
public GeneralTestingEventsProcessor(String testFrameworkName, TestRootState testRootState) {
super(testFrameworkName);
this.testRootState = testRootState;
this.lastTreeState = testRootState;
}
@Override
@ -67,9 +69,12 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
public void onTestSuiteStarted(TestSuiteStartedEvent event) {
String name = event.getName();
String location = event.getLocation();
TestState currentSuite = getCurrentSuite();
if (currentSuite.getName().equals(name) && treeBuildBeforeStart) {
return;
TestState currentSuite;
if (treeBuildBeforeStart) {
findState(testRootState, name);
currentSuite = lastTreeState;
} else {
currentSuite = getCurrentSuite();
}
TestState newState;
if (location == null) {
@ -92,10 +97,28 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
}
gettingChildren = true;
testSuiteStack.push(newState);
if (treeBuildBeforeStart) {
testSuiteStack.add(newState);
} else {
testSuiteStack.push(newState);
}
callSuiteStarted(newState);
}
private void findState(TestState currentState, String name) {
List<TestState> children = currentState.getChildren();
for (TestState state : children) {
if (state.getName().equals(name)) {
lastTreeState = currentState;
return;
}
}
for (TestState state : children) {
findState(state, name);
}
}
@Override
public void onTestSuiteFinished(TestSuiteFinishedEvent event) {
TestState suite = testSuiteStack.pop(event.getName());
@ -244,15 +267,19 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
@Override
public void onSuiteTreeStarted(String suiteName, String location) {
treeBuildBeforeStart = true;
TestState currentSuite = getCurrentSuite();
TestState newSuite = new TestState(suiteName, true, location);
if (testLocator != null) {
newSuite.setTestLocator(testLocator);
}
currentSuite.addChild(newSuite);
if (TestRootState.ROOT.equals(lastTreeState.getName())) {
testRootState.addChild(newSuite);
} else {
lastTreeState.addChild(newSuite);
}
testSuiteStack.push(newSuite);
lastTreeState = newSuite;
testSuiteStack.add(newSuite);
callSuiteTreeStarted(newSuite);
}
@ -272,7 +299,11 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
@Override
public void onSuiteTreeEnded(String suiteName) {
buildTreeEvents.add(() -> testSuiteStack.pop(suiteName));
if (!(TestRootState.ROOT.equals(lastTreeState.getName()))) {
lastTreeState = lastTreeState.getParent();
}
testSuiteStack.pop(suiteName);
}
@Override
@ -284,7 +315,7 @@ public class GeneralTestingEventsProcessor extends AbstractTestingEventsProcesso
newState.setTestLocator(testLocator);
}
TestState currentSuite = getCurrentSuite();
TestState currentSuite = testSuiteStack.peekLast();
currentSuite.setTreeBuildBeforeStart();
currentSuite.addChild(newState);

View File

@ -14,6 +14,7 @@ package org.eclipse.che.plugin.testing.ide.model;
* Describes test root state.
*/
public class TestRootState extends TestState {
public static final String ROOT = "Root";
private boolean testReporterAttached;
@ -22,7 +23,7 @@ public class TestRootState extends TestState {
private String comment;
public TestRootState() {
super("Root", true, null);
super(ROOT, true, null);
}
public boolean isTestReporterAttached() {

View File

@ -22,15 +22,51 @@ public class TestSuiteStack {
private Deque<TestState> stack = new ArrayDeque<>();
/**
* Pushes an element onto the stack at the head of this deque.
*
* @param state
* new test state
*/
public void push(TestState state) {
stack.push(state);
}
/**
* Inserts the specified element at the tail of this deque.
*
* @param state
* new test state
*/
public void add(TestState state) {
stack.add(state);
}
/**
* Retrieves, but does not remove, the last element of this deque,
* or returns {@code null} if this deque is empty.
*/
public TestState peekLast() {
return stack.peekLast();
}
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque), or
* returns {@code null} if this deque is empty.
*/
public TestState getCurrent() {
return stack.peek();
}
/**
* Pops an element from the stack represented by this deque. In other
* words, removes and returns the first element of this deque.
*
* @param suiteName
* name of suite
* @return element from the stack which has same name
*/
public TestState pop(String suiteName) {
if (stack.isEmpty()) {
Log.error(getClass(), "Test suite stack is empty, unexpected suite name: " + suiteName);
@ -67,10 +103,19 @@ public class TestSuiteStack {
return state;
}
/**
* Returns <tt>true</tt> if this collection contains no elements.
*
* @return <tt>true</tt> if this collection contains no elements
*/
public boolean isEmpty() {
return stack.isEmpty();
}
/**
* Removes all of the elements from this collection (optional operation).
* The collection will be empty after this method returns.
*/
public void clear() {
stack.clear();
}

View File

@ -20,11 +20,9 @@ import org.eclipse.che.plugin.testing.ide.model.TestState;
import javax.inject.Inject;
/**
*
* Represents an output console for test results.
*/
public class PrinterOutputConsole extends OutputConsoleViewImpl implements Printer {
private TestState currentTest;
@Inject
@ -47,6 +45,7 @@ public class PrinterOutputConsole extends OutputConsoleViewImpl implements Print
} else {
print(text, false);
}
enableAutoScroll(true);
}
@Override

View File

@ -59,9 +59,9 @@ public class TestResultViewImpl extends BaseView<TestResultView.ActionDelegate>
@UiField(provided = true)
SplitLayoutPanel splitLayoutPanel;
@UiField
FlowPanel navigationPanel;
FlowPanel navigationPanel;
private Tree resultTree;
private int lastWentLine = 0;
private int lastWentLine = 0;
private boolean showFailuresOnly = false;
private TestRootState testRootState;
@ -95,7 +95,7 @@ public class TestResultViewImpl extends BaseView<TestResultView.ActionDelegate>
resultTree.getSelectionModel().addSelectionHandler(event -> {
Node methodNode = event.getSelectedItem();
if (methodNode instanceof TestStateNode) {
outputConsole.testSelected(((TestStateNode) methodNode).getTestState());
outputConsole.testSelected(((TestStateNode)methodNode).getTestState());
}
});
@ -131,9 +131,11 @@ public class TestResultViewImpl extends BaseView<TestResultView.ActionDelegate>
TestStateNode parentStateNode = findNodeByState(parent);
if (parentStateNode != null) {
Node parentStateNodeParent = parentStateNode.getParent();
resultTree.refresh(parentStateNode);
int parentIndex = resultTree.getNodeStorage().indexOf(parentStateNode);
resultTree.getNodeStorage().remove(parentStateNode);
if (parentStateNodeParent != null) {
resultTree.getNodeStorage().add(parentStateNodeParent, parentStateNode);
resultTree.getNodeStorage().insert(parentStateNodeParent, parentIndex, parentStateNode);
} else {
resultTree.getNodeStorage().add(parentStateNode);
}
@ -150,7 +152,7 @@ public class TestResultViewImpl extends BaseView<TestResultView.ActionDelegate>
private TestStateNode findNodeByState(TestState parent) {
for (Node node : resultTree.getNodeStorage().getAll()) {
if (node instanceof TestStateNode) {
TestStateNode stateNode = (TestStateNode) node;
TestStateNode stateNode = (TestStateNode)node;
if (stateNode.getTestState().equals(parent)) {
return stateNode;
}
@ -170,7 +172,7 @@ public class TestResultViewImpl extends BaseView<TestResultView.ActionDelegate>
@Override
public void onSuiteTreeNodeAdded(TestState testState) {
addSuiteOrTest(testState);
//addSuiteOrTest(testState);
}
@Override

10
pom.xml
View File

@ -950,6 +950,11 @@
<artifactId>che-plugin-testing-ide</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-junit-ide</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-junit-runtime</artifactId>
@ -970,6 +975,11 @@
<artifactId>che-plugin-testing-phpunit-server</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-testng-ide</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-testing-testng-runtime</artifactId>

View File

@ -9,8 +9,20 @@
# Codenvy, S.A. - initial API and implementation
#
is_current_user_root() {
test "$(id -u)" = 0
}
is_current_user_sudoer() {
sudo -n true > /dev/null 2>&1
}
set_sudo_command() {
if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi
}
set_sudo_command
unset PACKAGES
unset SUDO
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
CURL_INSTALLED=false
WGET_INSTALLED=false
@ -23,8 +35,6 @@ if [ ${CURL_INSTALLED} = false ] && [ ${WGET_INSTALLED} = false ]; then
CURL_INSTALLED=true
fi
test "$(id -u)" = 0 || SUDO="sudo -E"
LOCAL_AGENT_BINARIES_URI="/mnt/che/ws-agent.tar.gz"
DOWNLOAD_AGENT_BINARIES_URI='${WORKSPACE_MASTER_URI}/agent-binaries/ws-agent.tar.gz'

View File

@ -34,9 +34,9 @@ public interface TestExecutionContext {
void setFilePath(String filePath);
/** returns type of the test. */
TestType getTestType();
ContextType getContextType();
void setTestType(TestType testType);
void setContextType(ContextType contextType);
/** returns cursor position. */
int getCursorOffset();
@ -50,7 +50,7 @@ public interface TestExecutionContext {
TestExecutionContext withDebugModeEnable(Boolean enable);
enum TestType {
enum ContextType {
FILE, FOLDER, PROJECT, CURSOR_POSITION
}
}