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

Test execution error visualization #64

Merged
merged 5 commits into from
Sep 11, 2023
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 @@ -251,6 +251,7 @@ class TestCaseDisplayService(private val project: Project) {

// Set border
languageTextField.border = getBorder(testCase.testName)
testCasePanel.toolTipText = project.service<TestsExecutionResultService>().getError(testCase.testName)

addListeners(
resetButton,
Expand All @@ -260,6 +261,7 @@ class TestCaseDisplayService(private val project: Project) {
checkbox,
testCase,
languageTextField.border,
testCasePanel,
)

val bottomPanel = JPanel()
Expand Down Expand Up @@ -638,7 +640,7 @@ class TestCaseDisplayService(private val project: Project) {
*/
private fun updateTestsPassedLabel() {
testsPassedLabel.text =
String.format(testsPassedText, project.service<TestsExecutionResultService>().size(), testCasePanels.size)
String.format(testsPassedText, testCasePanels.size - project.service<TestsExecutionResultService>().size(), testCasePanels.size)
}

/**
Expand Down Expand Up @@ -750,7 +752,7 @@ class TestCaseDisplayService(private val project: Project) {
updateTestsSelectedLabel()

// Passed tests update
project.service<TestsExecutionResultService>().removeFromPassingTest(test.testName)
project.service<TestsExecutionResultService>().removeFromFailingTest(test.testName)
updateTestsPassedLabel()

// If no more tests are remaining, close the tool window
Expand Down Expand Up @@ -863,6 +865,7 @@ class TestCaseDisplayService(private val project: Project) {
checkbox: JCheckBox,
testCase: TestCase,
initialBorder: Border,
testCasePanel: JPanel,
) {
languageTextField.document.addDocumentListener(object : DocumentListener {
override fun documentChanged(event: DocumentEvent) {
Expand All @@ -882,6 +885,8 @@ class TestCaseDisplayService(private val project: Project) {
else -> JBUI.Borders.empty()
}

testCasePanel.toolTipText = project.service<TestsExecutionResultService>().getError(testCase.testName)

val modifiedLineIndexes = getModifiedLines(
lastRunCode.split("\n"),
languageTextField.document.text.split("\n"),
Expand All @@ -905,14 +910,15 @@ class TestCaseDisplayService(private val project: Project) {
languageTextField.document.setText(testCase.testCode)
project.service<Workspace>().updateTestCase(testCase)
resetButton.isEnabled = false
resetToLastRunButton.isEnabled = false
runTestButton.isEnabled = false
if ((initialBorder as MatteBorder).matteColor == JBColor.GREEN) {
project.service<TestsExecutionResultService>().addPassingTest(testCase.testName)
project.service<TestsExecutionResultService>().removeFromFailingTest(testCase.testName)
} else {
project.service<TestsExecutionResultService>().removeFromPassingTest(testCase.testName)
project.service<TestsExecutionResultService>().addFailedTest(testCase.testName, testCasePanel.toolTipText)
}
resetToLastRunButton.isEnabled = false
runTestButton.isEnabled = false
languageTextField.border = initialBorder
testCasePanel.toolTipText = project.service<TestsExecutionResultService>().getError(testCase.testName)
languageTextField.editor!!.markupModel.removeAllHighlighters()

updateTestsPassedLabel()
Expand All @@ -925,7 +931,10 @@ class TestCaseDisplayService(private val project: Project) {
resetToLastRunButton.isEnabled = false
runTestButton.isEnabled = false
languageTextField.border = getBorder(testCase.testName)
testCasePanel.toolTipText = project.service<TestsExecutionResultService>().getError(testCase.testName)
languageTextField.editor!!.markupModel.removeAllHighlighters()

updateTestsPassedLabel()
}
}

Expand All @@ -934,10 +943,10 @@ class TestCaseDisplayService(private val project: Project) {
project.service<TestCoverageCollectorService>()
.updateDataWithTestCase(languageTextField.document.text, testCase.testName),
)

resetToLastRunButton.isEnabled = false
runTestButton.isEnabled = false
languageTextField.border = getBorder(testCase.testName)
testCasePanel.toolTipText = project.service<TestsExecutionResultService>().getError(testCase.testName)
languageTextField.editor!!.markupModel.removeAllHighlighters()

updateTestsPassedLabel()
Expand Down Expand Up @@ -1027,10 +1036,10 @@ class TestCaseDisplayService(private val project: Project) {
*/
private fun getBorder(testCaseName: String): Border {
val size = 3
return if (project.service<TestsExecutionResultService>().isTestCasePassing(testCaseName)) {
MatteBorder(size, size, size, size, JBColor.GREEN)
} else {
return if (project.service<TestsExecutionResultService>().isTestCaseFailing(testCaseName)) {
MatteBorder(size, size, size, size, JBColor.RED)
} else {
MatteBorder(size, size, size, size, JBColor.GREEN)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ class TestCoverageCollectorService(private val project: Project) {

log.info("Test execution error message: $testExecutionError")

// add passing test
if (!getExceptionData(testExecutionError).first) {
project.service<TestsExecutionResultService>().addPassingTest(testCaseName)
// add failing test
if (getExceptionData(testExecutionError).first) {
project.service<TestsExecutionResultService>().addFailedTest(testCaseName, testExecutionError)
} else {
project.service<TestsExecutionResultService>().removeFromPassingTest(testCaseName)
project.service<TestsExecutionResultService>().removeFromFailingTest(testCaseName)
}

// Prepare the command for generating the Jacoco report
Expand Down Expand Up @@ -299,8 +299,9 @@ class TestCoverageCollectorService(private val project: Project) {
)

// compilation checking
if (!project.service<TestCoverageCollectorService>().compileCode(generatedTestPath, buildPath).first) {
project.service<TestsExecutionResultService>().removeFromPassingTest(testName)
val compilationResult = project.service<TestCoverageCollectorService>().compileCode(generatedTestPath, buildPath)
if (!compilationResult.first) {
project.service<TestsExecutionResultService>().addFailedTest(testName, compilationResult.second)
} else {
val dataFileName = "${project.service<Workspace>().resultPath!!}/jacoco-${fileName.split(".")[0]}"

Expand All @@ -313,7 +314,7 @@ class TestCoverageCollectorService(private val project: Project) {
)

if (!File("$dataFileName.xml").exists()) {
project.service<TestsExecutionResultService>().removeFromPassingTest(testName)
project.service<TestsExecutionResultService>().addFailedTest(testName, testExecutionError)
} else {
val testCase = project.service<TestCoverageCollectorService>().getTestCaseFromXml(
testName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,53 @@ package org.jetbrains.research.testspark.services
import com.intellij.openapi.project.Project

class TestsExecutionResultService(private val project: Project) {
private val passingTests: MutableSet<String> = mutableSetOf()
// test case name --> test error
private val testErrors: MutableMap<String, String> = 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] = "<html>${testError.replace("===", "").replace("\t", "<br/>").trimEnd()}</html>"
}

/**
* 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 failing tests list.
*
* @param testName The name of the test to be removed.
*/
fun removeFromFailingTest(testName: String) {
if (testErrors.contains(testName)) testErrors.remove(testName)
}

/**
* Removes the specified test from the passing tests list.
* Gets error message.
*
* @param testName The name of the test to be removed.
*/
fun removeFromPassingTest(testName: String) {
if (passingTests.contains(testName)) passingTests.remove(testName)
fun getError(testName: String): String {
if (testErrors.contains(testName)) return testErrors[testName]!!
return ""
}

/**
* Number of passing tests
* 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()
}
Loading