Skip to content

Commit baea252

Browse files
authored
Sort tests by estimated size and exception type (#2590)
* Sort tests by estimated size and exception type * Cache `calculateSize()` for rendered executions
1 parent 27a4697 commit baea252

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractTestClassConstructor.kt

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@ import org.utbot.framework.codegen.domain.models.CgTestMethodCluster
1717
import org.utbot.framework.codegen.domain.models.CgTripleSlashMultilineComment
1818
import org.utbot.framework.codegen.domain.models.CgUtilEntity
1919
import org.utbot.framework.codegen.domain.models.CgUtilMethod
20-
import org.utbot.framework.codegen.domain.models.SimpleTestClassModel
2120
import org.utbot.framework.codegen.domain.models.TestClassModel
2221
import org.utbot.framework.codegen.renderer.importUtilMethodDependencies
2322
import org.utbot.framework.codegen.reports.TestsGenerationReport
2423
import org.utbot.framework.codegen.services.CgNameGenerator
2524
import org.utbot.framework.codegen.services.framework.TestFrameworkManager
2625
import org.utbot.framework.plugin.api.ClassId
2726
import org.utbot.framework.plugin.api.MethodId
27+
import org.utbot.framework.plugin.api.UtExecution
28+
import org.utbot.framework.plugin.api.UtExecutionFailure
29+
import org.utbot.framework.plugin.api.UtExecutionSuccess
2830
import org.utbot.framework.plugin.api.UtMethodTestSet
2931
import org.utbot.framework.plugin.api.util.description
32+
import org.utbot.framework.util.calculateSize
3033

3134
abstract class CgAbstractTestClassConstructor<T : TestClassModel>(val context: CgContext):
3235
CgContextOwner by context,
@@ -91,6 +94,12 @@ abstract class CgAbstractTestClassConstructor<T : TestClassModel>(val context: C
9194
) {
9295
val (_, _, clustersInfo) = testSet
9396

97+
// `stateAfter` is not accounted here, because usually most of it is not rendered
98+
val executionToSizeCache = testSet.executions.associateWith { execution ->
99+
execution.stateBefore.calculateSize() +
100+
((execution.result as? UtExecutionSuccess)?.model?.calculateSize() ?: 1)
101+
}
102+
94103
for ((clusterSummary, executionIndices) in clustersInfo) {
95104
val currentTestCaseTestMethods = mutableListOf<CgTestMethod>()
96105
emptyLineIfNeeded()
@@ -100,11 +109,23 @@ abstract class CgAbstractTestClassConstructor<T : TestClassModel>(val context: C
100109
executionIndices to false
101110
}
102111

103-
for (i in checkedRange) {
104-
withExecutionIdScope(i) {
105-
currentTestCaseTestMethods += methodConstructor.createTestMethod(testSet, testSet.executions[i])
112+
testSet.executions
113+
.withIndex()
114+
.toList()
115+
.slice(checkedRange)
116+
.sortedWith(
117+
// NPE tests are rendered last, because oftentimes they are meaningless in a sense
118+
// that they pass `null` somewhere where `null` is never passed in production
119+
compareBy<IndexedValue<UtExecution>> { (_, execution) ->
120+
if ((execution.result as? UtExecutionFailure)?.exception is NullPointerException) 1 else -1
121+
}
122+
// we place "smaller" tests earlier, since they are easier to read
123+
.thenComparingInt { (_, execution) -> executionToSizeCache.getValue(execution) }
124+
).forEach { (i, execution) ->
125+
withExecutionIdScope(i) {
126+
currentTestCaseTestMethods += methodConstructor.createTestMethod(testSet, execution)
127+
}
106128
}
107-
}
108129

109130
val comments = listOf("Actual number of generated tests (${executionIndices.last - executionIndices.first}) exceeds per-method limit (${UtSettings.maxTestsPerMethodInRegion})",
110131
"The limit can be configured in '{HOME_DIR}/.utbot/settings.properties' with 'maxTestsPerMethod' property")

utbot-framework/src/main/kotlin/org/utbot/framework/util/SizeUtils.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fun EnvironmentModels.calculateSize(): Int {
3535
* calculated the size for [this] model and [this] is [UtReferenceModel], then in codegen we would have already
3636
* created variable for [this] model and do not need to create it again, so size should be equal to 0.
3737
*/
38-
private fun UtModel.calculateSize(used: MutableSet<UtReferenceModel> = mutableSetOf()): Int {
38+
fun UtModel.calculateSize(used: MutableSet<UtReferenceModel> = mutableSetOf()): Int {
3939
if (this in used) return 0
4040

4141
if (this is UtReferenceModel)

0 commit comments

Comments
 (0)