Test refactoring: extract common parts from inspection tests

This commit is contained in:
Mikhail Glukhikh
2017-04-27 17:40:02 +03:00
committed by Mikhail Glukhikh
parent 6f94f45409
commit 9fca7e814f
6 changed files with 85 additions and 110 deletions
@@ -16,10 +16,9 @@
package org.jetbrains.kotlin.idea.maven package org.jetbrains.kotlin.idea.maven
import com.intellij.analysis.AnalysisScope import com.intellij.codeInspection.CommonProblemDescriptor
import com.intellij.codeInspection.* import com.intellij.codeInspection.ProblemDescriptorBase
import com.intellij.codeInspection.ex.InspectionManagerEx import com.intellij.codeInspection.QuickFix
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.ide.highlighter.JavaFileType import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.Result import com.intellij.openapi.application.Result
@@ -31,10 +30,8 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.search.FileTypeIndex import com.intellij.psi.search.FileTypeIndex
import com.intellij.testFramework.InspectionTestUtil
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
import org.jetbrains.jps.model.java.JavaSourceRootType import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.kotlin.idea.maven.inspections.DifferentKotlinMavenVersionInspection import org.jetbrains.kotlin.idea.inspections.runInspection
import org.jetbrains.kotlin.idea.maven.inspections.KotlinMavenPluginPhaseInspection import org.jetbrains.kotlin.idea.maven.inspections.KotlinMavenPluginPhaseInspection
import org.jetbrains.kotlin.idea.refactoring.toPsiDirectory import org.jetbrains.kotlin.idea.refactoring.toPsiDirectory
import org.jetbrains.kotlin.idea.util.projectStructure.allModules import org.jetbrains.kotlin.idea.util.projectStructure.allModules
@@ -67,7 +64,14 @@ abstract class AbstractKotlinMavenInspectionTest : MavenImportingTestCase() {
val matcher = "<!--\\s*problem:\\s*on\\s*([^,]+),\\s*title\\s*(.+)\\s*-->".toRegex() val matcher = "<!--\\s*problem:\\s*on\\s*([^,]+),\\s*title\\s*(.+)\\s*-->".toRegex()
val expected = pomText.lines().mapNotNull { matcher.find(it) }.map { SimplifiedProblemDescription(it.groups[2]!!.value.trim(), it.groups[1]!!.value.trim()) } val expected = pomText.lines().mapNotNull { matcher.find(it) }.map { SimplifiedProblemDescription(it.groups[2]!!.value.trim(), it.groups[1]!!.value.trim()) }
val actual = runInspection(inspectionClass).sortedBy { it.first.text } val actual = runInspection(inspectionClass, myProject)
.problemElements
.filter { it.key.name == "pom.xml" }
.values
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
.map { SimplifiedProblemDescription(it.descriptionTemplate, it.psiElement.text.replace("\\s+".toRegex(), "")) to it }
.sortedBy { it.first.text }
assertEquals(expected.sortedBy { it.text }, actual.map { it.first }) assertEquals(expected.sortedBy { it.text }, actual.map { it.first })
@@ -145,27 +149,5 @@ abstract class AbstractKotlinMavenInspectionTest : MavenImportingTestCase() {
assertTrue(FileTypeIndex.containsFileOfType(JavaFileType.INSTANCE, myProject.allModules().single().moduleScope)) assertTrue(FileTypeIndex.containsFileOfType(JavaFileType.INSTANCE, myProject.allModules().single().moduleScope))
} }
private fun runInspection(inspectionClass: Class<*>): List<Pair<SimplifiedProblemDescription, ProblemDescriptorBase>> {
val toolWrapper = LocalInspectionToolWrapper(inspectionClass.newInstance() as LocalInspectionTool)
val tool = toolWrapper.tool
if (tool is DifferentKotlinMavenVersionInspection) {
tool.testVersionMessage = "\$PLUGIN_VERSION"
}
val scope = AnalysisScope(myProject)
val inspectionManager = (InspectionManager.getInstance(myProject) as InspectionManagerEx)
val globalContext = CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, myProject, inspectionManager, toolWrapper)
InspectionTestUtil.runTool(toolWrapper, scope, globalContext)
val presentation = globalContext.getPresentation(toolWrapper)
return presentation.problemElements.filter { it.key.name == "pom.xml" }
.values
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
.map { SimplifiedProblemDescription(it.descriptionTemplate, it.psiElement.text.replace("\\s+".toRegex(), "")) to it }
}
private data class SimplifiedProblemDescription(val text: String, val elementText: String) private data class SimplifiedProblemDescription(val text: String, val elementText: String)
} }
@@ -16,20 +16,13 @@
package org.jetbrains.kotlin.idea.codeInsight package org.jetbrains.kotlin.idea.codeInsight
import com.intellij.analysis.AnalysisScope
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.codeInspection.ex.EntryPointsManagerBase import com.intellij.codeInspection.ex.EntryPointsManagerBase
import com.intellij.codeInspection.ex.InspectionManagerEx
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.testFramework.IdeaTestUtil import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.InspectionTestUtil
import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl import org.jetbrains.kotlin.idea.inspections.runInspection
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection
import org.jetbrains.kotlin.idea.test.* import org.jetbrains.kotlin.idea.test.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
@@ -63,12 +56,6 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
val options = FileUtil.loadFile(optionsFile, true) val options = FileUtil.loadFile(optionsFile, true)
val inspectionClass = Class.forName(InTextDirectivesUtils.findStringWithPrefixes(options, "// INSPECTION_CLASS: ")!!) val inspectionClass = Class.forName(InTextDirectivesUtils.findStringWithPrefixes(options, "// INSPECTION_CLASS: ")!!)
val toolWrapper = LocalInspectionToolWrapper(inspectionClass.newInstance() as LocalInspectionTool)
val tool = toolWrapper.tool
if (tool is DifferentKotlinGradleVersionInspection) {
tool.testVersionMessage = "\$PLUGIN_VERSION"
}
val fixtureClasses = InTextDirectivesUtils.findListWithPrefixes(options, "// FIXTURE_CLASS: ") val fixtureClasses = InTextDirectivesUtils.findListWithPrefixes(options, "// FIXTURE_CLASS: ")
@@ -128,17 +115,11 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
configExtra(psiFiles, options) configExtra(psiFiles, options)
val scope = AnalysisScope(project, psiFiles.map { it.virtualFile!! }) val presentation = runInspection(
scope.invalidate() inspectionClass, project, files = psiFiles.map { it.virtualFile!!}, withTestDir = inspectionsTestDir.path)
val inspectionManager = (InspectionManager.getInstance(project) as InspectionManagerEx)
val globalContext = CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, project, inspectionManager, toolWrapper)
InspectionTestUtil.runTool(toolWrapper, scope, globalContext)
InspectionTestUtil.compareToolResults(globalContext, toolWrapper, false, inspectionsTestDir.path)
if (afterFiles.isNotEmpty()) { if (afterFiles.isNotEmpty()) {
globalContext.getPresentation(toolWrapper).problemDescriptors.forEach { presentation.problemDescriptors.forEach {
problem -> problem ->
problem.fixes?.forEach { problem.fixes?.forEach {
CommandProcessor.getInstance().executeCommand(project, { CommandProcessor.getInstance().executeCommand(project, {
@@ -18,14 +18,8 @@ package org.jetbrains.kotlin.idea.codeInsight
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
import com.intellij.analysis.AnalysisScope
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.codeInspection.ex.InspectionManagerEx
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.InspectionTestUtil import org.jetbrains.kotlin.idea.inspections.runInspection
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
import org.jetbrains.kotlin.idea.jsonUtils.getString import org.jetbrains.kotlin.idea.jsonUtils.getString
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase
@@ -41,7 +35,6 @@ abstract class AbstractMultiFileInspectionTest : KotlinMultiFileTestCase() {
protected fun doTest(path: String) { protected fun doTest(path: String) {
val configFile = File(path) val configFile = File(path)
val config = JsonParser().parse(FileUtil.loadFile(configFile, true)) as JsonObject val config = JsonParser().parse(FileUtil.loadFile(configFile, true)) as JsonObject
val inspection = LocalInspectionToolWrapper(Class.forName(config.getString("inspectionClass")).newInstance() as LocalInspectionTool)
val withRuntime = config["withRuntime"]?.asBoolean ?: false val withRuntime = config["withRuntime"]?.asBoolean ?: false
val withFullJdk = config["withFullJdk"]?.asBoolean ?: false val withFullJdk = config["withFullJdk"]?.asBoolean ?: false
@@ -58,18 +51,8 @@ abstract class AbstractMultiFileInspectionTest : KotlinMultiFileTestCase() {
} }
} }
val scope = AnalysisScope(myProject) runInspection(Class.forName(config.getString("inspectionClass")), project,
scope.invalidate() withTestDir = configFile.parent)
val globalContext = CodeInsightTestFixtureImpl.createGlobalContextForTool(
scope,
myProject,
InspectionManager.getInstance(myProject) as InspectionManagerEx,
inspection
)
InspectionTestUtil.runTool(inspection, scope, globalContext)
InspectionTestUtil.compareToolResults(globalContext, inspection, false, configFile.parent)
} }
finally { finally {
if (withRuntime) { if (withRuntime) {
@@ -16,20 +16,13 @@
package org.jetbrains.kotlin.idea.codeInsight.gradle package org.jetbrains.kotlin.idea.codeInsight.gradle
import com.intellij.analysis.AnalysisScope
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalInspectionTool import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.codeInspection.ProblemDescriptorBase import com.intellij.codeInspection.ProblemDescriptorBase
import com.intellij.codeInspection.ex.InspectionManagerEx
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.openapi.util.Ref import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.InspectionTestUtil
import com.intellij.testFramework.UsefulTestCase
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
import com.intellij.testFramework.runInEdtAndWait
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection import org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection
import org.jetbrains.kotlin.idea.inspections.runInspection
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
@@ -163,18 +156,9 @@ class GradleInspectionTest : GradleImportingTestCase() {
} }
fun getInspectionResult(tool: LocalInspectionTool, file: VirtualFile): List<String> { fun getInspectionResult(tool: LocalInspectionTool, file: VirtualFile): List<String> {
val toolWrapper = LocalInspectionToolWrapper(tool)
val scope = AnalysisScope(myProject, listOf(file))
scope.invalidate()
val inspectionManager = (InspectionManager.getInstance(myProject) as InspectionManagerEx)
val globalContext = CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, myProject, inspectionManager, toolWrapper)
val resultRef = Ref<List<String>>() val resultRef = Ref<List<String>>()
invokeTestRunnable { invokeTestRunnable {
InspectionTestUtil.runTool(toolWrapper, scope, globalContext) val presentation = runInspection(tool, myProject, listOf(file))
val presentation = globalContext.getPresentation(toolWrapper)
val foundProblems = presentation.problemElements val foundProblems = presentation.problemElements
.values .values
@@ -17,14 +17,10 @@
package org.jetbrains.kotlin.idea.inspections package org.jetbrains.kotlin.idea.inspections
import com.google.common.collect.Lists import com.google.common.collect.Lists
import com.intellij.analysis.AnalysisScope
import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.InspectionTestUtil
import com.intellij.testFramework.createGlobalContextForTool
import junit.framework.ComparisonFailure import junit.framework.ComparisonFailure
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils
@@ -36,7 +32,7 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Assert import org.junit.Assert
import java.io.File import java.io.File
abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCase() { abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCase() {
protected open fun inspectionFileName(): String = ".inspection" protected open fun inspectionFileName(): String = ".inspection"
protected open fun afterFileNameSuffix(): String = ".after" protected open fun afterFileNameSuffix(): String = ".after"
@@ -74,8 +70,6 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestC
val mainFile = File(path) val mainFile = File(path)
val inspection = createInspection(mainFile) val inspection = createInspection(mainFile)
val psiFile = myFixture.configureByFiles(mainFile.name).first()
val fileText = FileUtil.loadFile(mainFile, true) val fileText = FileUtil.loadFile(mainFile, true)
TestCase.assertTrue("\"<caret>\" is missing in file \"$mainFile\"", fileText.contains("<caret>")) TestCase.assertTrue("\"<caret>\" is missing in file \"$mainFile\"", fileText.contains("<caret>"))
@@ -86,27 +80,24 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestC
DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile) DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile)
} }
doTestFor(mainFile.name, psiFile, inspection, fileText) val psiFile = myFixture.configureByFiles(mainFile.name).first()
doTestFor(mainFile.name, psiFile.virtualFile!!, inspection, fileText)
if (file is KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_AFTER")) { if (file is KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_AFTER")) {
DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile) DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile)
} }
} }
private fun doTestFor(mainFilePath: String, psiFile: PsiFile, inspection: AbstractKotlinInspection, fileText: String) { private fun doTestFor(mainFilePath: String, file: VirtualFile, inspection: AbstractKotlinInspection, fileText: String) {
val problemExpectedString = InTextDirectivesUtils.findStringWithPrefixes( val problemExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
fileText, "// ${expectedProblemDirectiveName()}: ") fileText, "// ${expectedProblemDirectiveName()}: ")
val problemExpected = problemExpectedString == null || problemExpectedString != "none" val problemExpected = problemExpectedString == null || problemExpectedString != "none"
val toolWrapper = LocalInspectionToolWrapper(inspection) val presentation = runInspection(inspection, project, listOf(file))
val scope = AnalysisScope(project, listOf(psiFile.virtualFile!!)) val problemDescriptors = presentation.problemDescriptors
scope.invalidate()
val globalContext = createGlobalContextForTool(scope, project, listOf(toolWrapper))
InspectionTestUtil.runTool(toolWrapper, scope, globalContext)
val problemDescriptors = globalContext.getPresentation(toolWrapper).problemDescriptors
.filterIsInstance<ProblemDescriptor>() .filterIsInstance<ProblemDescriptor>()
.filter { editor.caretModel.offset in it.psiElement.textRange } .filter { myFixture.caretOffset in it.psiElement.textRange }
Assert.assertTrue( Assert.assertTrue(
if (!problemExpected) if (!problemExpected)
"No problems should be detected at caret\n" + "No problems should be detected at caret\n" +
@@ -144,7 +135,6 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestC
project.executeWriteCommand(localFixAction!!.name, null) { project.executeWriteCommand(localFixAction!!.name, null) {
localFixAction.applyFix(project, problemDescriptor) localFixAction.applyFix(project, problemDescriptor)
null
} }
val canonicalPathToExpectedFile = mainFilePath + afterFileNameSuffix() val canonicalPathToExpectedFile = mainFilePath + afterFileNameSuffix()
try { try {
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* 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 org.jetbrains.kotlin.idea.inspections
import com.intellij.analysis.AnalysisScope
import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.codeInspection.ui.InspectionToolPresentation
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.InspectionTestUtil
import com.intellij.testFramework.createGlobalContextForTool
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection
import org.jetbrains.kotlin.idea.maven.inspections.DifferentKotlinMavenVersionInspection
fun runInspection(
inspection: LocalInspectionTool, project: Project, files: List<VirtualFile>? = null, withTestDir: String? = null
): InspectionToolPresentation {
val wrapper = LocalInspectionToolWrapper(inspection)
val tool = wrapper.tool
when (tool) {
is DifferentKotlinMavenVersionInspection -> tool.testVersionMessage = "\$PLUGIN_VERSION"
is DifferentKotlinGradleVersionInspection -> tool.testVersionMessage = "\$PLUGIN_VERSION"
}
val scope = if (files != null) AnalysisScope(project, files) else AnalysisScope(project)
scope.invalidate()
val globalContext = createGlobalContextForTool(scope, project, listOf(wrapper))
InspectionTestUtil.runTool(wrapper, scope, globalContext)
if (withTestDir != null) {
InspectionTestUtil.compareToolResults(globalContext, wrapper, false, withTestDir)
}
return globalContext.getPresentation(wrapper)
}
fun runInspection(
inspectionClass: Class<*>, project: Project, files: List<VirtualFile>? = null, withTestDir: String? = null
): InspectionToolPresentation {
return runInspection(inspectionClass.newInstance() as LocalInspectionTool, project, files, withTestDir)
}