diff --git a/core/src/main/kotlin/org/evomaster/core/EMConfig.kt b/core/src/main/kotlin/org/evomaster/core/EMConfig.kt index 63b17a2a66..0f06b00ed3 100644 --- a/core/src/main/kotlin/org/evomaster/core/EMConfig.kt +++ b/core/src/main/kotlin/org/evomaster/core/EMConfig.kt @@ -2381,6 +2381,11 @@ class EMConfig { @Cfg("Specify the naming strategy for test cases.") var namingStrategy = defaultTestCaseNamingStrategy + @Experimental + @Cfg("Specify if true boolean query parameters are included in the test case name." + + " Used for test case naming disambiguation. Only valid for Action based naming strategy.") + var nameWithQueryParameters = false + @Experimental @Probability(true) diff --git a/core/src/main/kotlin/org/evomaster/core/output/naming/ActionTestCaseNamingStrategy.kt b/core/src/main/kotlin/org/evomaster/core/output/naming/ActionTestCaseNamingStrategy.kt index a3378ef294..c9abe2055e 100644 --- a/core/src/main/kotlin/org/evomaster/core/output/naming/ActionTestCaseNamingStrategy.kt +++ b/core/src/main/kotlin/org/evomaster/core/output/naming/ActionTestCaseNamingStrategy.kt @@ -31,6 +31,7 @@ abstract class ActionTestCaseNamingStrategy( protected val with = "with" protected val param = "Param" protected val queryParam = "query$param" + protected val and = "and" protected fun formatName(nameTokens: List): String { return "_${languageConventionFormatter.formatName(nameTokens)}" diff --git a/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt b/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt index d9a806abda..652349ad01 100644 --- a/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt +++ b/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt @@ -11,11 +11,13 @@ import org.evomaster.core.search.EvaluatedIndividual import org.evomaster.core.search.Solution import org.evomaster.core.search.action.Action import org.evomaster.core.search.action.EvaluatedAction +import org.evomaster.core.search.gene.BooleanGene import javax.ws.rs.core.MediaType open class RestActionTestCaseNamingStrategy( solution: Solution<*>, - languageConventionFormatter: LanguageConventionFormatter + languageConventionFormatter: LanguageConventionFormatter, + private val nameWithQueryParameters: Boolean, ) : ActionTestCaseNamingStrategy(solution, languageConventionFormatter) { override fun expandName(individual: EvaluatedIndividual<*>, nameTokens: MutableList, ambiguitySolver: ((Action) -> List)?): String { @@ -86,7 +88,6 @@ open class RestActionTestCaseNamingStrategy( .filter { it.value.size == 1 && !it.key.second } .mapNotNull { entry -> val eInd = entry.value[0] -// duplicatedIndividuals.remove(eInd) eInd to expandName(eInd, mutableListOf(), ::pathAmbiguitySolver) } .toMap() @@ -130,7 +131,6 @@ open class RestActionTestCaseNamingStrategy( .filter { it.value.size == 1 && it.key.isNotEmpty()} .mapNotNull { entry -> val eInd = entry.value[0] -// duplicatedIndividuals.remove(eInd) eInd to expandName(eInd, mutableListOf(), ::queryParamsAmbiguitySolver) } .toMap() @@ -147,9 +147,26 @@ open class RestActionTestCaseNamingStrategy( val queryParams = restAction.parameters.filterIsInstance() result.add(with) result.add(if (queryParams.size > 1) "${queryParam}s" else queryParam) + if (nameWithQueryParameters) { + addQueryParameterNames(queryParams, result) + } return result } + private fun addQueryParameterNames(queryParams: List, result: MutableList) { + val booleanQueryParams = getBooleanQueryParams(queryParams) + booleanQueryParams.forEachIndexed { index, queryParam -> + result.add(queryParam.name) + if (index != booleanQueryParams.lastIndex) { + result.add(and) + } + } + } + + private fun getBooleanQueryParams(queryParams: List): List { + return queryParams.filter { it.getGeneForQuery() is BooleanGene && (it.getGeneForQuery() as BooleanGene).value } + } + private fun removeSolvedDuplicates(duplicatedIndividuals: MutableSet>, disambiguatedIndividuals: Set>) { duplicatedIndividuals.removeAll(disambiguatedIndividuals) } diff --git a/core/src/main/kotlin/org/evomaster/core/output/naming/TestCaseNamingStrategyFactory.kt b/core/src/main/kotlin/org/evomaster/core/output/naming/TestCaseNamingStrategyFactory.kt index 01af4f966f..5240582ce1 100644 --- a/core/src/main/kotlin/org/evomaster/core/output/naming/TestCaseNamingStrategyFactory.kt +++ b/core/src/main/kotlin/org/evomaster/core/output/naming/TestCaseNamingStrategyFactory.kt @@ -11,10 +11,11 @@ import org.slf4j.LoggerFactory class TestCaseNamingStrategyFactory( private val namingStrategy: NamingStrategy, - private val languageConventionFormatter: LanguageConventionFormatter + private val languageConventionFormatter: LanguageConventionFormatter, + private val nameWithQueryParameters: Boolean, ) { - constructor(config: EMConfig): this(config.namingStrategy, LanguageConventionFormatter(config.outputFormat)) + constructor(config: EMConfig): this(config.namingStrategy, LanguageConventionFormatter(config.outputFormat), config.nameWithQueryParameters) companion object { private val log: Logger = LoggerFactory.getLogger(TestCaseNamingStrategyFactory::class.java) @@ -31,7 +32,7 @@ class TestCaseNamingStrategyFactory( private fun actionBasedNamingStrategy(solution: Solution<*>): NumberedTestCaseNamingStrategy { val individuals = solution.individuals return when { - individuals.any { it.individual is RestIndividual } -> return RestActionTestCaseNamingStrategy(solution, languageConventionFormatter) + individuals.any { it.individual is RestIndividual } -> return RestActionTestCaseNamingStrategy(solution, languageConventionFormatter, nameWithQueryParameters) individuals.any { it.individual is GraphQLIndividual } -> return GraphQLActionTestCaseNamingStrategy(solution, languageConventionFormatter) individuals.any { it.individual is RPCIndividual } -> return RPCActionTestCaseNamingStrategy(solution, languageConventionFormatter) individuals.any { it.individual is WebIndividual } -> { diff --git a/core/src/test/kotlin/org/evomaster/core/EMConfigTest.kt b/core/src/test/kotlin/org/evomaster/core/EMConfigTest.kt index 61e9d17522..2018c4926c 100644 --- a/core/src/test/kotlin/org/evomaster/core/EMConfigTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/EMConfigTest.kt @@ -582,7 +582,7 @@ internal class EMConfigTest{ val parser = EMConfig.getOptionParser() val config = EMConfig() - var options = parser.parse("--outputFormat", "PYTHON_UNITTEST") + val options = parser.parse("--outputFormat", "PYTHON_UNITTEST") assertThrows(Exception::class.java, {config.updateProperties(options)}) } @@ -607,4 +607,38 @@ internal class EMConfigTest{ assertEquals(NamingStrategy.NUMBERED, config.namingStrategy) } + @Test + fun testQueryParamsInTestCaseNamesValidForActionStrategy() { + val parser = EMConfig.getOptionParser() + val config = EMConfig() + + val options = parser.parse("--namingStrategy", "ACTION", "--nameWithQueryParameters", "true") + config.updateProperties(options) + + assertEquals(NamingStrategy.ACTION, config.namingStrategy) + assertTrue(config.nameWithQueryParameters) + } + + @Test + fun testQueryParamsInTestCaseNamesFalseTurnsFeatureOff() { + val parser = EMConfig.getOptionParser() + val config = EMConfig() + + val options = parser.parse("--namingStrategy", "ACTION", "--nameWithQueryParameters", "false") + config.updateProperties(options) + + assertEquals(NamingStrategy.ACTION, config.namingStrategy) + assertFalse(config.nameWithQueryParameters) + } + + @Test + fun testQueryParamsInTestCaseNamesIsOffByDefault() { + val parser = EMConfig.getOptionParser() + val config = EMConfig() + + config.updateProperties(parser.parse()) + + assertFalse(config.nameWithQueryParameters) + } + } diff --git a/core/src/test/kotlin/org/evomaster/core/output/naming/RestActionNamingStrategyTest.kt b/core/src/test/kotlin/org/evomaster/core/output/naming/RestActionNamingStrategyTest.kt index fee039d4ae..d3b396c6d9 100644 --- a/core/src/test/kotlin/org/evomaster/core/output/naming/RestActionNamingStrategyTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/output/naming/RestActionNamingStrategyTest.kt @@ -20,6 +20,7 @@ open class RestActionNamingStrategyTest { companion object { val pythonFormatter = LanguageConventionFormatter(OutputFormat.PYTHON_UNITTEST) val javaFormatter = LanguageConventionFormatter(OutputFormat.JAVA_JUNIT_4) + const val NO_QUERY_PARAMS_IN_NAME = false } @Test @@ -29,7 +30,7 @@ open class RestActionNamingStrategyTest { val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -42,7 +43,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -58,7 +59,7 @@ open class RestActionNamingStrategyTest { val itemsIndividual = getEvaluatedIndividualWith(itemsAction) val solution = Solution(mutableListOf(rootIndividual, itemsIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(2, testCases.size) @@ -72,7 +73,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -85,7 +86,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "", MediaType.TEXT_XML_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -98,7 +99,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "[]", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -111,7 +112,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "[1]", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -124,7 +125,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "[1,2,3]", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -137,7 +138,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "{}", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -150,7 +151,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "{\"key\": \"value\"}", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -163,7 +164,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 200, "\"myItem\"", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -176,7 +177,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 401, "[]", MediaType.APPLICATION_JSON_TYPE) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -189,7 +190,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWithFaults(restAction, singletonList(DetectedFault(FaultCategory.HTTP_STATUS_500, "items")), 500) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -203,7 +204,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWithFaults(restAction, faults, 500) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, pythonFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -216,7 +217,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, true) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -229,7 +230,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, withMongo = true) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -242,7 +243,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, 201, withWireMock = true) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) @@ -255,7 +256,7 @@ open class RestActionNamingStrategyTest { val eIndividual = getEvaluatedIndividualWith(restAction, withSql = true, withWireMock = true) val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(1, testCases.size) diff --git a/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt b/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt index c459fb9e03..0e1b89f36e 100644 --- a/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt @@ -6,9 +6,13 @@ import org.evomaster.core.output.naming.RestActionTestCaseUtils.getEvaluatedIndi import org.evomaster.core.output.naming.RestActionTestCaseUtils.getRestCallAction import org.evomaster.core.problem.api.param.Param import org.evomaster.core.problem.rest.HttpVerb +import org.evomaster.core.problem.rest.RestCallAction +import org.evomaster.core.problem.rest.RestIndividual import org.evomaster.core.problem.rest.param.PathParam import org.evomaster.core.problem.rest.param.QueryParam +import org.evomaster.core.search.EvaluatedIndividual import org.evomaster.core.search.Solution +import org.evomaster.core.search.gene.BooleanGene import org.evomaster.core.search.gene.optional.CustomMutationRateGene import org.evomaster.core.search.gene.string.StringGene import org.junit.jupiter.api.Assertions.assertEquals @@ -19,6 +23,8 @@ class TestCaseDisambiguationTest { companion object { val javaFormatter = LanguageConventionFormatter(OutputFormat.JAVA_JUNIT_4) + const val NO_QUERY_PARAMS_IN_NAME = false + const val QUERY_PARAMS_IN_NAME = true } @Test @@ -28,7 +34,7 @@ class TestCaseDisambiguationTest { val solution = Solution(mutableListOf(funnyPathIndividual, funniestPathIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(2, testCases.size) @@ -45,7 +51,7 @@ class TestCaseDisambiguationTest { val solution = Solution(mutableListOf(languagesIndividual, statisticsLanguagesIndividual, syntaxLanguagesIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(3, testCases.size) @@ -63,7 +69,7 @@ class TestCaseDisambiguationTest { val solution = Solution(mutableListOf(languagesIndividual, syntaxLanguagesIndividual, syntaxLanguagesIndividual2), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(3, testCases.size) @@ -84,7 +90,7 @@ class TestCaseDisambiguationTest { val solution = Solution(mutableListOf(configurationFeatureIndividual, productFeatureIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(2, testCases.size) @@ -95,11 +101,11 @@ class TestCaseDisambiguationTest { @Test fun pathWithQueryParamDisambiguation() { val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) - val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getQueryParam("myQueryParam")))) + val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getStringQueryParam("myQueryParam")))) val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividualWithQP), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(2, testCases.size) @@ -110,11 +116,11 @@ class TestCaseDisambiguationTest { @Test fun pathWithMoreThanOneQueryParamDisambiguation() { val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) - val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = mutableListOf(getQueryParam("myQueryParam"), getQueryParam("myOtherQueryParam")))) + val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = mutableListOf(getStringQueryParam("myQueryParam"), getStringQueryParam("myOtherQueryParam")))) val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividualWithQP), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(2, testCases.size) @@ -126,11 +132,11 @@ class TestCaseDisambiguationTest { fun rootPathAndQueryParamDisambiguationReturnsThreeDifferentNames() { val languagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages")) val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) - val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getQueryParam("myQueryParam")))) + val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getStringQueryParam("myQueryParam")))) val solution = Solution(mutableListOf(languagesIndividual, syntaxLanguagesIndividual, syntaxLanguagesIndividualWithQP), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) - val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter) + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, NO_QUERY_PARAMS_IN_NAME) val testCases = namingStrategy.getTestCases() assertEquals(3, testCases.size) @@ -139,12 +145,90 @@ class TestCaseDisambiguationTest { assertEquals("test_2_getOnLanguagesWithQueryParamReturnsEmpty", testCases[2].name) } + @Test + fun noQueryParamsAddedWhenNoQueryParamsInIndividual() { + val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) + val syntaxLanguagesIndividual2 = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) + + val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividual2), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) + + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME) + + val testCases = namingStrategy.getTestCases() + assertEquals(2, testCases.size) + assertEquals("test_0_getOnLanguagesReturnsEmpty", testCases[0].name) + assertEquals("test_1_getOnLanguagesReturnsEmpty", testCases[1].name) + } + + @Test + fun oneTrueBooleanQueryParamIsAdded() { + val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) + val syntaxLanguagesIndividual2 = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getBooleanQueryParam("myQueryParam")))) + ensureBooleanGeneValue(syntaxLanguagesIndividual2, "myQueryParam", "true") + + val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividual2), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) + + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME) + + val testCases = namingStrategy.getTestCases() + assertEquals(2, testCases.size) + assertEquals("test_0_getOnSyntaxLanguagesReturnsEmpty", testCases[0].name) + assertEquals("test_1_getOnLanguagesWithQueryParamMyQueryParamReturnsEmpty", testCases[1].name) + } + + @Test + fun oneFalseBooleanQueryParamIsNotAdded() { + val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) + val syntaxLanguagesIndividual2 = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getBooleanQueryParam("myQueryParam")))) + ensureBooleanGeneValue(syntaxLanguagesIndividual2, "myQueryParam", "false") + + val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividual2), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) + + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME) + + val testCases = namingStrategy.getTestCases() + assertEquals(2, testCases.size) + assertEquals("test_0_getOnSyntaxLanguagesReturnsEmpty", testCases[0].name) + assertEquals("test_1_getOnLanguagesWithQueryParamReturnsEmpty", testCases[1].name) + } + + @Test + fun onlyTrueBooleanQueryParamsAreAdded() { + val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages")) + val syntaxLanguagesIndividual2 = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = mutableListOf(getBooleanQueryParam("firstParam"), getBooleanQueryParam("secondParam"), getStringQueryParam("thirdParam"), getBooleanQueryParam("fourthParam")))) + ensureBooleanGeneValue(syntaxLanguagesIndividual2, "firstParam", "true") + ensureBooleanGeneValue(syntaxLanguagesIndividual2, "secondParam", "false") + ensureBooleanGeneValue(syntaxLanguagesIndividual2, "fourthParam", "true") + + val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividual2), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) + + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME) + + val testCases = namingStrategy.getTestCases() + assertEquals(2, testCases.size) + assertEquals("test_0_getOnSyntaxLanguagesReturnsEmpty", testCases[0].name) + assertEquals("test_1_getOnLanguagesWithQueryParamsFirstParamAndFourthParamReturnsEmpty", testCases[1].name) + } + private fun getPathParam(paramName: String): Param { return PathParam(paramName, CustomMutationRateGene(paramName, StringGene(paramName), 1.0)) } - private fun getQueryParam(paramName: String): Param { - return QueryParam(paramName, CustomMutationRateGene(paramName, StringGene(paramName), 1.0)) + private fun getStringQueryParam(paramName: String): Param { + return QueryParam(paramName, StringGene(paramName)) + } + + private fun getBooleanQueryParam(paramName: String): Param { + return QueryParam(paramName, BooleanGene(paramName)) + } + + /* + Since the randomization used to construct the evaluated individuals might set a random boolean value, + we do this to ensure the one we want for unit testing + */ + private fun ensureBooleanGeneValue(evaluatedIndividual: EvaluatedIndividual, paramName: String, paramValue: String) { + val restCallAction = evaluatedIndividual.evaluatedMainActions().last().action as RestCallAction + (restCallAction.parameters.filter { it.name == paramName }).forEach { (it as QueryParam).getGeneForQuery().setFromStringValue(paramValue) } } } diff --git a/docs/options.md b/docs/options.md index c724fb7559..ca660a25b7 100644 --- a/docs/options.md +++ b/docs/options.md @@ -249,6 +249,7 @@ There are 3 types of options: |`maxTestSizeStrategy`| __Enum__. Specify a strategy to handle a max size of a test. *Valid values*: `SPECIFIED, DPC_INCREASING, DPC_DECREASING`. *Default value*: `SPECIFIED`.| |`maxTestsPerTestSuite`| __Int__. Specify the maximum number of tests to be generated in one test suite. Note that a negative number presents no limit per test suite. *Default value*: `-1`.| |`mutationTargetsSelectionStrategy`| __Enum__. Specify a strategy to select targets for evaluating mutation. *Valid values*: `FIRST_NOT_COVERED_TARGET, EXPANDED_UPDATED_NOT_COVERED_TARGET, UPDATED_NOT_COVERED_TARGET`. *Default value*: `FIRST_NOT_COVERED_TARGET`.| +|`nameWithQueryParameters`| __Boolean__. Specify if true boolean query parameters are included in the test case name. Used for test case naming disambiguation. Only valid for Action based naming strategy. *Default value*: `false`.| |`prematureStopStrategy`| __Enum__. Specify how 'improvement' is defined: either any kind of improvement even if partial (ANY), or at least one new target is fully covered (NEW). *Valid values*: `ANY, NEW`. *Default value*: `NEW`.| |`probOfHandlingLength`| __Double__. Specify a probability of applying length handling. *Constraints*: `probability 0.0-1.0`. *Default value*: `0.0`.| |`probOfHarvestingResponsesFromActualExternalServices`| __Double__. a probability of harvesting actual responses from external services as seeds. *Constraints*: `probability 0.0-1.0`. *Default value*: `0.0`.|