Skip to content

Commit

Permalink
Added test case naming length tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Pgarrett committed Jan 27, 2025
1 parent 6a52089 commit 5b1227d
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ abstract class ActionTestCaseNamingStrategy(
protected val wiremock = "wireMock"

protected fun formatName(nameTokens: List<String>): String {
return "_${languageConventionFormatter.formatName(nameTokens)}"
return if (nameTokens.isNotEmpty()) "_${languageConventionFormatter.formatName(nameTokens)}" else ""
}

private fun fault(faults: Set<FaultCategory>): String {
Expand Down
21 changes: 21 additions & 0 deletions core/src/test/kotlin/org/evomaster/core/EMConfigTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -641,4 +641,25 @@ internal class EMConfigTest{
assertFalse(config.nameWithQueryParameters)
}

@Test
fun testMaxCharsLengthIs80ByDefault() {
val parser = EMConfig.getOptionParser()
val config = EMConfig()

config.updateProperties(parser.parse())

assertEquals(config.maxTestCaseNameLength, 80)
}

@Test
fun testMaxCharsLengthCanBeChangedByParam() {
val parser = EMConfig.getOptionParser()
val config = EMConfig()

val options = parser.parse("--maxTestCaseNameLength", "30")
config.updateProperties(options)

assertEquals(config.maxTestCaseNameLength, 30)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ class GraphQLActionNamingStrategyTest {
assertEquals("test_0_query_on_add_causes500_internalServerError", testCases[0].name)
}

@Test
fun testActionAndMethodNameAreAddedTogether() {
val eIndividual = getEvaluatedIndividualWithFaults(GQMethodType.QUERY, singletonList(DetectedFault(FaultCategory.HTTP_STATUS_500, "items")))
val solution = Solution(singletonList(eIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList())

val withActionAndMethodName = GraphQLActionTestCaseNamingStrategy(solution, pythonFormatter, 20).getTestCases()
val noActionAndMethodName = GraphQLActionTestCaseNamingStrategy(solution, pythonFormatter, 15).getTestCases()

assertEquals(1, withActionAndMethodName.size)
assertEquals(1, noActionAndMethodName.size)
assertEquals(withActionAndMethodName[0].test, noActionAndMethodName[0].test)
assertEquals("test_0_query_on_add", withActionAndMethodName[0].name)
assertEquals("test_0", noActionAndMethodName[0].name)
}

private fun getEvaluatedIndividualWith(query: GQMethodType): EvaluatedIndividual<GraphQLIndividual> {
return getEvaluatedIndividualWithFaults(query, emptyList())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ class RPCActionNamingStrategyTest {
assertEquals("test_0_fakeRPCCallOnFunction_4ThrowsRuntimeException", testCases[0].name)
}

@Test
fun testClassAndFunctionNamesAreAddedIfAllowedByLength() {
val solution = getSolution(outputFormat, true)

val withClassAndFunctionName = RPCActionTestCaseNamingStrategy(solution, languageConventionFormatter, 30).getTestCases()
val noClassAndFunctionName = RPCActionTestCaseNamingStrategy(solution, languageConventionFormatter, 15).getTestCases()

assertEquals(1, withClassAndFunctionName.size)
assertEquals(1, noClassAndFunctionName.size)
assertEquals("test_0_fakeRPCCallOnFunction_4", withClassAndFunctionName[0].name)
assertEquals("test_0", noClassAndFunctionName[0].name)
}

private fun getSolution(outputFormat: OutputFormat, throwsException: Boolean = false): Solution<*> {
return Solution(
mutableListOf(getEvaluatedIndividual(outputFormat, throwsException)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ import org.evomaster.core.problem.externalservice.httpws.HttpExternalServiceInfo
import org.evomaster.core.problem.externalservice.httpws.HttpExternalServiceRequest
import org.evomaster.core.problem.externalservice.httpws.HttpWsExternalService
import org.evomaster.core.problem.rest.*
import org.evomaster.core.problem.rest.param.PathParam
import org.evomaster.core.problem.rest.param.QueryParam
import org.evomaster.core.problem.rest.resource.RestResourceCalls
import org.evomaster.core.search.EvaluatedIndividual
import org.evomaster.core.search.FitnessValue
import org.evomaster.core.search.GroupsOfChildren
import org.evomaster.core.search.action.ActionComponent
import org.evomaster.core.search.action.ActionResult
import org.evomaster.core.search.gene.BooleanGene
import org.evomaster.core.search.gene.Gene
import org.evomaster.core.search.gene.numeric.IntegerGene
import org.evomaster.core.search.gene.optional.CustomMutationRateGene
import org.evomaster.core.search.gene.optional.OptionalGene
import org.evomaster.core.search.gene.string.StringGene
import org.evomaster.core.search.service.Randomness
import org.evomaster.core.search.tracer.Traceable
import org.evomaster.core.sql.SqlAction
Expand Down Expand Up @@ -103,6 +111,41 @@ object RestActionTestCaseUtils {
return RestCallAction("1", verb, RestPath(path), parameters)
}

fun getPathParam(paramName: String): Param {
return PathParam(paramName, CustomMutationRateGene(paramName, StringGene(paramName), 1.0))
}

fun getStringQueryParam(paramName: String, wrapped: Boolean = true): Param {
return getQueryParam(paramName, StringGene(paramName), wrapped)
}

fun getBooleanQueryParam(paramName: String): Param {
return getQueryParam(paramName, BooleanGene(paramName))
}

fun getIntegerQueryParam(paramName: String, wrapped: Boolean = true): Param {
return getQueryParam(paramName, IntegerGene(paramName), wrapped)
}

/*
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
*/
fun ensureGeneValue(evaluatedIndividual: EvaluatedIndividual<RestIndividual>, 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)
}
}

private fun getQueryParam(paramName: String, gene: Gene, wrapped: Boolean = true): Param {
return QueryParam(paramName, if (wrapped) getWrappedGene(paramName, gene) else gene)
}

private fun getWrappedGene(paramName: String, gene: Gene): OptionalGene {
return OptionalGene(paramName, gene)
}

private fun getRestCallResult(sourceLocalId: String, statusCode: Int, resultBodyString: String, bodyType: MediaType): RestCallResult {
val restResult = RestCallResult(sourceLocalId)
restResult.setStatusCode(statusCode)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package org.evomaster.core.output.naming

import org.evomaster.core.output.OutputFormat
import org.evomaster.core.output.Termination
import org.evomaster.core.output.naming.RestActionTestCaseUtils.ensureGeneValue
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getBooleanQueryParam
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getEvaluatedIndividualWith
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getIntegerQueryParam
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getRestCallAction
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getStringQueryParam
import org.evomaster.core.output.naming.rest.RestActionTestCaseNamingStrategy
import org.evomaster.core.search.Solution
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.util.Collections.singletonList

class RestTestCaseNameLengthTest {

companion object {
val javaFormatter = LanguageConventionFormatter(OutputFormat.JAVA_JUNIT_4)
const val QUERY_PARAMS_IN_NAME = true
}

@Test
fun simpleTestWithShortNameOnlyIncludesTestNumber() {
val simpleIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages"))

val solution = Solution(mutableListOf(simpleIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList())

val testCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 10).getTestCases()

assertEquals(1, testCases.size)
assertEquals("test_0", testCases[0].name)
}

@Test
fun pathIsFavouredInsteadOfResult() {
val simpleIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages"))

val solution = Solution(mutableListOf(simpleIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList())

val longTestCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 35).getTestCases()
val shortTestCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 30).getTestCases()

assertEquals(1, longTestCases.size)
assertEquals(1, shortTestCases.size)
assertEquals(shortTestCases[0].test, longTestCases[0].test)
assertEquals("test_0_getOnLanguagesReturnsEmpty", longTestCases[0].name)
assertEquals("test_0_getOnLanguages", shortTestCases[0].name)
}

@Test
fun pathAmbiguitySolverIsFavouredInsteadOfQueryParams() {
val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages"))
val syntaxLanguagesIndividualWithQP = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = singletonList(getStringQueryParam("myQueryParam"))))
ensureGeneValue(syntaxLanguagesIndividualWithQP, "myQueryParam", "aStringValue")

val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividualWithQP), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList())

val longTestCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 80).getTestCases()
val shortTestCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 30).getTestCases()

assertEquals(2, longTestCases.size)
assertEquals(2, shortTestCases.size)
assertEquals(shortTestCases[1].test, longTestCases[1].test)
assertEquals("test_1_getOnSyntaxLanguagesWithQueryParamReturnsEmpty", longTestCases[1].name)
assertEquals("test_1_getOnSyntaxLanguages", shortTestCases[1].name)
}

@Test
fun queryParamsDisambiguationRespectsBooleanNumberStringOrder() {
val syntaxLanguagesIndividual = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages"))
val syntaxLanguagesIndividual2 = getEvaluatedIndividualWith(getRestCallAction("/syntax/languages", parameters = mutableListOf(getBooleanQueryParam("firstParam"), getStringQueryParam("secondParam"), getIntegerQueryParam("thirdParam"))))
ensureGeneValue(syntaxLanguagesIndividual2, "firstParam", "true")
ensureGeneValue(syntaxLanguagesIndividual2, "secondParam", "")
ensureGeneValue(syntaxLanguagesIndividual2, "thirdParam", "-1")

val solution = Solution(mutableListOf(syntaxLanguagesIndividual, syntaxLanguagesIndividual2), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList())

val fullNames = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 100).getTestCases()
val noParamsNames = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 50).getTestCases()
val onlyBooleanNames = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 65).getTestCases()
val booleanAndIntegerNames = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 85).getTestCases()

