Add multiplatform DynamicTest

This commit is contained in:
Him188 2022-07-18 02:42:06 +08:00
parent 3bcdf9b640
commit 699718f958
4 changed files with 147 additions and 0 deletions

View File

@ -0,0 +1,68 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmName("DynamicTestKt_common")
package net.mamoe.mirai.internal.testFramework
import kotlin.jvm.JvmName
import kotlin.test.Test
/**
* Annotates a function to be a [Test] factory that returns a [DynamicTestsResult].
*
* On JVM, this delegates to JUnit's `TestFactory`. On Native, test functions are executed in-place.
*
* Tips: To run [TestFactory]s in IDEA, you can press `Ctrl + Shift + R`(for both macOS and Windows) with caret in the test function.
*/
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
expect annotation class TestFactory()
/**
* @see dynamicTest
*/
expect open class DynamicTest // = junit.DynamicTest
/**
* @see runDynamicTests
*/
expect class DynamicTestsResult
/**
* Creates a dynamic test
*/
expect fun dynamicTest(displayName: String, action: () -> Unit): DynamicTest
/**
* The returned value must be returned from the function annotated with [TestFactory], otherwise the tests won't be executed on some platforms.
*/
expect fun runDynamicTests(dynamicTests: List<DynamicTest>): DynamicTestsResult
/**
* The returned value must be returned from the function annotated with [TestFactory], otherwise the tests won't be executed on some platforms.
*/
fun runDynamicTests(vararg dynamicTests: Iterable<DynamicTest>): DynamicTestsResult =
runDynamicTests(dynamicTests = dynamicTests.flatMap { it })
/**
* The returned value must be returned from the function annotated with [TestFactory], otherwise the tests won't be executed on some platforms.
*/
fun runDynamicTests(vararg dynamicTests: Sequence<DynamicTest>): DynamicTestsResult =
runDynamicTests(dynamicTests = dynamicTests.flatMap { it })
/**
* The returned value must be returned from the function annotated with [TestFactory], otherwise the tests won't be executed on some platforms.
*/
fun runDynamicTests(vararg dynamicTests: DynamicTest): DynamicTestsResult = runDynamicTests(dynamicTests.toList())
/**
* The returned value must be returned from the function annotated with [TestFactory], otherwise the tests won't be executed on some platforms.
*/
fun runDynamicTests(dynamicTests: Sequence<DynamicTest>): DynamicTestsResult = runDynamicTests(dynamicTests.toList())

View File

@ -13,15 +13,38 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.debug.DebugProbes import kotlinx.coroutines.debug.DebugProbes
import net.mamoe.mirai.IMirai import net.mamoe.mirai.IMirai
import net.mamoe.mirai.internal.network.framework.SynchronizedStdoutLogger import net.mamoe.mirai.internal.network.framework.SynchronizedStdoutLogger
import net.mamoe.mirai.internal.testFramework.DynamicTest
import net.mamoe.mirai.internal.testFramework.TestFactory
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.setSystemProp import net.mamoe.mirai.utils.setSystemProp
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.TestInfo
import org.junit.jupiter.api.Timeout import org.junit.jupiter.api.Timeout
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.jvm.optionals.getOrNull
import kotlin.reflect.full.functions
import kotlin.reflect.full.hasAnnotation
@Timeout(value = 7, unit = TimeUnit.MINUTES) @Timeout(value = 7, unit = TimeUnit.MINUTES)
internal actual abstract class AbstractTest actual constructor() : CommonAbstractTest() { internal actual abstract class AbstractTest actual constructor() : CommonAbstractTest() {
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
actual companion object { actual companion object {
@OptIn(ExperimentalStdlibApi::class)
@BeforeAll
private fun checkTestFactories(testInfo: TestInfo) {
val clazz = testInfo.testClass.getOrNull()?.kotlin ?: return
for (function in clazz.functions) {
if (function.hasAnnotation<TestFactory>()) {
check(function.returnType.classifier == List::class) {
"Illegal TestFactory function. A such function must return DynamicTestsResult."
}
check(function.returnType.arguments.singleOrNull()?.type?.classifier == DynamicTest::class) {
"Illegal TestFactory function. A such function must return DynamicTestsResult."
}
}
}
}
init { init {
initPlatform() initPlatform()

View File

@ -0,0 +1,24 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.testFramework
actual typealias TestFactory = org.junit.jupiter.api.TestFactory
actual typealias DynamicTest = org.junit.jupiter.api.DynamicTest
@Suppress("ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE", "ACTUAL_WITHOUT_EXPECT")
actual typealias DynamicTestsResult = List<*>
actual fun dynamicTest(displayName: String, action: () -> Unit): DynamicTest {
return DynamicTest.dynamicTest(displayName, action)
}
actual fun runDynamicTests(dynamicTests: List<DynamicTest>): DynamicTestsResult = dynamicTests

View File

@ -0,0 +1,32 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.testFramework
import kotlin.test.Test
actual typealias TestFactory = Test
actual open class DynamicTest(
val displayName: String,
val action: () -> Unit,
)
@Suppress("ACTUAL_WITHOUT_EXPECT")
actual typealias DynamicTestsResult = Unit
actual fun dynamicTest(displayName: String, action: () -> Unit): DynamicTest = DynamicTest(displayName, action)
actual fun runDynamicTests(dynamicTests: List<DynamicTest>) {
for (dynamicTest in dynamicTests) {
println("=".repeat(32) + " ${dynamicTest.displayName} " + "=".repeat(32))
dynamicTest.action.invoke()
println("=".repeat(32) + "=".repeat(dynamicTest.displayName.length + 2) + "=".repeat(32))
}
}