Skip to content

Commit

Permalink
Merge pull request #908 from MarathonLabs/feature/simple-testname-filter
Browse files Browse the repository at this point in the history
feat(core): add simple-test-name filter
  • Loading branch information
Malinskiy authored Mar 14, 2024
2 parents f1316c1 + d942a5d commit e8f9dc7
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ data class FilteringConfiguration(
name = "fully-qualified-class-name"
),
JsonSubTypes.Type(value = TestFilterConfiguration.FullyQualifiedTestnameFilterConfiguration::class, name = "fully-qualified-test-name"),
JsonSubTypes.Type(value = TestFilterConfiguration.SimpleTestnameFilterConfiguration::class, name = "simple-test-name"),
JsonSubTypes.Type(value = TestFilterConfiguration.SimpleClassnameFilterConfiguration::class, name = "simple-class-name"),
JsonSubTypes.Type(value = TestFilterConfiguration.TestMethodFilterConfiguration::class, name = "method"),
JsonSubTypes.Type(value = TestFilterConfiguration.TestPackageFilterConfiguration::class, name = "package"),
Expand Down Expand Up @@ -70,6 +71,42 @@ sealed class TestFilterConfiguration {
}
}

data class SimpleTestnameFilterConfiguration(
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
if (regex != null) i++
if (values != null) i++
if (file != null) i++

if (i > 1) throw ConfigurationException("Only one of [regex,values,file] can be specified for ${this::class.simpleName}")
if (i == 0) throw ConfigurationException("At least one of [regex,values,file] should be specified for ${this::class.simpleName}")
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as SimpleClassnameFilterConfiguration

if (!regex.toString().contentEquals(other.regex.toString())) return false
if (values != other.values) return false
if (file != other.file) return false

return true
}

override fun hashCode(): Int {
var result = regex?.hashCode() ?: 0
result = 31 * result + (values?.hashCode() ?: 0)
result = 31 * result + (file?.hashCode() ?: 0)
return result
}
}

data class FullyQualifiedClassnameFilterConfiguration(
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.malinskiy.marathon.execution.filter

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)
})
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.malinskiy.marathon.execution.filter.FragmentationFilter
import com.malinskiy.marathon.execution.filter.FullyQualifiedClassnameFilter
import com.malinskiy.marathon.execution.filter.FullyQualifiedTestnameFilter
import com.malinskiy.marathon.execution.filter.SimpleClassnameFilter
import com.malinskiy.marathon.execution.filter.SimpleTestnameFilter
import com.malinskiy.marathon.execution.filter.TestMethodFilter
import com.malinskiy.marathon.execution.filter.TestPackageFilter
import com.malinskiy.marathon.execution.strategy.BatchingStrategy
Expand Down Expand Up @@ -67,6 +68,7 @@ fun TestFilterConfiguration.toTestFilter(): TestFilter {
is TestFilterConfiguration.FullyQualifiedClassnameFilterConfiguration -> FullyQualifiedClassnameFilter(this)
is TestFilterConfiguration.FullyQualifiedTestnameFilterConfiguration -> FullyQualifiedTestnameFilter(this)
is TestFilterConfiguration.SimpleClassnameFilterConfiguration -> SimpleClassnameFilter(this)
is TestFilterConfiguration.SimpleTestnameFilterConfiguration -> SimpleTestnameFilter(this)
is TestFilterConfiguration.TestMethodFilterConfiguration -> TestMethodFilter(this)
is TestFilterConfiguration.TestPackageFilterConfiguration -> TestPackageFilter(this)
is TestFilterConfiguration.AllureFilterConfiguration -> AllureTestFilter(this)
Expand Down
8 changes: 7 additions & 1 deletion core/src/main/kotlin/com/malinskiy/marathon/test/Test.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ fun Test.toClassName(separator: Char = '.'): String {
}.toString()
}

fun Test.toSimpleSafeTestName(): String = "$clazz.$method"
fun Test.toSimpleSafeTestName(methodSeparator: Char = '.'): String {
return StringBuilder().apply {
append(clazz)
append(methodSeparator)
append(method)
}.toString()
}

fun Test.toSafeTestName() = toTestName(methodSeparator = '.')
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.malinskiy.marathon.execution.filter

import com.malinskiy.marathon.config.TestFilterConfiguration
import com.malinskiy.marathon.extension.toTestFilter
import org.amshove.kluent.shouldBeEqualTo
import org.junit.jupiter.api.Test
import com.malinskiy.marathon.test.Test as MarathonTest