assertEquals(2, fullNames.size)
assertEquals(2, noParamsNames.size)
assertEquals(2, onlyBooleanNames.size)
assertEquals(2, booleanAndIntegerNames.size)
assertEquals(fullNames[1].test, noParamsNames[1].test)
assertEquals(fullNames[1].test, onlyBooleanNames[1].test)
assertEquals(fullNames[1].test, booleanAndIntegerNames[1].test)
assertEquals("test_1_getOnSyntaxLanguagesWithQueryParamsFirstParamNegativeThirdParamEmptySecondParamReturnsEmpty", fullNames[1].name)
assertEquals("test_1_getOnSyntaxLanguagesWithQueryParams", noParamsNames[1].name)
assertEquals("test_1_getOnSyntaxLanguagesWithQueryParamsFirstParamReturnsEmpty", onlyBooleanNames[1].name)
assertEquals("test_1_getOnSyntaxLanguagesWithQueryParamsFirstParamNegativeThirdParamReturnsEmpty", booleanAndIntegerNames[1].name)
}

@Test
fun sameTestRespectsMaxCharsLength() {
val simpleIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages"))
val negativeQPIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages", parameters = mutableListOf(getIntegerQueryParam("limit", false))))
ensureGeneValue(negativeQPIndividual, "limit", "-1")

val solution = Solution(mutableListOf(simpleIndividual, negativeQPIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList())

val longTestCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 80).getTestCases()
val shortTestCases = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME, 40).getTestCases()

