mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
[jvm] Convert TestCaseWithNoTestMethods inspection to JVM
#IDEA-331938 Fixed GitOrigin-RevId: 9ecdc3d6e03d52cb54865067483b4c97e29d3236
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6a706d72a4
commit
cc61bc25c7
@@ -823,7 +823,6 @@ continue.or.break.from.finally.block.display.name='continue' or 'break' inside '
|
||||
abstract.method.with.missing.implementations.display.name=Abstract method with missing implementations
|
||||
object.allocation.in.loop.display.name=Object allocation in loop
|
||||
wait.called.on.condition.display.name='wait()' called on 'java.util.concurrent.locks.Condition' object
|
||||
test.case.with.no.test.methods.display.name=Test class with no tests
|
||||
abstract.class.never.implemented.display.name=Abstract class which has no concrete subclass
|
||||
interface.never.implemented.display.name=Interface which has no concrete subclass
|
||||
constant.declared.in.interface.display.name=Constant declared in interface
|
||||
@@ -1070,7 +1069,6 @@ assert.without.message.problem.descriptor=<code>#ref()</code> without message #l
|
||||
assert.without.message.quick.fix.family.name=Add error message
|
||||
misordered.assert.equals.arguments.problem.descriptor=Arguments to <code>#ref()</code> in wrong order #loc
|
||||
simplifiable.junit.assertion.problem.descriptor=<code>#ref()</code> can be simplified to ''{0}'' #loc
|
||||
test.case.with.no.test.methods.problem.descriptor=Test class <code>#ref</code> has no tests #loc
|
||||
deserializable.class.in.secure.context.problem.descriptor=Class <code>#ref</code> may be deserialized, compromising security #loc
|
||||
serializable.class.in.secure.context.problem.descriptor=Class <code>#ref</code> may be serialized, compromising security #loc
|
||||
serializable.deserializable.class.in.secure.context.problem.descriptor=Class <code>#ref</code> may be serialized and deserialized, compromising security #loc
|
||||
@@ -1799,7 +1797,6 @@ boxing.boxed.value.quickfix=Remove unnecessary boxing
|
||||
unnecessary.javadoc.link.option=Ignore inline links to super methods
|
||||
constant.junit.assert.argument.display.name=Constant assert argument
|
||||
constant.junit.assert.argument.problem.descriptor=Argument <code>#ref</code> is constant #loc
|
||||
test.case.with.no.test.methods.option=Ignore test cases which have superclasses with test methods
|
||||
package.dot.html.may.be.package.info.display.name='package.html' may be converted to 'package-info.java'
|
||||
package.dot.html.may.be.package.info.exists.problem.descriptor=<code>package.html</code> is ignored because <code>package-info.java</code> exists
|
||||
package.dot.html.may.be.package.info.problem.descriptor=<code>package.html</code> may be converted to <code>package-info.java</code>
|
||||
|
||||
@@ -1400,10 +1400,6 @@
|
||||
groupKey="group.names.test.frameworks.issues" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.testFrameworks.SimplifiableAssertionInspection" cleanupTool="true"/>
|
||||
<inspectionElementsMerger implementation="com.siyeh.ig.testFrameworks.SimplifiableAssertionMerger"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="JUnitTestCaseWithNoTests" shortName="TestCaseWithNoTestMethods" bundle="messages.InspectionGadgetsBundle"
|
||||
key="test.case.with.no.test.methods.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.junit.TestCaseWithNoTestMethodsInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="UseOfObsoleteAssert" bundle="messages.InspectionGadgetsBundle" key="usage.of.obsolete.assert.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.junit.UseOfObsoleteAssertInspection" cleanupTool="true"/>
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.junit;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.TestFrameworks;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.options.OptPane;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.testIntegration.JavaTestFramework;
|
||||
import com.intellij.testIntegration.TestFramework;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.fixes.ChangeModifierFix;
|
||||
import org.intellij.lang.annotations.Pattern;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.intellij.codeInspection.options.OptPane.checkbox;
|
||||
import static com.intellij.codeInspection.options.OptPane.pane;
|
||||
|
||||
public class TestCaseWithNoTestMethodsInspection extends BaseInspection {
|
||||
|
||||
@SuppressWarnings("PublicField")
|
||||
public boolean ignoreSupers = true;
|
||||
|
||||
@Pattern(VALID_ID_PATTERN)
|
||||
@Override
|
||||
@NotNull
|
||||
public String getID() {
|
||||
return "JUnitTestCaseWithNoTests";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"test.case.with.no.test.methods.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable LocalQuickFix buildFix(Object... infos) {
|
||||
return (Boolean)infos[0] ? new ChangeModifierFix(PsiModifier.ABSTRACT) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull OptPane getOptionsPane() {
|
||||
return pane(
|
||||
checkbox("ignoreSupers", InspectionGadgetsBundle.message(
|
||||
"test.case.with.no.test.methods.option")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new TestCaseWithNoTestMethodsVisitor();
|
||||
}
|
||||
|
||||
private class TestCaseWithNoTestMethodsVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitClass(@NotNull PsiClass aClass) {
|
||||
if (aClass.isInterface()
|
||||
|| aClass.isEnum()
|
||||
|| aClass.isAnnotationType()
|
||||
|| PsiUtil.isLocalOrAnonymousClass(aClass)
|
||||
|| aClass.hasModifierProperty(PsiModifier.ABSTRACT)
|
||||
|| AnnotationUtil.isAnnotated(aClass, JUnitCommonClassNames.ORG_JUNIT_IGNORE, 0)) {
|
||||
return;
|
||||
}
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<TestFramework> applicableFrameworks = TestFrameworks.detectApplicableFrameworks(aClass);
|
||||
if (applicableFrameworks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<TestFramework> applicableToNestedClasses = applicableFrameworks.stream()
|
||||
.filter(framework -> framework instanceof JavaTestFramework && ((JavaTestFramework)framework).acceptNestedClasses())
|
||||
.collect(Collectors.toSet());
|
||||
if (hasTestMethods(aClass, applicableFrameworks, applicableToNestedClasses, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ignoreSupers) {
|
||||
PsiManager manager = aClass.getManager();
|
||||
PsiClass superClass = aClass.getSuperClass();
|
||||
while (superClass != null && manager.isInProject(superClass)) {
|
||||
if (hasTestMethods(superClass, applicableFrameworks, applicableToNestedClasses, false)) {
|
||||
return;
|
||||
}
|
||||
superClass = superClass.getSuperClass();
|
||||
}
|
||||
}
|
||||
registerClassError(aClass, ClassInheritorsSearch.search(aClass, aClass.getUseScope(), false).findFirst() != null);
|
||||
}
|
||||
|
||||
private static boolean hasTestMethods(@NotNull PsiClass aClass,
|
||||
Set<TestFramework> selfFrameworks,
|
||||
Set<TestFramework> nestedTestFrameworks,
|
||||
boolean checkSuite) {
|
||||
|
||||
PsiMethod[] methods = aClass.getMethods();
|
||||
|
||||
for (TestFramework framework : selfFrameworks) {
|
||||
if (checkSuite && framework instanceof JavaTestFramework && ((JavaTestFramework)framework).isSuiteClass(aClass)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ContainerUtil.exists(methods, method -> framework.isTestMethod(method, false))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nestedTestFrameworks.isEmpty()) {
|
||||
for (PsiClass innerClass : aClass.getInnerClasses()) {
|
||||
if (!innerClass.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
hasTestMethods(innerClass, nestedTestFrameworks, nestedTestFrameworks, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports non-<code>abstract</code> test cases without any test methods.
|
||||
<p>Such test cases usually indicate unfinished code
|
||||
or could be a refactoring leftover that should be removed.</p>
|
||||
<p>Example:</p>
|
||||
<pre><code>
|
||||
<b>public class</b> CrucialTest {
|
||||
@Before
|
||||
<b>public void</b> setUp() {
|
||||
System.out.println("setting up");
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<!-- tooltip end -->
|
||||
<p>Use the <b>Ignore test cases which have superclasses with test methods</b> option to ignore test cases which have super classes
|
||||
with test methods.<p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,55 +0,0 @@
|
||||
public class <warning descr="Test class 'TestCaseWithNoTestMethods' has no tests">TestCaseWithNoTestMethods</warning> extends junit.framework.TestCase {
|
||||
|
||||
public int testOne() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static void testTwo() {}
|
||||
void testThree() {}
|
||||
public void testFour(int i) {}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractTest extends junit.framework.TestCase {
|
||||
public void testInAbstract() {}
|
||||
}
|
||||
|
||||
class MyImplTest extends AbstractTest {}
|
||||
class MyImplImplTest extends MyImplTest {}
|
||||
|
||||
class NotATestClass {}
|
||||
|
||||
class MySuite {
|
||||
public static junit.framework.Test suite() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
<error descr="Class 'TestCaseWithInner' is public, should be declared in a file named 'TestCaseWithInner.java'">public class <warning descr="Test class 'TestCaseWithInner' has no tests">TestCaseWithInner</warning> extends junit.framework.TestCase</error> {
|
||||
public static class Inner extends junit.framework.TestCase {
|
||||
public void test1() {}
|
||||
}
|
||||
}
|
||||
|
||||
class Test5WithInner {
|
||||
@org.junit.jupiter.api.Nested
|
||||
class Inner {
|
||||
@org.junit.jupiter.api.Test
|
||||
void test1() {}
|
||||
}
|
||||
}
|
||||
|
||||
class <warning descr="Test class 'Test5WithInner1' has no tests">Test5WithInner1</warning> {
|
||||
@org.junit.jupiter.api.Nested
|
||||
class <warning descr="Test class 'Inner' has no tests">Inner</warning> {
|
||||
void test1() {}
|
||||
}
|
||||
}
|
||||
@org.junit.Ignore
|
||||
class IgnoredTest extends junit.framework.TestCase {}
|
||||
@@ -1,11 +0,0 @@
|
||||
<error descr="Class 'SomeTest' is public, should be declared in a file named 'SomeTest.java'">public class SomeTest extends SomeParentClass</error> {
|
||||
public SomeTest() {
|
||||
super("");
|
||||
}
|
||||
}
|
||||
|
||||
<error descr="Class 'SomeParentClass' is public, should be declared in a file named 'SomeParentClass.java'">public class SomeParentClass extends junit.framework.TestCase</error> {
|
||||
protected SomeParentClass(String name) {}
|
||||
|
||||
public void testInParent() {}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.siyeh.ig.junit;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightJavaInspectionTestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class TestCaseWithNoTestMethodsInspectionTest extends LightJavaInspectionTestCase {
|
||||
|
||||
public void testTestCaseWithNoTestMethods() { doTest(); }
|
||||
|
||||
public void testTestCaseWithTestMethods() { doTest(); }
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
TestCaseWithNoTestMethodsInspection inspection = new TestCaseWithNoTestMethodsInspection();
|
||||
inspection.ignoreSupers = true;
|
||||
return inspection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getEnvironmentClasses() {
|
||||
return new String[] {
|
||||
"package junit.framework;" +
|
||||
"public abstract class TestCase {" +
|
||||
" protected void setUp() throws Exception {}" +
|
||||
" protected void tearDown() throws Exception {}" +
|
||||
"}",
|
||||
"""
|
||||
package junit.framework;
|
||||
public interface Test {
|
||||
int countTestCases();
|
||||
void run(TestResult result);
|
||||
}""",
|
||||
"package org.junit; public @interface Ignore {}",
|
||||
"package org.junit.jupiter.api;" +
|
||||
"import org.junit.platform.commons.annotation.Testable;" +
|
||||
"@Testable\n" +
|
||||
"public @interface Test {}",
|
||||
"package org.junit.jupiter.api;" +
|
||||
"public @interface Nested {}",
|
||||
"package org.junit.platform.commons.annotation;" +
|
||||
"public @interface Testable {}"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,12 @@
|
||||
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
|
||||
key="jvm.inspections.test.method.without.assertion.display.name"
|
||||
implementationClass="com.intellij.codeInspection.test.TestMethodWithoutAssertionInspection"/>
|
||||
<localInspection language="UAST" enabledByDefault="false" level="WARNING" shortName="TestCaseWithNoTestMethods"
|
||||
suppressId="JUnitTestCaseWithNoTests"
|
||||
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
|
||||
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
|
||||
key="jvm.inspections.test.case.without.test.methods.display.name"
|
||||
implementationClass="com.intellij.codeInspection.test.TestCaseWithoutTestsInspection"/>
|
||||
<localInspection language="UAST" enabledByDefault="false" level="WARNING" shortName="TestCaseWithConstructor"
|
||||
suppressId="JUnitTestCaseWithNonTrivialConstructors"
|
||||
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports non-<code>abstract</code> test cases without any test methods. Such test cases usually indicate unfinished code or could be a
|
||||
refactoring leftover that should be removed.
|
||||
<p>Example:</p>
|
||||
<pre><code>
|
||||
public class CrucialTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
System.out.println("setting up");
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
Use the <b>Ignore test cases which have superclasses with test methods</b> option to ignore test cases which have super classes
|
||||
with test methods.
|
||||
<p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -133,6 +133,11 @@ jvm.inspections.testonly.visiblefortesting=@VisibleForTesting makes little sense
|
||||
jvm.inspections.test.method.without.assertion.display.name=Test method without assertions
|
||||
jvm.inspections.test.method.without.assertion.problem.descriptor=Test method <code>#ref()</code> contains no assertions #loc
|
||||
|
||||
jvm.inspections.test.case.without.test.methods.display.name=Test class without tests
|
||||
jvm.inspections.test.case.without.test.methods.option=Ignore test cases which have superclasses with test methods
|
||||
jvm.inspections.test.case.without.test.methods.problem.descriptor=Test class <code>#ref</code> has no tests #loc
|
||||
|
||||
|
||||
jvm.inspections.test.case.with.constructor.display.name=TestCase with non-trivial constructors
|
||||
jvm.inspections.test.case.with.constructor.problem.descriptor=Initialization logic in constructor <code>#ref()</code> instead of 'setup()' life cycle method #loc
|
||||
jvm.inspections.test.case.with.constructor.problem.descriptor.initializer=Initialization logic in initializer instead of 'setup()' life cycle method
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection.test
|
||||
|
||||
import com.intellij.analysis.JvmAnalysisBundle
|
||||
import com.intellij.codeInsight.TestFrameworks
|
||||
import com.intellij.codeInspection.options.OptPane
|
||||
import com.intellij.lang.jvm.DefaultJvmElementVisitor
|
||||
import com.intellij.lang.jvm.JvmClass
|
||||
import com.intellij.lang.jvm.JvmElementVisitor
|
||||
import com.intellij.lang.jvm.JvmModifier
|
||||
import com.intellij.lang.jvm.inspection.JvmLocalInspection
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||
import com.intellij.psi.util.PsiUtil
|
||||
import com.intellij.testIntegration.JavaTestFramework
|
||||
import com.intellij.testIntegration.TestFramework
|
||||
import com.siyeh.ig.junit.JUnitCommonClassNames
|
||||
|
||||
class TestCaseWithoutTestsInspection : JvmLocalInspection() {
|
||||
@JvmField
|
||||
var ignoreSupers = true
|
||||
|
||||
override fun getOptionsPane() = OptPane.pane(OptPane.checkbox(
|
||||
"ignoreSupers",
|
||||
JvmAnalysisBundle.message("jvm.inspections.test.case.without.test.methods.option")
|
||||
))
|
||||
|
||||
override fun buildVisitor(project: Project, sink: HighlightSink, isOnTheFly: Boolean): JvmElementVisitor<Boolean> {
|
||||
return TestCaseWithoutTestsVisitor(sink, ignoreSupers)
|
||||
}
|
||||
}
|
||||
|
||||
private class TestCaseWithoutTestsVisitor(
|
||||
private val sink: JvmLocalInspection.HighlightSink,
|
||||
private val ignoreSupers: Boolean
|
||||
) : DefaultJvmElementVisitor<Boolean> {
|
||||
override fun visitClass(clazz: JvmClass): Boolean? {
|
||||
if (clazz !is PsiClass) return true
|
||||
if (clazz is PsiTypeParameter) return true
|
||||
if (clazz.isEnum || clazz.isAnnotationType || clazz.isInterface || PsiUtil.isLocalOrAnonymousClass(clazz)) return true
|
||||
if (clazz.hasModifier(JvmModifier.ABSTRACT)) return true
|
||||
if (clazz.hasAnnotation(JUnitCommonClassNames.ORG_JUNIT_IGNORE)) return true
|
||||
|
||||
val applicableFrameworks = TestFrameworks.detectApplicableFrameworks(clazz)
|
||||
if (applicableFrameworks.isEmpty()) return true
|
||||
|
||||
val applicableToNestedClasses = applicableFrameworks
|
||||
.filter { framework -> framework is JavaTestFramework && framework.acceptNestedClasses() }
|
||||
.toSet()
|
||||
|
||||
if (hasTestMethods(clazz, applicableFrameworks, applicableToNestedClasses, true)) return true
|
||||
|
||||
if (ignoreSupers) {
|
||||
var superClass = clazz.getSuperClass()
|
||||
while (superClass != null && clazz.getManager().isInProject(superClass)) {
|
||||
if (hasTestMethods(superClass, applicableFrameworks, applicableToNestedClasses, false)) return true
|
||||
superClass = superClass.getSuperClass()
|
||||
}
|
||||
}
|
||||
|
||||
sink.highlight(JvmAnalysisBundle.message(
|
||||
"jvm.inspections.test.case.without.test.methods.problem.descriptor",
|
||||
ClassInheritorsSearch.search(clazz, clazz.getUseScope(), false).findFirst() != null
|
||||
))
|
||||
return true
|
||||
}
|
||||
|
||||
private fun hasTestMethods(
|
||||
aClass: PsiClass,
|
||||
selfFrameworks: Set<TestFramework>,
|
||||
nestedTestFrameworks: Set<TestFramework>,
|
||||
checkSuite: Boolean
|
||||
): Boolean {
|
||||
val methods = aClass.getMethods()
|
||||
for (framework in selfFrameworks) {
|
||||
if (checkSuite && framework is JavaTestFramework && framework.isSuiteClass(aClass)) return true
|
||||
if (methods.any { method ->
|
||||
framework.isTestMethod(method)
|
||||
}) return true
|
||||
}
|
||||
|
||||
if (!nestedTestFrameworks.isEmpty()) {
|
||||
for (innerClass in aClass.getInnerClasses()) {
|
||||
if (!innerClass.hasModifierProperty(PsiModifier.STATIC)
|
||||
&& hasTestMethods(innerClass, nestedTestFrameworks, nestedTestFrameworks, false)
|
||||
) return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.intellij.codeInspection.tests.java.test
|
||||
|
||||
import com.intellij.codeInspection.tests.JvmLanguage
|
||||
import com.intellij.codeInspection.tests.test.TestCaseWithoutTestsInspectionTestBase
|
||||
|
||||
class JavaTestCaseWithoutTestsInspectionTest : TestCaseWithoutTestsInspectionTestBase() {
|
||||
fun `test case without test methods`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
public class <warning descr="Test class 'TestCaseWithNoTestMethods' has no tests">TestCaseWithNoTestMethods</warning> extends junit.framework.TestCase {
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public int testOne() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static void testTwo() { }
|
||||
|
||||
void testThree() {}
|
||||
|
||||
public void testFour(int i) { }
|
||||
}
|
||||
""".trimIndent(), fileName = "TestCaseWithNoTestMethods")
|
||||
}
|
||||
|
||||
fun `test case with JUnit 3 inner class without test methods`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
public class <warning descr="Test class 'TestCaseWithInner' has no tests">TestCaseWithInner</warning> extends junit.framework.TestCase {
|
||||
public static class Inner extends junit.framework.TestCase {
|
||||
public void test1() { }
|
||||
}
|
||||
}
|
||||
""".trimIndent(), fileName = "TestCaseWithInner")
|
||||
}
|
||||
|
||||
fun `test case with JUnit 5 nested class without test methods`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
public class <warning descr="Test class 'TestCaseWithInner' has no tests">TestCaseWithInner</warning> {
|
||||
@org.junit.jupiter.api.Nested
|
||||
class <warning descr="Test class 'Inner' has no tests">Inner</warning> {
|
||||
void test1() {}
|
||||
}
|
||||
}
|
||||
""".trimIndent(), "TestCaseWithInner")
|
||||
}
|
||||
|
||||
fun `test case without test methods but class is ignored`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
@org.junit.Ignore
|
||||
public class IgnoredTest extends junit.framework.TestCase {}
|
||||
""".trimIndent(), "IgnoredTest")
|
||||
}
|
||||
|
||||
fun `test case with test in parent class`() {
|
||||
myFixture.addClass("""
|
||||
public class SomeParentClass extends junit.framework.TestCase {
|
||||
protected SomeParentClass(String name) {}
|
||||
public void testInParent() {}
|
||||
}
|
||||
""".trimIndent())
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
public class SomeTestClass extends SomeParentClass {
|
||||
public SomeTestClass() {
|
||||
super("");
|
||||
}
|
||||
}
|
||||
""".trimIndent(), "SomeTestClass")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.intellij.codeInspection.tests.kotlin.test
|
||||
|
||||
import com.intellij.codeInspection.tests.JvmLanguage
|
||||
import com.intellij.codeInspection.tests.test.TestCaseWithoutTestsInspectionTestBase
|
||||
|
||||
class KotlinTestCaseWithoutTestsInspectionTest : TestCaseWithoutTestsInspectionTestBase() {
|
||||
// Wait for KotlinJUnit framework to be fixed
|
||||
fun `_test case without test methods`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
class <warning descr="Test class 'TestCaseWithNoTestMethods' has no tests">TestCaseWithNoTestMethods</warning> : junit.framework.TestCase() {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
fun testOne(): Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
fun testThree() {}
|
||||
|
||||
fun testFour(i: Int) { i + 1 }
|
||||
}
|
||||
""".trimIndent(), fileName = "TestCaseWithNoTestMethods")
|
||||
}
|
||||
|
||||
fun `test case with JUnit 3 inner class without test methods`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
class <warning descr="Test class 'TestCaseWithInner' has no tests">TestCaseWithInner</warning> : junit.framework.TestCase() {
|
||||
class Inner : junit.framework.TestCase() {
|
||||
fun test1() {}
|
||||
}
|
||||
}
|
||||
""".trimIndent(), fileName = "TestCaseWithInner")
|
||||
}
|
||||
|
||||
// Wait for KotlinJUnit framework to be fixed
|
||||
fun `_test case with JUnit 5 nested class without test methods`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
class <warning descr="Test class 'TestCaseWithInner' has no tests">TestCaseWithInner</warning> {
|
||||
@org.junit.jupiter.api.Nested
|
||||
class <warning descr="Test class 'Inner' has no tests">Inner</warning> {
|
||||
fun test1() { }
|
||||
}
|
||||
}
|
||||
""".trimIndent(), "TestCaseWithInner")
|
||||
}
|
||||
|
||||
fun `test case without test methods but class is ignored`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
@org.junit.Ignore
|
||||
class IgnoredTest : junit.framework.TestCase() { }
|
||||
""".trimIndent(), "IgnoredTest")
|
||||
}
|
||||
|
||||
fun `test case with test in parent class`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
open class SomeParentClass(val name: String) : junit.framework.TestCase() {
|
||||
fun testInParent() { }
|
||||
}
|
||||
|
||||
class SomeTestClass : SomeParentClass("") { }
|
||||
""".trimIndent(), "SomeTestClass")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.intellij.codeInspection.tests.test
|
||||
|
||||
import com.intellij.codeInspection.test.TestCaseWithoutTestsInspection
|
||||
import com.intellij.codeInspection.tests.JvmInspectionTestBase
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.ContentEntry
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
|
||||
abstract class TestCaseWithoutTestsInspectionTestBase : JvmInspectionTestBase() {
|
||||
override val inspection: TestCaseWithoutTestsInspection = TestCaseWithoutTestsInspection()
|
||||
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor = JUnitProjectDescriptor(sdkLevel)
|
||||
|
||||
private class JUnitProjectDescriptor(languageLevel: LanguageLevel) : ProjectDescriptor(languageLevel) {
|
||||
override fun configureModule(module: Module, model: ModifiableRootModel, contentEntry: ContentEntry) {
|
||||
super.configureModule(module, model, contentEntry)
|
||||
model.addJUnit3Library()
|
||||
model.addJUnit4Library()
|
||||
model.addJUnit5Library()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,6 @@ com.siyeh.ig.j2me.OverlyLargePrimitiveArrayInitializerInspection
|
||||
com.siyeh.ig.javabeans.ClassWithoutNoArgConstructorInspection
|
||||
com.siyeh.ig.javadoc.UnnecessaryJavaDocLinkInspection
|
||||
com.siyeh.ig.jdk.AutoBoxingInspection
|
||||
com.siyeh.ig.junit.TestCaseWithNoTestMethodsInspection
|
||||
com.siyeh.ig.logging.ClassWithMultipleLoggersInspection
|
||||
com.siyeh.ig.logging.ClassWithoutLoggerInspection
|
||||
com.siyeh.ig.logging.LoggerInitializedWithForeignClassInspection
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.java.library.JavaLibraryUtil
|
||||
import com.intellij.util.Processor
|
||||
import com.intellij.util.ThreeState
|
||||
import com.intellij.util.ThreeState.*
|
||||
import org.jetbrains.kotlin.idea.base.psi.kotlinFqName
|
||||
import org.jetbrains.kotlin.idea.base.util.module
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasFqNameIndex
|
||||
@@ -62,6 +63,8 @@ abstract class AbstractKotlinPsiBasedTestFramework : KotlinPsiBasedTestFramework
|
||||
declaration.isLocal -> false
|
||||
declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) -> false
|
||||
declaration.hasModifier(KtTokens.ABSTRACT_KEYWORD) -> false
|
||||
declaration.hasModifier(KtTokens.SUSPEND_KEYWORD) -> false // suspend functions pass implicit argument
|
||||
declaration.typeReference != null && declaration.typeReference?.kotlinFqName?.asString() != "kotlin.Unit" -> false
|
||||
declaration.isExtensionDeclaration() -> false
|
||||
else -> {
|
||||
val ktClassOrObject =
|
||||
@@ -132,4 +135,8 @@ abstract class AbstractKotlinPsiBasedTestFramework : KotlinPsiBasedTestFramework
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KOTLIN_UNIT: String? = "kotlin.Unit"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user