Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove hard-coded test finder from JUnitCore #953

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
import org.eclipse.jdt.core.IType;

import org.eclipse.jdt.internal.junit.JUnitCorePlugin;
import org.eclipse.jdt.internal.junit.launcher.JUnit4TestFinder;
import org.eclipse.jdt.internal.junit.launcher.ITestFinder;
import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry;
import org.eclipse.jdt.internal.junit.model.JUnitModel;
import org.eclipse.jdt.internal.junit.model.ModelMessages;
import org.eclipse.jdt.internal.junit.model.TestRunSession;
Expand Down Expand Up @@ -156,7 +157,8 @@ public static void removeTestRunListener(TestRunListener listener) {
*/
public static IType[] findTestTypes(IJavaElement container, IProgressMonitor monitor) throws CoreException, OperationCanceledException {
final Set<IType> result= new HashSet<>();
JUnit4TestFinder finder= new JUnit4TestFinder();
ITestFinder finder= TestKindRegistry.getContainerTestKind(container).getFinder();

finder.findTestsInContainer(container, result, monitor);

return result.toArray(new IType[result.size()]);
Expand Down
3 changes: 2 additions & 1 deletion org.eclipse.jdt.ui.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ Require-Bundle:
Bundle-RequiredExecutionEnvironment: JavaSE-17
Eclipse-BundleShape: dir
Bundle-ActivationPolicy: lazy
Import-Package: org.junit.jupiter.api,
Import-Package: org.assertj.core.api;version="3.24.2",
org.junit.jupiter.api,
org.junit.platform.suite.api,
org.junit.platform.suite.commons;status=INTERNAL,
org.junit.platform.suite.engine;status=INTERNAL
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*******************************************************************************
* Copyright (c) 2023 Vector Informatik GmbH and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Vector Informatik GmbH - initial API and implementation
*******************************************************************************/
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate;

import junit.framework.TestCase;

/**
* This class contains some internal classes that should be found/not found by the
* JUnit5TestFinder.<br/>
* <br/>
* The names of the classes give a hint about whether or not the class should be found and the
* reason for that. In order to be discovered, a class needs to fulfill these requirements:
* <ul>
* <li>It should be visible (it can <strong>not</strong> be <code>private</code>)</li>
* <li>It must have tests in it.</li>
* </ul>
*
* Whether or not the class can be instantiated (<i>i.e.</i> if they have a non-private empty
* constructor) does not play a role in the discoverability, but running tests on that class will
* throw an exception,
*/
class JupiterTests {
/**
* Methods using this annotation are also considered tests
*/
@Test
@Retention(RetentionPolicy.RUNTIME)
@interface CustomTestAnnotation {}

static class FoundStatic {
@Test void myTest() {}
}

static class FoundStaticCustomTestAnnotation {
@CustomTestAnnotation void myTest() {}
}

private static class NotFoundPrivate {
@CustomTestAnnotation void myTest() {}
}

static class NotFoundHasNoTests {}

static class FoundExtendsTestCase extends TestCase {
@Test void myTest() {}
}

static class FoundExtendsTestCaseCustomTestAnnotation extends TestCase {
@CustomTestAnnotation public void myTest() {}
}

private static class NotFoundPrivateExtendsTestCase extends TestCase {
@Test public void myTest() {}
}

static class FoundTestTemplateClass {
@TestTemplate void myTestTemplate() {}
}

static abstract class NotFoundAbstractWithInnerClass {
class NotFoundInnerInstanceClassWithTest {
@Test void myTest() {}
}
}

static class NotFoundExtendsAbstractWithInnerWithTest extends NotFoundAbstractWithInnerClass {}

static class FoundHasInnerClassWithNested {
@Nested class FoundExtendsAbstractWithNested extends NotFoundAbstractWithInnerClass {
@Test void myTest() {}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*******************************************************************************
* Copyright (c) 2023 Vector Informatik GmbH and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Vector Informatik GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.junit.tests;

import static org.assertj.core.api.Assertions.assertThat;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import org.eclipse.jdt.junit.JUnitCore;
import org.eclipse.jdt.testplugin.JavaProjectHelper;

import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.internal.junit.launcher.ITestFinder;
import org.eclipse.jdt.internal.junit.launcher.JUnit5TestFinder;
import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry;


/**
* Test if the <code>JUnit5TestFinder</code> can find tests annotated with the API of JUnit5
* (Jupiter)
*/
@RunWith(Parameterized.class)
public class JUnit5TestFinderJupiterTest {

record TestScenario(String testClass, int testTypesCount) {
}

private static final String JAVA_CLASS_NAME= "JupiterTests";

private static final String JAVA_FILE_NAME= JAVA_CLASS_NAME + ".java";

private static final Path TEST_CLASS_FILE= Path.of("testresources").resolve("testClasses").resolve(JAVA_FILE_NAME);

private static IJavaProject javaProject;

@Parameters(name= "{0}")
public static Collection<TestScenario> getCompilationUnits() {

// These are the current "valid" results
return List.of(new TestScenario(JAVA_CLASS_NAME, 7), //
new TestScenario("CustomTestAnnotation", 0), // Not a test class
new TestScenario("FoundStatic", 1), //
new TestScenario("FoundStaticCustomTestAnnotation", 1), //
new TestScenario("NotFoundPrivate", 0), // private class
new TestScenario("NotFoundHasNoTests", 0), // empty class (no tests)
new TestScenario("FoundExtendsTestCase", 1), //
new TestScenario("FoundExtendsTestCaseCustomTestAnnotation", 1), //
new TestScenario("NotFoundPrivateExtendsTestCase", 0), // private class
new TestScenario("FoundTestTemplateClass", 1), //
new TestScenario("NotFoundAbstractWithInnerClass", 0), // can't be instantiated
new TestScenario("NotFoundExtendsAbstractWithInnerWithTest", 0), // FIXME: why isn't this one found even though it can be instantiated?
new TestScenario("FoundHasInnerClassWithNested", 1), //
new TestScenario("NotFoundInnerInstanceClassWithTest", 0), // has test but it can't be instantiated (needs enclosing instance)
new TestScenario("FoundExtendsAbstractWithNested", 1) //
);

}

@Parameter
public TestScenario scenario;

private static ICompilationUnit compilationUnit;

@BeforeClass
public static void beforeClass() throws Exception {
javaProject= JavaProjectHelper.createJavaProject("TestProject", "bin");
JavaProjectHelper.addRTJar(javaProject);
IClasspathEntry cpe= JavaCore.newContainerEntry(JUnitCore.JUNIT5_CONTAINER_PATH);
JavaProjectHelper.addToClasspath(javaProject, cpe);
JavaProjectHelper.set18CompilerOptions(javaProject);

IPackageFragmentRoot root= JavaProjectHelper.addSourceContainer(javaProject, "src");
IPackageFragment packageFragment= root.createPackageFragment("somepackage", true, null);

compilationUnit= createCompilationUnit(packageFragment);
}

@AfterClass
public static void afterClass() throws Exception {
JavaProjectHelper.delete(javaProject);
}

@Test
public void testTestKindRegistryGetContainerTestKind_isJUnit5TestFinder() throws Exception {
IType type= findTypeWithName(scenario.testClass());

ITestFinder finder= TestKindRegistry.getContainerTestKind(type).getFinder();
assertThat(finder).isInstanceOf(JUnit5TestFinder.class);
}

@Test
public void testFindTestsInContainer() throws Exception {
IType type= findTypeWithName(scenario.testClass());
Set<IType> foundTestTypes= new HashSet<>();

JUnit5TestFinder objectUnderTest= new JUnit5TestFinder();
objectUnderTest.findTestsInContainer(type, foundTestTypes, null);

assertThat(foundTestTypes).hasSize(scenario.testTypesCount());
}


private IType findTypeWithName(String name) throws JavaModelException {
for (IType type : compilationUnit.getAllTypes()) {
if (type.getElementName().equals(name))
return type;
}
return null;
}

private static ICompilationUnit createCompilationUnit(IPackageFragment packageFragment) throws Exception {
String content= Files.readString(TEST_CLASS_FILE);
return packageFragment.createCompilationUnit(JAVA_FILE_NAME, content, false, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@
TestRunSessionSerializationTests4.class,

JUnit3TestFinderTest.class,
JUnit4TestFinderTest.class,
JUnitTestFinderTest.class,
JUnit4TestFinderTest16.class,
JUnit5TestFinderJupiterTest.class,

TestSorting.class
//LegacyTestRunListenerTest.class
Expand Down
Loading
Loading