assertEquals(2, longTestCases.size)
assertEquals(2, shortTestCases.size)
assertEquals(shortTestCases[1].test, longTestCases[1].test)
assertEquals("test_1_getOnLanguagesWithQueryParamNegativeLimitReturnsEmpty", longTestCases[1].name)
assertEquals("test_1_getOnLanguagesWithQueryParam", shortTestCases[1].name)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,16 @@ package org.evomaster.core.output.naming

import org.evomaster.core.output.OutputFormat
import org.evomaster.core.output.Termination
import org.evomaster.core.output.naming.RestActionTestCaseUtils.ensureGeneValue
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getBooleanQueryParam
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getEvaluatedIndividualWith
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getIntegerQueryParam
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getPathParam
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getRestCallAction
import org.evomaster.core.output.naming.RestActionTestCaseUtils.getStringQueryParam
import org.evomaster.core.output.naming.rest.RestActionTestCaseNamingStrategy
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.Gene
import org.evomaster.core.search.gene.numeric.IntegerGene
import org.evomaster.core.search.gene.optional.CustomMutationRateGene
import org.evomaster.core.search.gene.optional.OptionalGene
import org.evomaster.core.search.gene.string.StringGene
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.util.Collections.singletonList
Expand Down Expand Up @@ -295,39 +288,4 @@ class TestCaseDisambiguationTest {
assertEquals("test_1_getOnLanguagesWithQueryParamEmptyNameReturnsEmpty", testCases[1].name)
}

private fun getPathParam(paramName: String): Param {
return PathParam(paramName, CustomMutationRateGene(paramName, StringGene(paramName), 1.0))
}

private fun getStringQueryParam(paramName: String, wrapped: Boolean = true): Param {
return getQueryParam(paramName, StringGene(paramName), wrapped)
}

private fun getBooleanQueryParam(paramName: String): Param {
return getQueryParam(paramName, BooleanGene(paramName))
}

private fun getIntegerQueryParam(paramName: String, wrapped: Boolean = true): Param {
return getQueryParam(paramName, IntegerGene(paramName), wrapped)
}

private fun getQueryParam(paramName: String, gene: Gene, wrapped: Boolean = true): Param {
return QueryParam(paramName, if (wrapped) getWrappedGene(paramName, gene) else gene)
}

private fun getWrappedGene(paramName: String, gene: Gene): OptionalGene {
return OptionalGene(paramName, gene)
}

/*
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 ensureGeneValue(evaluatedIndividual: EvaluatedIndividual<RestIndividual>, 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)
}
}

}

0 comments on commit 5b1227d

Please sign in to comment.