Ir al contenido principal
Versión: 6.2 🚧

Estadísticas

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

A veces puede ser útil conocer los tipos de valores generados por Kotest, para asegurarse de que sus generadores están configurados según lo previsto. Las estadísticas de pruebas de propiedades están diseñadas para satisfacer esta necesidad.

La función collect es el punto de entrada para las estadísticas y se utiliza para contar categorías de valores. La invocamos dentro de una prueba de propiedad con la categoría que queremos incrementar.

Por ejemplo, supongamos que queremos recopilar estadísticas sobre los valores de RoundingMode usados por un BigDecimal. Invocaríamos checkAll normalmente, pasando el modo de redondeo a la función collect.

checkAll(Arb.enum<RoundingMode>(), Arb.bigDecimal()) { mode, decimal ->
collect(mode)
// test here
}

Tras completar la prueba, Kotest mostrará el nombre del test junto con los conteos y porcentajes de cada categoría:

Statistics: [collecting stats] (1000 iterations, 1 args)

HALF_DOWN 142 (14%)
HALF_UP 141 (14%)
CEILING 132 (13%)
FLOOR 122 (12%)
UP 119 (12%)
UNNECESSARY 119 (12%)
HALF_EVEN 118 (12%)
DOWN 107 (11%)

La categoría no necesita ser un enum. Puede ser cualquier objeto, y puedes envolverlo en condicionales para mayor control. Por ejemplo:

checkAll(Arb.int()) { k ->
when {
k % 2 == 0 -> collect("EVEN")
else -> collect("ODD")
}
// test here
}

Etiquetas

A veces pueden necesitarse conjuntos de estadísticas ortogonales. Por ejemplo, en una prueba numérica simple, podríamos querer confirmar que cierto porcentaje son números pares y otro porcentaje son negativos. Un enfoque sería usar EVEN_POS, EVEN_NEG, ODD_POS, ODD_NEG:

checkAll(Arb.int()) { k ->
when {
k > 0 && k % 2 == 0 -> collect("EVEN_POS")
k % 2 == 0 -> collect("EVEN_NEG")
k > 0 -> collect("ODD_POS")
else -> collect("ODD_NEG")
}
// test here
}

Esto produce un único conjunto de resultados:

EVEN_POS                                                       142 (27%)
EVEN_NEG 141 (23%)
ODD_POS 132 (24%)
ODD_NEG 122 (26%)

Sin embargo, a medida que crecen las combinaciones esto se volvería engorroso. Kotest soporta estadísticas etiquetadas, que puedes entender como conjuntos distintos de estadísticas. Para usarlas, pasa el nombre de la etiqueta como primer argumento al método collect.

checkAll(Arb.int()) { k ->
when {
k % 2 == 0 -> collect("even_odd", "EVEN")
else -> collect("even_odd", "ODD")
}
when {
k > 0 -> collect("pos_neg", "POS")
else -> collect("pos_neg", "NEG")
}
// test here
}

Ahora Kotest mostrará múltiples conjuntos de estadísticas, con el nombre de la etiqueta en el título:

Statistics: [collecting labelled stats] (1000 iterations, 1 args) [even_odd]

ODD 520 (52%)
EVEN 480 (48%)


Statistics: [collecting labelled stats] (1000 iterations, 1 args) [pos_neg]

NEG 527 (53%)
POS 473 (47%)

Modos de informe

Por defecto, las estadísticas se imprimen para cada prueba de propiedad. Existen cuatro modos configurables mediante el objeto global PropertyTesting.

Las opciones disponibles son:

ModeFunction
PropertyTesting.statisticsReportMode = StatisticsReportMode.OFFdisable all statistics reporting
PropertyTesting.statisticsReportMode = StatisticsReportMode.ONenables all statistics reporting
PropertyTesting.statisticsReportMode = StatisticsReportMode.SUCCESSoutput statistics only on successful tests
PropertyTesting.statisticsReportMode = StatisticsReportMode.FAILEDoutput statistics only on failed tests

Verificación de cobertura de estadísticas

Si deseas verificar mediante código que se generan ciertos valores, puedes especificar restricciones que deben cumplirse.

Por ejemplo, en nuestro caso anterior de redondeo, podemos comprobar que al menos el 10% de las entradas cubren HALF_DOWN y otro 10% cubren FLOOR usando withCoveragePercentages:

withCoveragePercentages(mapOf(RoundingMode.HALF_DOWN to 10.0, RoundingMode.FLOOR to 10.0)) {
checkAll(Arb.enum<RoundingMode>(), Arb.bigDecimal()) { mode, decimal ->
collect(mode)
// use the mode / decimal
}
}

Si preferimos verificar mediante números absolutos en lugar de porcentajes, usamos withCoverageCounts:

withCoverageCounts(mapOf(RoundingMode.HALF_DOWN to 75, RoundingMode.FLOOR to 75)) {
checkAll(Arb.enum<RoundingMode>(), Arb.bigDecimal()) { mode, decimal ->
collect(mode)
// use the mode / decimal
}
}

Informes personalizados

Puedes personalizar el formato de informe o generar informes a partir de los datos en bruto usando tu propia instancia de StatisticsReporter. Esto se configura mediante el objeto global PropertyTesting.

Por ejemplo:

object MyStatisticsReporter : object : StatisticsReporter { ... }
PropertyTesting.statisticsReporter = MyStatisticsReporter