From e99d17eb47dbb0600371c630cdc36b1f967750c7 Mon Sep 17 00:00:00 2001 From: Arkadii Sapozhnikov Date: Wed, 6 Sep 2023 16:03:00 +0200 Subject: [PATCH 1/3] add test execution error visualization --- .../services/TestCaseDisplayService.kt | 27 +++++++++----- .../services/TestCoverageCollectorService.kt | 15 ++++---- .../services/TestsExecutionResultService.kt | 36 ++++++++++++------- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt index fedfd9c24..96ca7e7ce 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt @@ -239,6 +239,7 @@ class TestCaseDisplayService(private val project: Project) { // Set border textFieldEditor.border = getBorder(testCase.testName) + testCasePanel.toolTipText = project.service().getError(testCase.testName) addListeners( document, @@ -249,6 +250,7 @@ class TestCaseDisplayService(private val project: Project) { checkbox, testCase, textFieldEditor.border, + testCasePanel, ) val bottomPanel = JPanel() @@ -736,7 +738,7 @@ class TestCaseDisplayService(private val project: Project) { updateTestsSelectedLabel() // Passed tests update - project.service().removeFromPassingTest(test.testName) + project.service().removeFromFailingTest(test.testName) updateTestsPassedLabel() // If no more tests are remaining, close the tool window @@ -851,6 +853,7 @@ class TestCaseDisplayService(private val project: Project) { checkbox: JCheckBox, testCase: TestCase, initialBorder: Border, + testCasePanel: JPanel, ) { document.addDocumentListener(object : DocumentListener { override fun documentChanged(event: DocumentEvent) { @@ -868,6 +871,8 @@ class TestCaseDisplayService(private val project: Project) { else -> JBUI.Borders.empty() } + testCasePanel.toolTipText = project.service().getError(testCase.testName) + val modifiedLineIndexes = getModifiedLines( lastRunCode.split("\n"), document.text.split("\n"), @@ -891,14 +896,15 @@ class TestCaseDisplayService(private val project: Project) { document.setText(testCase.testCode) project.service().updateTestCase(testCase) resetButton.isEnabled = false - resetToLastRunButton.isEnabled = false - runTestButton.isEnabled = false if ((initialBorder as MatteBorder).matteColor == JBColor.GREEN) { - project.service().addPassingTest(testCase.testName) + project.service().removeFromFailingTest(testCase.testName) } else { - project.service().removeFromPassingTest(testCase.testName) + project.service().addFailedTest(testCase.testName, testCasePanel.toolTipText) } + resetToLastRunButton.isEnabled = false + runTestButton.isEnabled = false textFieldEditor.border = initialBorder + testCasePanel.toolTipText = project.service().getError(testCase.testName) textFieldEditor.editor!!.markupModel.removeAllHighlighters() updateTestsPassedLabel() @@ -911,7 +917,10 @@ class TestCaseDisplayService(private val project: Project) { resetToLastRunButton.isEnabled = false runTestButton.isEnabled = false textFieldEditor.border = getBorder(testCase.testName) + testCasePanel.toolTipText = project.service().getError(testCase.testName) textFieldEditor.editor!!.markupModel.removeAllHighlighters() + + updateTestsPassedLabel() } } @@ -919,10 +928,10 @@ class TestCaseDisplayService(private val project: Project) { project.service().updateTestCase( project.service().updateDataWithTestCase(document.text, testCase.testName), ) - resetToLastRunButton.isEnabled = false runTestButton.isEnabled = false textFieldEditor.border = getBorder(testCase.testName) + testCasePanel.toolTipText = project.service().getError(testCase.testName) textFieldEditor.editor!!.markupModel.removeAllHighlighters() updateTestsPassedLabel() @@ -1012,10 +1021,10 @@ class TestCaseDisplayService(private val project: Project) { */ private fun getBorder(testCaseName: String): Border { val size = 3 - return if (project.service().isTestCasePassing(testCaseName)) { - MatteBorder(size, size, size, size, JBColor.GREEN) - } else { + return if (project.service().isTestCaseFailing(testCaseName)) { MatteBorder(size, size, size, size, JBColor.RED) + } else { + MatteBorder(size, size, size, size, JBColor.GREEN) } } } diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt index 8e3855d37..ab85fe7b8 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt @@ -186,11 +186,11 @@ class TestCoverageCollectorService(private val project: Project) { log.info("Test execution error message: $testExecutionError") - // add passing test - if (!getExceptionData(testExecutionError).first) { - project.service().addPassingTest(testCaseName) + // add failing test + if (getExceptionData(testExecutionError).first) { + project.service().addFailedTest(testCaseName, testExecutionError) } else { - project.service().removeFromPassingTest(testCaseName) + project.service().removeFromFailingTest(testCaseName) } // Prepare the command for generating the Jacoco report @@ -337,8 +337,9 @@ class TestCoverageCollectorService(private val project: Project) { ) // compilation checking - if (!project.service().compileCode(generatedTestPath, buildPath).first) { - project.service().removeFromPassingTest(testName) + val compilationResult = project.service().compileCode(generatedTestPath, buildPath) + if (!compilationResult.first) { + project.service().addFailedTest(testName, compilationResult.second) } else { val dataFileName = "${project.service().resultPath!!}/jacoco-${fileName.split(".")[0]}" @@ -351,7 +352,7 @@ class TestCoverageCollectorService(private val project: Project) { ) if (!File("$dataFileName.xml").exists()) { - project.service().removeFromPassingTest(testName) + project.service().addFailedTest(testName, testExecutionError) } else { val testCase = project.service().getTestCaseFromXml( testName, diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt index 7bfc9267f..41d58bc1c 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt @@ -3,39 +3,51 @@ package org.jetbrains.research.testspark.services import com.intellij.openapi.project.Project class TestsExecutionResultService(private val project: Project) { - private val passingTests: MutableSet = mutableSetOf() + // test case name --> test error + private val testErrors: MutableMap = mutableMapOf() /** - * Adds a passing test to the collection. + * Adds a failed test to the collection. * * @param testName the name of the passing test to add + * @param testError the error */ - fun addPassingTest(testName: String) { passingTests.add(testName) } + fun addFailedTest(testName: String, testError: String) { testErrors[testName] = testError } /** - * Checks if a test case with the given name is passing. + * Checks if a test case with the given name is failing. * * @param testName The name of the test case to check. * @return Returns true if the test case is passing, false otherwise. */ - fun isTestCasePassing(testName: String): Boolean = passingTests.contains(testName) + fun isTestCaseFailing(testName: String): Boolean = testErrors.contains(testName) /** - * Removes the specified test from the passing tests list. + * Removes the specified test from the failing tests list. * * @param testName The name of the test to be removed. */ - fun removeFromPassingTest(testName: String) { - if (passingTests.contains(testName)) passingTests.remove(testName) + fun removeFromFailingTest(testName: String) { + if (testErrors.contains(testName)) testErrors.remove(testName) } /** - * Number of passing tests + * Gets error message. + * + * @param testName The name of the test to be removed. + */ + fun getError(testName: String): String { + if (testErrors.contains(testName)) return testErrors[testName]!! + return "" + } + + /** + * Number of failing tests */ - fun size() = passingTests.size + fun size() = testErrors.size /** - * Clear passing tests + * Clear failing tests */ - fun clear() = passingTests.clear() + fun clear() = testErrors.clear() } From e371268c2f4633f951418b549256a84c0822fd19 Mon Sep 17 00:00:00 2001 From: Arkadii Sapozhnikov Date: Mon, 11 Sep 2023 15:31:37 +0200 Subject: [PATCH 2/3] remove === from error message --- .../research/testspark/services/TestCaseDisplayService.kt | 2 +- .../research/testspark/services/TestsExecutionResultService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt index 47d113554..becf2a4e9 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt @@ -640,7 +640,7 @@ class TestCaseDisplayService(private val project: Project) { */ private fun updateTestsPassedLabel() { testsPassedLabel.text = - String.format(testsPassedText, project.service().size(), testCasePanels.size) + String.format(testsPassedText, testCasePanels.size - project.service().size(), testCasePanels.size) } /** diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt index 41d58bc1c..c1bb03b48 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt @@ -12,7 +12,7 @@ class TestsExecutionResultService(private val project: Project) { * @param testName the name of the passing test to add * @param testError the error */ - fun addFailedTest(testName: String, testError: String) { testErrors[testName] = testError } + fun addFailedTest(testName: String, testError: String) { testErrors[testName] = testError.replace("===", "").trimEnd() } /** * Checks if a test case with the given name is failing. From 147308380d42fa6570374d95169525b9e3aec5ff Mon Sep 17 00:00:00 2001 From: Arkadii Sapozhnikov Date: Mon, 11 Sep 2023 16:07:26 +0200 Subject: [PATCH 3/3] add multiline tip --- .../testspark/services/TestsExecutionResultService.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt index c1bb03b48..8297e533a 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestsExecutionResultService.kt @@ -12,7 +12,9 @@ class TestsExecutionResultService(private val project: Project) { * @param testName the name of the passing test to add * @param testError the error */ - fun addFailedTest(testName: String, testError: String) { testErrors[testName] = testError.replace("===", "").trimEnd() } + fun addFailedTest(testName: String, testError: String) { + testErrors[testName] = "${testError.replace("===", "").replace("\t", "
").trimEnd()}" + } /** * Checks if a test case with the given name is failing.