class SimpleTestnameFilterTest {
private val test1 = MarathonTest("com.example", "Test", "test1", emptyList())
private val test2 = MarathonTest("com.example.subpackage", "Test2", "test2", emptyList())
private val test3 = MarathonTest("com.sample", "Test3", "test3", emptyList())
private val test4 = MarathonTest("", "Test4", "test1", emptyList())

private val filter =
TestFilterConfiguration.SimpleTestnameFilterConfiguration(values = listOf("Test2#test2")).toTestFilter()
val tests = listOf(
test1,
test2,
test3,
test4
)

@Test
fun shouldFilter() {
filter.filter(tests) shouldBeEqualTo listOf(test2)
}

@Test
fun shouldNotFilter() {
filter.filterNot(tests) shouldBeEqualTo listOf(test1, test3, test4)
}

@Test
fun shouldFilterWithRegex() {
TestFilterConfiguration.SimpleTestnameFilterConfiguration(
regex = ".+test3".toRegex()
).toTestFilter().filter(tests) shouldBeEqualTo listOf(test3)
}
}
22 changes: 13 additions & 9 deletions docs/runner/configuration/filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ Filters tests by their FQTN which is `$package.$class#$method`. The `#` sign is
### "fully-qualified-class-name"
Filters tests by their FQCN which is `$package.$class` |

### "simple-test-name"
Filters tests by using only test class name with test method, e.g. `MyTest#mySimpleTest`

### "simple-class-name"
Filters tests by using only test class name, e.g. `MyTest`

Expand All @@ -124,15 +127,16 @@ Filters tests by using allure-test-filter, [source][2]

### Gradle plugin mapping

| YAML type | Gradle class |
| --------------------------------- |:-----------------------------------------------:|
| "fully-qualified-test-name" | `FullyQualifiedTestnameFilterConfiguration` |
| "fully-qualified-class-name" | `FullyQualifiedClassnameFilterConfiguration` |
| "simple-class-name" | `SimpleClassnameFilterConfiguration` |
| "package" | `TestPackageFilterConfiguration` |
| "method" | `TestMethodFilterConfiguration` |
| "annotation" | `AnnotationFilterConfiguration` |
| "allure" | `AllureFilterConfiguration` |
| YAML type | Gradle class |
|------------------------------|:--------------------------------------------:|
| "fully-qualified-test-name" | `FullyQualifiedTestnameFilterConfiguration` |
| "fully-qualified-class-name" | `FullyQualifiedClassnameFilterConfiguration` |
| "simple-test-name" | `SimpleTestnameFilterConfiguration` |
| "simple-class-name" | `SimpleClassnameFilterConfiguration` |
| "package" | `TestPackageFilterConfiguration` |
| "method" | `TestMethodFilterConfiguration` |
| "annotation" | `AnnotationFilterConfiguration` |
| "allure" | `AllureFilterConfiguration` |

:::caution

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ open class MarathonExtension {
* | "fully-qualified-test-name" | `FullyQualifiedTestnameFilterConfiguration` | Filters tests by their FQTN which is `$package.$class#$method`. The `#` sign is important! |
* | "fully-qualified-class-name" | `FullyQualifiedClassnameFilterConfiguration` | Filters tests by their FQCN which is `$package.$class` |
* | "simple-class-name" | `SimpleClassnameFilterConfiguration` | Filters tests by using only test class name, e.g. `MyTest` |
* | "simple-test-name" | `SimpleTestnameFilterConfiguration` | Filters tests by using only test class name with test method, e.g. `MyTest#mySimpleTest` |
* | "package" | `TestPackageFilterConfiguration` | Filters tests by using only test package, e.g. `com.example` |
* | "method" | `TestMethodFilterConfiguration` | Filters tests by using only test method, e.g. `myComplicatedTest` |
* | "annotation" | `AnnotationFilterConfiguration` | Filters tests by using only test annotation name, e.g. `androidx.test.filters.LargeTest` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ open class FilteringPluginConfiguration {

open class Wrapper {
open var simpleClassNameFilter: ArrayList<String>? = null
open var simpleTestNameFilter: ArrayList<String>? = null
open var fullyQualifiedClassnameFilter: ArrayList<String>? = null
open var fullyQualifiedTestnameFilter: ArrayList<String>? = null
open var testPackageFilter: ArrayList<String>? = null
Expand Down Expand Up @@ -71,6 +72,11 @@ fun Wrapper.toList(): List<TestFilterConfiguration> {
1 -> mutableList.add(TestFilterConfiguration.SimpleClassnameFilterConfiguration(simpleClassNameFilter?.first().orEmpty().toRegex()))
else -> mutableList.add(TestFilterConfiguration.SimpleClassnameFilterConfiguration(values = simpleClassNameFilter))
}
when (simpleTestNameFilter?.size) {
null, 0 -> Unit
1 -> mutableList.add(TestFilterConfiguration.SimpleTestnameFilterConfiguration(simpleTestNameFilter?.first().orEmpty().toRegex()))
else -> mutableList.add(TestFilterConfiguration.SimpleTestnameFilterConfiguration(values = simpleTestNameFilter))
}
when (fullyQualifiedTestnameFilter?.size) {
null, 0 -> Unit
1 -> mutableList.add(TestFilterConfiguration.FullyQualifiedTestnameFilterConfiguration(fullyQualifiedTestnameFilter?.first().orEmpty().toRegex()))
Expand Down

0 comments on commit e8f9dc7

Please sign in to comment.