Skip to content
Prev Previous commit
Next Next commit
Reorder UnitTestBot settings for clarity #1857
  • Loading branch information
Vassiliy-Kudryashov committed May 10, 2023
commit 33c041fe4d953024aeff015a312a314061244316
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.intellij.openapi.ui.DialogPanel
import com.intellij.ui.ContextHelpLabel
import com.intellij.ui.components.JBLabel
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.layout.selected
import com.intellij.ui.layout.selectedValueMatches
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.components.BorderLayoutPanel
Expand Down Expand Up @@ -36,24 +37,35 @@ class SettingsWindow(val project: Project) {
private lateinit var enableSummarizationGenerationCheckBox: JCheckBox
private lateinit var enableExperimentalLanguagesCheckBox: JCheckBox

private fun Row.createCombo(loader: KClass<*>, values: Array<*>) {
comboBox(DefaultComboBoxModel(values))
.bindItem(
getter = { settings.providerNameByServiceLoader(loader) },
setter = { settings.setProviderByLoader(loader, it as CodeGenerationSettingItem) },
).component.renderer = CodeGenerationSettingItemRenderer()
}

val panel: JPanel = panel {
row("Generated test language:") {
codegenLanguageCombo = comboBox(DefaultComboBoxModel(CodegenLanguage.values()))
codegenLanguageCombo = comboBox(DefaultComboBoxModel(CodegenLanguage.values())).gap(RightGap.COLUMNS)
.apply {
component.renderer = CodeGenerationSettingItemRenderer()
ContextHelpLabel.create("You can generate test methods in Java or Kotlin regardless of your source code language.")
}.bindItem(
getter = { settings.providerNameByServiceLoader(CodegenLanguage::class) as CodegenLanguage },
setter = { settings.setProviderByLoader(CodegenLanguage::class, it as CodeGenerationSettingItem) }
).component
component.renderer = CodeGenerationSettingItemRenderer()
ContextHelpLabel.create("You can generate test methods in Java or Kotlin regardless of your source code language.")
}.bindItem(
getter = { settings.providerNameByServiceLoader(CodegenLanguage::class) as CodegenLanguage },
setter = {
settings.setProviderByLoader(
CodegenLanguage::class,
it as CodeGenerationSettingItem
)
}
).component
codegenLanguageCombo.addActionListener {
if (!codegenLanguageCombo.item.isSummarizationCompatible()) {
enableSummarizationGenerationCheckBox.isSelected = false
}
}
}

row {
enableExperimentalLanguagesCheckBox = checkBox("Experimental languages support")
.onApply {
settings.state.enableExperimentalLanguagesSupport =
Expand All @@ -66,89 +78,7 @@ class SettingsWindow(val project: Project) {
.onIsModified { enableExperimentalLanguagesCheckBox.isSelected xor settings.experimentalLanguagesSupport }
.component
contextHelp("Enable JavaScript and Python if IDE supports them")
}

row("Hanging test timeout:") {
spinner(
range = IntRange(
HangingTestsTimeout.MIN_TIMEOUT_MS.toInt(),
HangingTestsTimeout.MAX_TIMEOUT_MS.toInt()
),
step = 50
).bindIntValue(
getter = {
settings.hangingTestsTimeout.timeoutMs
.coerceIn(HangingTestsTimeout.MIN_TIMEOUT_MS, HangingTestsTimeout.MAX_TIMEOUT_MS).toInt()
},
setter = {
settings.hangingTestsTimeout = HangingTestsTimeout(it.toLong())
}
)

label("milliseconds per method")
contextHelp(
"Set this timeout to define which test is \"hanging\". Increase it to test the " +
"time-consuming method or decrease if the execution speed is critical for you."
)
}

val valuesComboBox: (KClass<*>, Array<*>) -> Unit = { loader, values ->
val serviceLabels = mapOf(
RuntimeExceptionTestsBehaviour::class to "Tests with exceptions:",
TreatOverflowAsError::class to "Overflow detection:",
JavaDocCommentStyle::class to "Javadoc comment style:"
)

row(serviceLabels[loader] ?: error("Unknown service loader: $loader")) {
comboBox(DefaultComboBoxModel(values))
.bindItem(
getter = { settings.providerNameByServiceLoader(loader) },
setter = { settings.setProviderByLoader(loader, it as CodeGenerationSettingItem) },
).component.renderer = CodeGenerationSettingItemRenderer()
}
}

mapOf(
RuntimeExceptionTestsBehaviour::class to RuntimeExceptionTestsBehaviour.values(),
TreatOverflowAsError::class to TreatOverflowAsError.values()
).forEach { (loader, values) ->
valuesComboBox(loader, values)
}

row {
runInspectionAfterTestGenerationCheckBox = checkBox("Display detected errors on the Problems tool window")
.onApply {
settings.state.runInspectionAfterTestGeneration =
runInspectionAfterTestGenerationCheckBox.isSelected
}
.onReset {
runInspectionAfterTestGenerationCheckBox.isSelected =
settings.state.runInspectionAfterTestGeneration
}
.onIsModified {
runInspectionAfterTestGenerationCheckBox.isSelected xor settings.state.runInspectionAfterTestGeneration
}
.component
contextHelp("Automatically run code inspection after test generation")
}

row {
enableSummarizationGenerationCheckBox = checkBox("Enable summaries generation")
.onApply {
settings.state.summariesGenerationType =
if (enableSummarizationGenerationCheckBox.isSelected) SummariesGenerationType.FULL else SummariesGenerationType.NONE
}
.onReset {
enableSummarizationGenerationCheckBox.isSelected =
settings.state.summariesGenerationType != SummariesGenerationType.NONE
}
.onIsModified {
enableSummarizationGenerationCheckBox.isSelected xor (settings.state.summariesGenerationType != SummariesGenerationType.NONE)
}.enabledIf(codegenLanguageCombo.selectedValueMatches(CodegenLanguage?::isSummarizationCompatible))
.component
}

valuesComboBox(JavaDocCommentStyle::class, JavaDocCommentStyle.values())
}.bottomGap(BottomGap.MEDIUM)

row {
forceMockCheckBox = checkBox("Force mocking static methods")
Expand All @@ -161,7 +91,6 @@ class SettingsWindow(val project: Project) {
.component
contextHelp("Overrides other mocking settings")
}

row("Classes to be forcedly mocked:") {}
row {
val updater = Runnable {
Expand All @@ -177,8 +106,75 @@ class SettingsWindow(val project: Project) {
.onIsModified { excludeTable.isModified() }

forceMockCheckBox.addActionListener { updater.run() }
}.bottomGap(BottomGap.MEDIUM)

row("Tests with exceptions:") {
createCombo(RuntimeExceptionTestsBehaviour::class, RuntimeExceptionTestsBehaviour.values())
}
row("Overflow detection:") {
createCombo(TreatOverflowAsError::class, TreatOverflowAsError.values())
}
row {
enableSummarizationGenerationCheckBox = checkBox("Enable summaries generation")
.onApply {
settings.state.summariesGenerationType =
if (enableSummarizationGenerationCheckBox.isSelected) SummariesGenerationType.FULL else SummariesGenerationType.NONE
}
.onReset {
enableSummarizationGenerationCheckBox.isSelected =
settings.state.summariesGenerationType != SummariesGenerationType.NONE
}
.onIsModified {
enableSummarizationGenerationCheckBox.isSelected xor (settings.state.summariesGenerationType != SummariesGenerationType.NONE)
}.enabledIf(codegenLanguageCombo.selectedValueMatches(CodegenLanguage?::isSummarizationCompatible))
.component
}
indent {
row("Javadoc comment style:") {
createCombo(JavaDocCommentStyle::class, JavaDocCommentStyle.values())
}.enabledIf(enableSummarizationGenerationCheckBox.selected)
}
row {
runInspectionAfterTestGenerationCheckBox =
checkBox("Display detected errors on the Problems tool window")
.onApply {
settings.state.runInspectionAfterTestGeneration =
runInspectionAfterTestGenerationCheckBox.isSelected
}
.onReset {
runInspectionAfterTestGenerationCheckBox.isSelected =
settings.state.runInspectionAfterTestGeneration
}
.onIsModified {
runInspectionAfterTestGenerationCheckBox.isSelected xor settings.state.runInspectionAfterTestGeneration
}
.component
contextHelp("Automatically run code inspection after test generation")
}.bottomGap(BottomGap.MEDIUM)

row("Hanging test timeout:") {
spinner(
range = IntRange(
HangingTestsTimeout.MIN_TIMEOUT_MS.toInt(),
HangingTestsTimeout.MAX_TIMEOUT_MS.toInt()
),
step = 50
).bindIntValue(
getter = {
settings.hangingTestsTimeout.timeoutMs
.coerceIn(HangingTestsTimeout.MIN_TIMEOUT_MS, HangingTestsTimeout.MAX_TIMEOUT_MS).toInt()
},
setter = {
settings.hangingTestsTimeout = HangingTestsTimeout(it.toLong())
}
)

label("milliseconds per method")
contextHelp(
"Set this timeout to define which test is \"hanging\". Increase it to test the " +
"time-consuming method or decrease if the execution speed is critical for you."
)
}
val fuzzLabel = JBLabel("Fuzzing")
val symLabel = JBLabel("Symbolic execution")
row {
Expand All @@ -187,12 +183,13 @@ class SettingsWindow(val project: Project) {
addToLeft(JBLabel("Test generation method:").apply { verticalAlignment = SwingConstants.TOP })
addToCenter(BorderLayoutPanel().apply {
val granularity = 20
val slider = object:JSlider() {
val slider = object : JSlider() {
val updater = Runnable() {
val fuzzingPercent = 100.0 * (granularity - value) / granularity
fuzzLabel.text = "Fuzzing %.0f %%".format(fuzzingPercent)
symLabel.text = "%.0f %% Symbolic execution".format(100.0 - fuzzingPercent)
}

override fun getValue() = ((1 - settings.fuzzingValue) * granularity).toInt()

override fun setValue(n: Int) {
Expand All @@ -211,7 +208,8 @@ class SettingsWindow(val project: Project) {
slider.paintTicks = true
slider.paintTrack = true
slider.paintLabels = false
slider.toolTipText = "<html><body>While fuzzer \"guesses\" the values to enter as much execution paths as possible, symbolic executor tries to \"deduce\" them. Choose the proportion of generation time allocated for each of these methods within Test generation timeout. The slide has no effect for Spring Projects.</body></html>"
slider.toolTipText =
"<html><body>While fuzzer \"guesses\" the values to enter as much execution paths as possible, symbolic executor tries to \"deduce\" them. Choose the proportion of generation time allocated for each of these methods within Test generation timeout. The slide has no effect for Spring Projects.</body></html>"
slider.updater.run()
addToTop(slider)
addToBottom(BorderLayoutPanel().apply {
Expand Down