From ed98f7faef3a9f67077dc9906c7ccae6dfc7bea9 Mon Sep 17 00:00:00 2001 From: Nikita Vlaev Date: Thu, 14 Jul 2022 00:12:30 +0300 Subject: [PATCH] Test report reworked (#522) Removed tsv. Sarif and detailed statistics appears only in event log. Bubble with warnings is now of warning type. --- .../org/utbot/cli/GenerateTestsCommand.kt | 2 +- .../tree/CgTestClassConstructor.kt | 88 +++++-------- .../GenerateTestsAndSarifReportFacade.kt | 1 - .../generator/CodeGenerationController.kt | 48 ++----- .../plugin/ui/GenerateTestsDialogWindow.kt | 121 +++++++++--------- .../utbot/intellij/plugin/ui/Notifications.kt | 51 ++++++-- 6 files changed, 150 insertions(+), 161 deletions(-) diff --git a/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt b/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt index c7ff55033b..0e053e59a8 100644 --- a/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt +++ b/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt @@ -145,7 +145,7 @@ class GenerateTestsCommand : SourceFindingStrategyDefault(classFqn, sourceCodeFile, testsFilePath, projectRootPath) val report = SarifReport(testCases, testClassBody, sourceFinding).createReport() saveToFile(report, sarifReport) - println("The report was saved to \"$sarifReport\". You can open it using the VS Code extension \"Sarif Viewer\".") + println("The report was saved to \"$sarifReport\".") } } } catch (t: Throwable) { diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt index 8475b4363c..d7b8f82142 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt @@ -189,9 +189,29 @@ data class TestsGenerationReport( get() = executables.firstOrNull()?.clazz ?: error("No executables found in test report") - // Summary message is generated lazily to avoid evaluation of classUnderTest - var summaryMessage: () -> String = { "Unit tests for $classUnderTest were generated successfully." } val initialWarnings: MutableList<() -> String> = mutableListOf() + val hasWarnings: Boolean + get() = initialWarnings.isNotEmpty() + + val detailedStatistics: String + get() = buildString { + appendHtmlLine("Class: ${classUnderTest.qualifiedName}") + val testMethodsStatistic = executables.map { it.countTestMethods() } + val errors = executables.map { it.countErrors() } + val overallErrors = errors.sum() + + appendHtmlLine("Successful test methods: ${testMethodsStatistic.sumBy { it.successful }}") + appendHtmlLine( + "Failing because of unexpected exception test methods: ${testMethodsStatistic.sumBy { it.failing }}" + ) + appendHtmlLine( + "Failing because of exceeding timeout test methods: ${testMethodsStatistic.sumBy { it.timeout }}" + ) + appendHtmlLine( + "Failing because of possible JVM crash test methods: ${testMethodsStatistic.sumBy { it.crashes }}" + ) + appendHtmlLine("Not generated because of internal errors test methods: $overallErrors") + } fun addMethodErrors(testCase: UtTestCase, errors: Map) { this.errors[testCase.method] = errors @@ -216,61 +236,24 @@ data class TestsGenerationReport( } } - override fun toString(): String = buildString { - appendHtmlLine(summaryMessage()) - appendHtmlLine() - initialWarnings.forEach { appendHtmlLine(it()) } - appendHtmlLine() + fun toString(isShort: Boolean): String = buildString { + appendHtmlLine("Target: ${classUnderTest.qualifiedName}") + if (initialWarnings.isNotEmpty()) { + initialWarnings.forEach { appendHtmlLine(it()) } + appendHtmlLine() + } val testMethodsStatistic = executables.map { it.countTestMethods() } - val errors = executables.map { it.countErrors() } val overallTestMethods = testMethodsStatistic.sumBy { it.count } - val overallErrors = errors.sum() + appendHtmlLine("Overall test methods: $overallTestMethods") - appendHtmlLine("Successful test methods: ${testMethodsStatistic.sumBy { it.successful }}") - appendHtmlLine( - "Failing because of unexpected exception test methods: ${testMethodsStatistic.sumBy { it.failing }}" - ) - appendHtmlLine( - "Failing because of exceeding timeout test methods: ${testMethodsStatistic.sumBy { it.timeout }}" - ) - appendHtmlLine( - "Failing because of possible JVM crash test methods: ${testMethodsStatistic.sumBy { it.crashes }}" - ) - appendHtmlLine("Not generated because of internal errors test methods: $overallErrors") - } - // TODO: should we use TsvWriter from univocity instead of this manual implementation? - fun getFileContent(): String = - (listOf(getHeader()) + getLines()).joinToString(System.lineSeparator()) - - private fun getHeader(): String { - val columnNames = listOf( - "Executable/Number of test methods", - SUCCESSFUL, - FAILING, - TIMEOUT, - CRASH, - "Errors tests" - ) - - return columnNames.joinToString(TAB_SEPARATOR) + if (!isShort) { + appendHtmlLine(detailedStatistics) + } } - private fun getLines(): List = - executables.map { executable -> - val testMethodStatistic = executable.countTestMethods() - with(testMethodStatistic) { - listOf( - executable, - successful, - failing, - timeout, - crashes, - executable.countErrors() - ).joinToString(TAB_SEPARATOR) - } - } + override fun toString(): String = toString(false) private fun UtMethod<*>.countTestMethods(): TestMethodStatistic = TestMethodStatistic( testMethodsNumber(successfulExecutions), @@ -291,9 +274,4 @@ data class TestsGenerationReport( private data class TestMethodStatistic(val successful: Int, val failing: Int, val timeout: Int, val crashes: Int) { val count: Int = successful + failing + timeout + crashes } - - companion object { - private const val TAB_SEPARATOR: String = "\t" - const val EXTENSION: String = ".tsv" - } } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/sarif/GenerateTestsAndSarifReportFacade.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/sarif/GenerateTestsAndSarifReportFacade.kt index 408756e25f..7e738861db 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/sarif/GenerateTestsAndSarifReportFacade.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/sarif/GenerateTestsAndSarifReportFacade.kt @@ -53,7 +53,6 @@ class GenerateTestsAndSarifReportFacade( mergedSarifReportFile.writeText(mergedReport) if (verbose) { println("SARIF report was saved to \"${mergedSarifReportFile.path}\"") - println("You can open it using the VS Code extension \"Sarif Viewer\"") } } } diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt index 010ee21ea7..de3b4d0bd4 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt @@ -15,7 +15,6 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable -import com.intellij.openapi.vfs.VfsUtil import com.intellij.psi.JavaDirectoryService import com.intellij.psi.PsiClass import com.intellij.psi.PsiClassOwner @@ -47,7 +46,6 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.scripting.resolve.classId import org.utbot.common.HTML_LINE_SEPARATOR -import org.utbot.common.PathUtil.classFqnToPath import org.utbot.common.PathUtil.toHtmlLinkTag import org.utbot.common.appendHtmlLine import org.utbot.framework.codegen.Import @@ -56,7 +54,6 @@ import org.utbot.framework.codegen.RegularImport import org.utbot.framework.codegen.StaticImport import org.utbot.framework.codegen.model.CodeGenerator import org.utbot.framework.codegen.model.TestsCodeWithTestReport -import org.utbot.framework.codegen.model.constructor.tree.TestsGenerationReport import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.framework.plugin.api.UtMethod import org.utbot.framework.plugin.api.UtTestCase @@ -70,16 +67,17 @@ import org.utbot.intellij.plugin.models.GenerateTestsModel import org.utbot.intellij.plugin.models.packageName import org.utbot.intellij.plugin.sarif.SarifReportIdea import org.utbot.intellij.plugin.sarif.SourceFindingStrategyIdea +import org.utbot.intellij.plugin.ui.DetailsTestsReportNotifier import org.utbot.intellij.plugin.ui.SarifReportNotifier import org.utbot.intellij.plugin.ui.TestReportUrlOpeningListener import org.utbot.intellij.plugin.ui.TestsReportNotifier +import org.utbot.intellij.plugin.ui.WarningTestsReportNotifier import org.utbot.intellij.plugin.ui.utils.getOrCreateSarifReportsPath import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath import org.utbot.intellij.plugin.ui.utils.showErrorDialogLater import org.utbot.intellij.plugin.util.signature import org.utbot.sarif.SarifReport import java.nio.file.Path -import java.nio.file.Paths import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.reflect.KClass @@ -167,7 +165,6 @@ object CodeGenerationController { SarifReportNotifier.notify( info = """ SARIF report was saved to ${toHtmlLinkTag(mergedReportFile.path)}$HTML_LINE_SEPARATOR - You can open it using the VS Code extension "Sarif Viewer" """.trimIndent() ) } @@ -394,32 +391,10 @@ object CodeGenerationController { "Test resources directory $testResourcesDirPath does not exist" } - val testReportSubDir = "utbot-tests-report" - val classFqn = with(testsCodeWithTestReport.testsGenerationReport.classUnderTest) { - qualifiedName ?: error("Could not save tests report for anonymous or local class $this") - } - val fileReportPath = classFqnToPath(classFqn) - - val resultedReportedPath = - Paths.get( - testResourcesDirPath.toString(), - testReportSubDir, - fileReportPath + "TestReport" + TestsGenerationReport.EXTENSION - ) - - val parent = resultedReportedPath.parent - requireNotNull(parent) { - "Expected from parent of $resultedReportedPath to be not null but it is null" - } - - VfsUtil.createDirectories(parent.toString()) - resultedReportedPath.toFile().writeText(testsCodeWithTestReport.testsGenerationReport.getFileContent()) - processInitialWarnings(testsCodeWithTestReport, model) val notifyMessage = buildString { - appendHtmlLine(testsCodeWithTestReport.testsGenerationReport.toString()) - appendHtmlLine() + appendHtmlLine(testsCodeWithTestReport.testsGenerationReport.toString(isShort = true)) val classUnderTestPackageName = testsCodeWithTestReport.testsGenerationReport.classUnderTest.classId.packageFqName.toString() if (classUnderTestPackageName != model.testPackageName) { @@ -430,12 +405,19 @@ object CodeGenerationController { appendHtmlLine(warningMessage) appendHtmlLine() } - val savedFileMessage = """ - Tests report was saved to ${toHtmlLinkTag(resultedReportedPath.toString())} in TSV format + val eventLogMessage = """ + See details in Event Log. """.trimIndent() - appendHtmlLine(savedFileMessage) + appendHtmlLine(eventLogMessage) + } + + if (testsCodeWithTestReport.testsGenerationReport.hasWarnings) { + WarningTestsReportNotifier.notify(notifyMessage) + } else { + TestsReportNotifier.notify(notifyMessage) } - TestsReportNotifier.notify(notifyMessage) + + DetailsTestsReportNotifier.notify(testsCodeWithTestReport.testsGenerationReport.detailedStatistics) } private fun processInitialWarnings(testsCodeWithTestReport: TestsCodeWithTestReport, model: GenerateTestsModel) { @@ -445,8 +427,6 @@ object CodeGenerationController { } testsCodeWithTestReport.testsGenerationReport.apply { - summaryMessage = { "Unit tests for $classUnderTest were generated with warnings.
" } - if (model.forceMockHappened) { initialWarnings.add { """ diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt index 4b4d1a1992..90cda951e1 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt @@ -4,35 +4,6 @@ package org.utbot.intellij.plugin.ui import com.intellij.codeInsight.hint.HintUtil import com.intellij.icons.AllIcons -import org.utbot.common.PathUtil.toPath -import org.utbot.framework.UtSettings -import org.utbot.framework.codegen.ForceStaticMocking -import org.utbot.framework.codegen.Junit4 -import org.utbot.framework.codegen.Junit5 -import org.utbot.framework.codegen.NoStaticMocking -import org.utbot.framework.codegen.ParametrizedTestSource -import org.utbot.framework.codegen.StaticsMocking -import org.utbot.framework.codegen.TestFramework -import org.utbot.framework.codegen.TestNg -import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_FILE_CONTENT -import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_STORAGE -import org.utbot.framework.codegen.model.util.MOCKITO_MOCKMAKER_FILE_NAME -import org.utbot.framework.plugin.api.CodeGenerationSettingItem -import org.utbot.framework.plugin.api.CodegenLanguage -import org.utbot.framework.plugin.api.MockFramework -import org.utbot.framework.plugin.api.MockFramework.MOCKITO -import org.utbot.framework.plugin.api.MockStrategyApi -import org.utbot.framework.plugin.api.TreatOverflowAsError -import org.utbot.intellij.plugin.settings.Settings -import org.utbot.intellij.plugin.ui.components.TestFolderComboWithBrowseButton -import org.utbot.intellij.plugin.ui.utils.LibrarySearchScope -import org.utbot.intellij.plugin.ui.utils.findFrameworkLibrary -import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath -import org.utbot.intellij.plugin.ui.utils.kotlinTargetPlatform -import org.utbot.intellij.plugin.ui.utils.parseVersion -import org.utbot.intellij.plugin.ui.utils.testResourceRootTypes -import org.utbot.intellij.plugin.ui.utils.addSourceRootIfAbsent -import org.utbot.intellij.plugin.ui.utils.testRootType import com.intellij.ide.impl.ProjectNewWindowDoNotAskOption import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.command.WriteCommandAction @@ -64,6 +35,7 @@ import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtilCore.urlToPath import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile +import com.intellij.openapi.wm.ToolWindowManager import com.intellij.psi.PsiClass import com.intellij.psi.PsiManager import com.intellij.psi.PsiMethod @@ -100,21 +72,52 @@ import com.intellij.util.ui.JBUI.Borders.merge import com.intellij.util.ui.JBUI.scale import com.intellij.util.ui.JBUI.size import com.intellij.util.ui.UIUtil +import com.intellij.util.ui.components.BorderLayoutPanel +import org.jetbrains.concurrency.Promise +import org.jetbrains.concurrency.thenRun +import org.utbot.common.PathUtil.toPath +import org.utbot.framework.UtSettings +import org.utbot.framework.codegen.ForceStaticMocking +import org.utbot.framework.codegen.Junit4 +import org.utbot.framework.codegen.Junit5 +import org.utbot.framework.codegen.NoStaticMocking +import org.utbot.framework.codegen.ParametrizedTestSource +import org.utbot.framework.codegen.StaticsMocking +import org.utbot.framework.codegen.TestFramework +import org.utbot.framework.codegen.TestNg +import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_FILE_CONTENT +import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_STORAGE +import org.utbot.framework.codegen.model.util.MOCKITO_MOCKMAKER_FILE_NAME +import org.utbot.framework.plugin.api.CodeGenerationSettingItem +import org.utbot.framework.plugin.api.CodegenLanguage +import org.utbot.framework.plugin.api.MockFramework +import org.utbot.framework.plugin.api.MockFramework.MOCKITO +import org.utbot.framework.plugin.api.MockStrategyApi +import org.utbot.framework.plugin.api.TreatOverflowAsError import org.utbot.intellij.plugin.models.GenerateTestsModel import org.utbot.intellij.plugin.models.jUnit4LibraryDescriptor import org.utbot.intellij.plugin.models.jUnit5LibraryDescriptor +import org.utbot.intellij.plugin.models.mockitoCoreLibraryDescriptor import org.utbot.intellij.plugin.models.packageName import org.utbot.intellij.plugin.models.testNgLibraryDescriptor -import com.intellij.util.ui.components.BorderLayoutPanel -import org.jetbrains.concurrency.Promise -import org.utbot.intellij.plugin.models.mockitoCoreLibraryDescriptor +import org.utbot.intellij.plugin.settings.Settings +import org.utbot.intellij.plugin.ui.components.TestFolderComboWithBrowseButton +import org.utbot.intellij.plugin.ui.utils.LibrarySearchScope +import org.utbot.intellij.plugin.ui.utils.addSourceRootIfAbsent +import org.utbot.intellij.plugin.ui.utils.allLibraries +import org.utbot.intellij.plugin.ui.utils.findFrameworkLibrary +import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath +import org.utbot.intellij.plugin.ui.utils.kotlinTargetPlatform +import org.utbot.intellij.plugin.ui.utils.parseVersion +import org.utbot.intellij.plugin.ui.utils.testResourceRootTypes +import org.utbot.intellij.plugin.ui.utils.testRootType import org.utbot.intellij.plugin.util.AndroidApiHelper import java.awt.BorderLayout import java.awt.Color import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -import java.util.Objects +import java.util.* import java.util.concurrent.TimeUnit import javax.swing.DefaultComboBoxModel import javax.swing.JComboBox @@ -122,9 +125,6 @@ import javax.swing.JComponent import javax.swing.JList import javax.swing.JPanel import kotlin.streams.toList -import org.jetbrains.concurrency.thenRun -import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass -import org.utbot.intellij.plugin.ui.utils.allLibraries private const val RECENTS_KEY = "org.utbot.recents" @@ -183,28 +183,24 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m title = "Generate tests with UtBot" setResizable(false) - TestFramework.allItems.forEach { - it.isInstalled = findFrameworkLibrary(model.project, model.testModule, it) != null - } - MockFramework.allItems.forEach { - it.isInstalled = findFrameworkLibrary(model.project, model.testModule, it) != null - } - StaticsMocking.allItems.forEach { it.isConfigured = staticsMockingConfigured() } - - // Configure notification urls callbacks - TestsReportNotifier.urlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoSuffix]?.plusAssign { + TestReportUrlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoSuffix]?.plusAssign { if (createMockFrameworkNotificationDialog() == Messages.YES) { configureMockFramework() } } - TestsReportNotifier.urlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoInlineSuffix]?.plusAssign { + TestReportUrlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoInlineSuffix]?.plusAssign { if (createStaticsMockingNotificationDialog() == Messages.YES) { configureStaticMocking() } } + TestReportUrlOpeningListener.callbacks[TestReportUrlOpeningListener.eventLogSuffix]?.plusAssign { + val twm = ToolWindowManager.getInstance(model.project) + twm.getToolWindow("Event Log")?.activate(null) + } + init() } @@ -436,7 +432,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m .toSet() val selectedMethods = selectedMembers.filter { it.member is PsiMethod }.toSet() - model.selectedMethods = if (selectedMethods.any()) selectedMethods else null + model.selectedMethods = if (selectedMethods.isEmpty()) null else selectedMethods model.testFramework = testFrameworks.item model.mockStrategy = mockStrategies.item @@ -582,6 +578,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m cbSpecifyTestPackage.isEnabled = model.srcClasses.all { cl -> cl.packageName.isNotEmpty() } val settings = model.project.service() + codegenLanguages.item = settings.codegenLanguage mockStrategies.item = settings.mockStrategy staticsMocking.item = settings.staticsMocking parametrizedTestSources.item = settings.parametrizedTestSource @@ -590,19 +587,15 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m mockStrategies.isEnabled = areMocksSupported staticsMocking.isEnabled = areMocksSupported && mockStrategies.item != MockStrategyApi.NO_MOCKS - codegenLanguages.item = - if (model.srcClasses.all { it is KtUltraLightClass }) CodegenLanguage.KOTLIN else CodegenLanguage.JAVA - - - val installedTestFramework = TestFramework.allItems.singleOrNull { it.isInstalled } + //We do not support parameterized tests for JUnit4 currentFrameworkItem = when (parametrizedTestSources.item) { - ParametrizedTestSource.DO_NOT_PARAMETRIZE -> installedTestFramework ?: settings.testFramework - ParametrizedTestSource.PARAMETRIZE -> installedTestFramework - ?: if (settings.testFramework != Junit4) settings.testFramework else TestFramework.parametrizedDefaultItem + ParametrizedTestSource.DO_NOT_PARAMETRIZE -> settings.testFramework + ParametrizedTestSource.PARAMETRIZE -> + if (settings.testFramework == Junit4) TestFramework.parametrizedDefaultItem else settings.testFramework } updateTestFrameworksList(settings.parametrizedTestSource) - updateParametrizationEnabled(currentFrameworkItem) + updateParametrizationVisibility(settings.testFramework) updateMockStrategyList() updateStaticMockingStrategyList() @@ -852,7 +845,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m val item = comboBox.item as TestFramework currentFrameworkItem = item - updateParametrizationEnabled(currentFrameworkItem) + updateParametrizationVisibility(currentFrameworkItem) } parametrizedTestSources.addActionListener { event -> @@ -902,7 +895,10 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m ParametrizedTestSource.DO_NOT_PARAMETRIZE -> TestFramework.defaultItem ParametrizedTestSource.PARAMETRIZE -> TestFramework.parametrizedDefaultItem } - enabledTestFrameworks.forEach { if (it.isInstalled && !defaultItem.isInstalled) defaultItem = it } + enabledTestFrameworks.forEach { + it.isInstalled = findFrameworkLibrary(model.project, model.testModule, it) != null + if (it.isInstalled && !defaultItem.isInstalled) defaultItem = it + } testFrameworks.model = DefaultComboBoxModel(enabledTestFrameworks.toTypedArray()) testFrameworks.item = if (currentFrameworkItem in enabledTestFrameworks) currentFrameworkItem else defaultItem @@ -922,7 +918,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m } //We would like to disable parametrization options for JUnit4 - private fun updateParametrizationEnabled(testFramework: TestFramework) { + private fun updateParametrizationVisibility(testFramework: TestFramework) { when (testFramework) { Junit4 -> parametrizedTestSources.isEnabled = false Junit5, @@ -931,6 +927,9 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m } private fun updateMockStrategyList() { + MOCKITO.isInstalled = + findFrameworkLibrary(model.project, model.testModule, MOCKITO) != null + mockStrategies.renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer( list: JList, value: MockStrategyApi?, @@ -945,6 +944,8 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m } private fun updateStaticMockingStrategyList() { + val staticsMockingConfigured = staticsMockingConfigured() + StaticsMocking.allItems.forEach { it.isConfigured = staticsMockingConfigured } staticsMocking.renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer( list: JList, value: StaticsMocking?, diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/Notifications.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/Notifications.kt index fe9c229252..0c916c0239 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/Notifications.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/Notifications.kt @@ -31,8 +31,10 @@ abstract class Notifier { .notify(project) } + protected open val notificationDisplayType = NotificationDisplayType.BALLOON + protected val notificationGroup: NotificationGroup - get() = NotificationGroup(displayId, NotificationDisplayType.BALLOON) + get() = NotificationGroup(displayId, notificationDisplayType) } abstract class WarningNotifier : Notifier() { @@ -95,7 +97,15 @@ abstract class InformationUrlNotifier : UrlNotifier() { override val notificationType: NotificationType = NotificationType.INFORMATION } -object SarifReportNotifier : InformationUrlNotifier() { +abstract class WarningUrlNotifier : UrlNotifier() { + override val notificationType: NotificationType = NotificationType.WARNING +} + +abstract class EventLogNotifier : InformationUrlNotifier() { + override val notificationDisplayType = NotificationDisplayType.NONE +} + +object SarifReportNotifier : EventLogNotifier() { override val displayId: String = "SARIF report" @@ -109,9 +119,30 @@ object SarifReportNotifier : InformationUrlNotifier() { object TestsReportNotifier : InformationUrlNotifier() { override val displayId: String = "Generated unit tests report" - override val titleText: String = "Report of the unit tests generation via UtBot" + override val titleText: String = "UTBot: unit tests generated successfully" + + public override val urlOpeningListener: TestReportUrlOpeningListener = TestReportUrlOpeningListener + + override fun content(project: Project?, module: Module?, info: String): String = info +} + +// TODO replace inheritance with decorators +object WarningTestsReportNotifier : WarningUrlNotifier() { + override val displayId: String = "Generated unit tests report" + + override val titleText: String = "UTBot: unit tests generated with warnings" + + public override val urlOpeningListener: TestReportUrlOpeningListener = TestReportUrlOpeningListener + + override fun content(project: Project?, module: Module?, info: String): String = info +} + +object DetailsTestsReportNotifier : EventLogNotifier() { + override val displayId: String = "Test report details" - public override val urlOpeningListener: TestReportUrlOpeningListener = TestReportUrlOpeningListener() + override val titleText: String = "Test report details of the unit tests generation via UtBot" + + public override val urlOpeningListener: TestReportUrlOpeningListener = TestReportUrlOpeningListener override fun content(project: Project?, module: Module?, info: String): String = info } @@ -119,16 +150,16 @@ object TestsReportNotifier : InformationUrlNotifier() { /** * Listener that handles URLs starting with [prefix], like "#utbot/configure-mockito". */ -class TestReportUrlOpeningListener: NotificationListener.Adapter() { - companion object { - const val prefix = "#utbot/" - const val mockitoSuffix = "configure-mockito" - const val mockitoInlineSuffix = "mockito-inline" - } +object TestReportUrlOpeningListener: NotificationListener.Adapter() { + const val prefix = "#utbot/" + const val mockitoSuffix = "configure-mockito" + const val mockitoInlineSuffix = "mockito-inline" + const val eventLogSuffix = "event-log" val callbacks: Map Unit>> = hashMapOf( Pair(mockitoSuffix, mutableListOf()), Pair(mockitoInlineSuffix, mutableListOf()), + Pair(eventLogSuffix, mutableListOf()), ) private val defaultListener = NotificationListener.UrlOpeningListener(false)