Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add filter disabling thought config #937

Merged
merged 8 commits into from
Jun 28, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ data class FilteringConfiguration(
JsonSubTypes.Type(value = TestFilterConfiguration.AllureFilterConfiguration::class, name = "allure"),
)
sealed class TestFilterConfiguration {
@JsonProperty("enabled")
open val enabled: Boolean = true

abstract fun validate()

data class SimpleClassnameFilterConfiguration(
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -75,6 +79,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -111,6 +116,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -148,6 +154,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("subpackages") val subpackages: Boolean = false,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -184,7 +191,8 @@ sealed class TestFilterConfiguration {

data class AnnotationDataFilterConfiguration(
@JsonProperty("nameRegex") val nameRegex: Regex,
@JsonProperty("valueRegex") val valueRegex: Regex
@JsonProperty("valueRegex") val valueRegex: Regex,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {}

Expand All @@ -200,6 +208,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -235,6 +244,7 @@ sealed class TestFilterConfiguration {
data class FragmentationFilterConfiguration(
val index: Int,
val count: Int,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
if (index < 0) throw ConfigurationException("Fragment index [$index] should be >= 0")
Expand All @@ -247,6 +257,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -283,6 +294,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -317,7 +329,8 @@ sealed class TestFilterConfiguration {

data class CompositionFilterConfiguration(
@JsonProperty("filters") val filters: List<TestFilterConfiguration>,
@JsonProperty("op") val op: OPERATION
@JsonProperty("op") val op: OPERATION,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
filters.forEach { it.validate() }
Expand All @@ -342,7 +355,9 @@ sealed class TestFilterConfiguration {
override fun hashCode(): Int = filters.hashCode() + op.hashCode()
}

object AllureFilterConfiguration : TestFilterConfiguration() {
data class AllureFilterConfiguration(
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ class ConfigurationFactoryTest {
configuration.retryStrategy shouldBeEqualTo
RetryStrategyConfiguration.FixedQuotaRetryStrategyConfiguration(100, 2)

TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex()) shouldBeEqualTo
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex())
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),) shouldBeEqualTo
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),)

configuration.filteringConfiguration.allowlist shouldContainSame listOf(
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex()),
TestFilterConfiguration.SimpleClassnameFilterConfiguration(values = listOf("SimpleTest")),
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),),
TestFilterConfiguration.SimpleClassnameFilterConfiguration(values = listOf("SimpleTest"),),
TestFilterConfiguration.FullyQualifiedClassnameFilterConfiguration(".*".toRegex()),
TestFilterConfiguration.FullyQualifiedClassnameFilterConfiguration(
file = File(
Expand Down Expand Up @@ -335,7 +335,7 @@ class ConfigurationFactoryTest {
val configuration = parser.parse(file)

configuration.filteringConfiguration.allowlist shouldBeEqualTo listOf(
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex())
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),)
)

configuration.filteringConfiguration.blocklist shouldBe emptyList()
Expand All @@ -349,7 +349,7 @@ class ConfigurationFactoryTest {
configuration.filteringConfiguration.allowlist shouldBe emptyList()

configuration.filteringConfiguration.blocklist shouldBeEqualTo listOf(
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex())
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import io.qameta.allure.testfilter.TestPlanSupplier
import io.qameta.allure.testfilter.TestPlanV1_0

val ALLURE_ID_ANNOTATIONS = setOf("io.qameta.allure.AllureId", "io.qameta.allure.kotlin.AllureId")
class AllureTestFilter(val cnf: TestFilterConfiguration.AllureFilterConfiguration, private val testPlanSupplier: TestPlanSupplier = FileTestPlanSupplier()) : TestFilter {

class AllureTestFilter(
val cnf: TestFilterConfiguration.AllureFilterConfiguration,
private val testPlanSupplier: TestPlanSupplier = FileTestPlanSupplier()
) : TestFilter {
private val testPlan: TestPlan? by lazy {
val optional = testPlanSupplier.supply()
if (optional.isPresent) {
Expand All @@ -21,7 +25,7 @@ class AllureTestFilter(val cnf: TestFilterConfiguration.AllureFilterConfiguratio
}

override fun filter(tests: List<Test>): List<Test> {
return if (testPlan != null && testPlan is TestPlanV1_0) {
return if (cnf.enabled && testPlan != null && testPlan is TestPlanV1_0) {
val plan = testPlan as TestPlanV1_0
tests.filter { test ->
val allureId: String? = findAllureId(test)
Expand All @@ -31,11 +35,12 @@ class AllureTestFilter(val cnf: TestFilterConfiguration.AllureFilterConfiguratio
tests
}
}

private fun findAllureId(test: Test) =
test.metaProperties.find { ALLURE_ID_ANNOTATIONS.contains(it.name) }?.values?.get("value") as? String

override fun filterNot(tests: List<Test>): List<Test> {
return if (testPlan != null && testPlan is TestPlanV1_0) {
return if (cnf.enabled && testPlan != null && testPlan is TestPlanV1_0) {
val plan = testPlan as TestPlanV1_0
tests.filterNot { test ->
val allureId: String? = findAllureId(test)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,25 @@ import com.malinskiy.marathon.test.MetaProperty
import com.malinskiy.marathon.test.Test

data class AnnotationDataFilter(val cnf: TestFilterConfiguration.AnnotationDataFilterConfiguration) : TestFilter {
override fun filter(tests: List<Test>): List<Test> = tests.filter { test ->
test.metaProperties.any {
match(it)

override fun filter(tests: List<Test>): List<Test> = if (cnf.enabled) {
tests.filter { test ->
test.metaProperties.any {
match(it)
}
}
} else {
tests
}

override fun filterNot(tests: List<Test>): List<Test> = tests.filterNot { test ->
test.metaProperties.any {
match(it)
override fun filterNot(tests: List<Test>): List<Test> = if (cnf.enabled) {
tests.filterNot { test ->
test.metaProperties.any {
match(it)
}
}
} else {
tests
}

private fun match(metaProperty: MetaProperty): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ package com.malinskiy.marathon.execution.filter
import com.malinskiy.marathon.config.TestFilterConfiguration

class AnnotationFilter(cnf: TestFilterConfiguration.AnnotationFilterConfiguration) :
SingleValueTestFilter(cnf.regex, cnf.values, cnf.file, { test, values ->
when {
regex != null -> {
test.metaProperties.map { it.name }.any(regex::matches)
}
values != null -> {
test.metaProperties.map { it.name }.intersect(values).isNotEmpty()
}
else -> {
true
SingleValueTestFilter(
cnf.regex,
cnf.values,
cnf.file,
cnf.enabled,
{ test, values ->
when {
regex != null -> {
test.metaProperties.map { it.name }.any(regex::matches)
}

values != null -> {
test.metaProperties.map { it.name }.intersect(values).isNotEmpty()
}

else -> {
true
}
}
}
})
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,32 @@ import com.malinskiy.marathon.test.Test

class CompositionFilter(
private val filters: List<TestFilter>,
private val op: TestFilterConfiguration.CompositionFilterConfiguration.OPERATION
private val op: TestFilterConfiguration.CompositionFilterConfiguration.OPERATION,
val enabled: Boolean
) : TestFilter {

override fun filter(tests: List<Test>): List<Test> {
return when (op) {
override fun filter(tests: List<Test>): List<Test> = if (enabled) {
when (op) {
TestFilterConfiguration.CompositionFilterConfiguration.OPERATION.UNION -> filterWithUnionOperation(tests)
TestFilterConfiguration.CompositionFilterConfiguration.OPERATION.INTERSECTION -> filterWithIntersectionOperation(tests)
TestFilterConfiguration.CompositionFilterConfiguration.OPERATION.SUBTRACT -> filterWithSubtractOperation(tests)
}
} else {
tests
}

override fun filterNot(tests: List<Test>): List<Test> {
override fun filterNot(tests: List<Test>): List<Test> = if (enabled) {
val filteredTests = filter(tests)
return when (op) {
when (op) {
TestFilterConfiguration.CompositionFilterConfiguration.OPERATION.UNION -> tests.subtract(filteredTests).toList()
TestFilterConfiguration.CompositionFilterConfiguration.OPERATION.INTERSECTION -> tests.subtract(filteredTests).toList()
TestFilterConfiguration.CompositionFilterConfiguration.OPERATION.SUBTRACT -> tests.subtract(filteredTests).toList()
}
} else {
tests
}


private fun filterWithUnionOperation(tests: List<Test>): List<Test> {
return filters.fold(emptySet<Test>()) { acc, f ->
acc.union(f.filter(tests))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.math.BigInteger
class FragmentationFilter(private val cnf: TestFilterConfiguration.FragmentationFilterConfiguration) : TestFilter {
private val power by lazy { BigInteger.valueOf(cnf.count.toLong()) }
private val remainder by lazy { BigInteger.valueOf(cnf.index.toLong()) }

private val predicate: (Test) -> Boolean = {
/**
* Randomizing the distribution via md5
Expand All @@ -35,7 +36,15 @@ class FragmentationFilter(private val cnf: TestFilterConfiguration.Fragmentation
actualRemainder == remainder
}

override fun filter(tests: List<Test>): List<Test> = tests.filter(predicate)
override fun filter(tests: List<Test>): List<Test> = if (cnf.enabled) {
tests.filter(predicate)
} else {
tests
}

override fun filterNot(tests: List<Test>): List<Test> = tests.filterNot(predicate)
override fun filterNot(tests: List<Test>): List<Test> = if (cnf.enabled) {
tests.filterNot(predicate)
} else {
tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import com.malinskiy.marathon.config.TestFilterConfiguration
import com.malinskiy.marathon.test.toClassName

class FullyQualifiedClassnameFilter(cnf: TestFilterConfiguration.FullyQualifiedClassnameFilterConfiguration) :
SingleValueTestFilter(cnf.regex, cnf.values, cnf.file, { test, values ->
(regex?.matches(test.toClassName()) ?: true) && (values?.contains(test.toClassName()) ?: true)
})
SingleValueTestFilter(
cnf.regex,
cnf.values,
cnf.file,
cnf.enabled,
{ test, values ->
(regex?.matches(test.toClassName()) ?: true) && (values?.contains(test.toClassName()) ?: true)
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import com.malinskiy.marathon.config.TestFilterConfiguration
import com.malinskiy.marathon.test.toTestName

class FullyQualifiedTestnameFilter(cnf: TestFilterConfiguration.FullyQualifiedTestnameFilterConfiguration) :
SingleValueTestFilter(cnf.regex, cnf.values, cnf.file, { test, values ->
(regex?.matches(test.toTestName()) ?: true) && (values?.contains(test.toTestName()) ?: true)
})
SingleValueTestFilter(
cnf.regex,
cnf.values,
cnf.file,
cnf.enabled,
{ test, values ->
(regex?.matches(test.toTestName()) ?: true) && (values?.contains(test.toTestName()) ?: true)
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package com.malinskiy.marathon.execution.filter
import com.malinskiy.marathon.config.TestFilterConfiguration

class SimpleClassnameFilter(cnf: TestFilterConfiguration.SimpleClassnameFilterConfiguration) :
SingleValueTestFilter(cnf.regex, cnf.values, cnf.file, { test, values ->
(regex?.matches(test.clazz) ?: true) && (values?.contains(test.clazz) ?: true)
})
SingleValueTestFilter(cnf.regex,
cnf.values,
cnf.file,
cnf.enabled,
{ test, values ->
(regex?.matches(test.clazz) ?: true) && (values?.contains(test.clazz) ?: true)
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import com.malinskiy.marathon.config.TestFilterConfiguration
import com.malinskiy.marathon.test.toSimpleSafeTestName

class SimpleTestnameFilter(cnf: TestFilterConfiguration.SimpleTestnameFilterConfiguration) :
SingleValueTestFilter(cnf.regex, cnf.values, cnf.file, { test, values ->
val simpleSafeTestName = test.toSimpleSafeTestName(methodSeparator = '#')
(regex?.matches(simpleSafeTestName) ?: true) && (values?.contains(simpleSafeTestName) ?: true)
})
SingleValueTestFilter(
cnf.regex,
cnf.values,
cnf.file,
cnf.enabled,
{ test, values ->
val simpleSafeTestName = test.toSimpleSafeTestName(methodSeparator = '#')
(regex?.matches(simpleSafeTestName) ?: true) && (values?.contains(simpleSafeTestName) ?: true)
},
)
Loading
Loading