From c6e644b8e06666897c32d7c7269b99e6626164c4 Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Thu, 23 Jun 2022 16:19:34 +0300 Subject: [PATCH] Assert nullable executions in parametrized tests with special approach --- .../constructor/tree/CgMethodConstructor.kt | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt index 6cd04f061f..c0c5265118 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt @@ -7,6 +7,7 @@ import org.utbot.framework.codegen.ForceStaticMocking import org.utbot.framework.codegen.JUNIT5_PARAMETERIZED_PACKAGE import org.utbot.framework.codegen.Junit4 import org.utbot.framework.codegen.Junit5 +import org.utbot.framework.codegen.ParametrizedTestSource import org.utbot.framework.codegen.RuntimeExceptionTestsBehaviour.PASS import org.utbot.framework.codegen.TestNg import org.utbot.framework.codegen.model.constructor.builtin.closeMethodIdOrNull @@ -996,7 +997,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c "but `${resultModel::class}` found" } - generateDeepEqualsAssertion(expected, actual) + generateDeepEqualsOrNullAssertion(expected, actual) } } } @@ -1028,16 +1029,41 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c return } - generateDeepEqualsAssertion(expected, actual) + generateDeepEqualsOrNullAssertion(expected, actual) } } } } - private fun generateDeepEqualsAssertion( + /** + * We can't use standard deepEquals method in parametrized tests + * because nullable objects require different asserts. + * See https://github.com/UnitTestBot/UTBotJava/issues/252 for more details. + */ + private fun generateDeepEqualsOrNullAssertion( expected: CgValue, - actual: CgVariable + actual: CgVariable, ) { + when (parameterizedTestSource) { + ParametrizedTestSource.DO_NOT_PARAMETRIZE -> + currentBlock = currentBlock.addAll(generateDeepEqualsAssertion(expected, actual)) + ParametrizedTestSource.PARAMETRIZE -> { + val assertNullStmt = listOf(testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement()) + currentBlock = currentBlock.add( + CgIfStatement( + CgEqualTo(expected, nullLiteral()), + assertNullStmt, + generateDeepEqualsAssertion(expected, actual) + ) + ) + } + } + } + + private fun generateDeepEqualsAssertion( + expected: CgValue, + actual: CgVariable, + ): List { require(expected is CgVariable) { "Expected value have to be Literal or Variable but `${expected::class}` found" } @@ -1051,7 +1077,8 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c depth = 0, visitedModels = hashSetOf() ) - currentBlock = currentBlock.addAll(statements.dropLastWhile { it is CgEmptyLine }) + + return statements.dropLastWhile { it is CgEmptyLine } } private fun recordActualResult() { @@ -1166,7 +1193,9 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } //TODO: orientation on arbitrary execution may be misleading, but what is the alternative? - val arbitraryExecution = utTestCase.executions.firstOrNull { it.result is UtExecutionSuccess } + //may be a heuristic to select a model with minimal number of internal nulls should be used + val arbitraryExecution = utTestCase.executions + .firstOrNull { it.result is UtExecutionSuccess && (it.result as UtExecutionSuccess).model !is UtNullModel } ?: utTestCase.executions.first() return withTestMethodScope(arbitraryExecution) { @@ -1217,7 +1246,6 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c //record result and generate result assertions recordActualResult() generateAssertionsForParameterizedTest() - } methodType = PARAMETRIZED