JS: test kotlin-test as box tests, support nested, fix mpp

Support tests inside nested classes and companion objects (KT-21850
fixed).
Don't launch multiplatform tests twice (KT-21567 fixed).
This commit is contained in:
Anton Bannykh
2017-12-20 21:37:06 +03:00
parent 3bf8436895
commit 79359b7bc2
12 changed files with 483 additions and 14 deletions
+108
View File
@@ -0,0 +1,108 @@
import kotlin.test.FrameworkAdapter
private val context = TestContext()
fun call(name: String) = context.call(name)
fun raise(name: String): Nothing {
context.raised(name)
throw Exception(name)
}
@Suppress("INVISIBLE_MEMBER")
val underscore = kotlin.test.setAdapter(object : FrameworkAdapter {
override fun suite(name: String, ignored: Boolean, suiteFn: () -> Unit) {
context.suite(name, ignored) { suiteFn() }
}
override fun test(name: String, ignored: Boolean, testFn: () -> Unit) {
context.test(name, ignored) { testFn() }
}
})
class TestContext {
val log: String
get() = logHead + (lastRecord ?: "")
var indentation = ""
fun suite(name: String, ignored: Boolean = false, body: TestContext.() -> Unit) = indent {
record("suite(\"$name\"${optionalIgnore(ignored)}) {")
body.runSafely()
record("}")
}
fun test(name: String, ignored: Boolean = false, body: TestContext.() -> Unit = {}) = indent {
val num = record("test(\"$name\"${optionalIgnore(ignored)}) {")
body.runSafely()
if (!writtenSince(num)) {
record("test(\"$name\"${optionalIgnore(ignored)})", replaceLast = true)
}
else {
record("}")
}
}
fun call(name: String) = indent {
record("call(\"$name\")")
}
fun raised(msg: String) = indent {
record("raised(\"$msg\")")
}
fun caught(msg: String) = indent {
record("caught(\"$msg\")")
}
private fun (TestContext.() -> Unit).runSafely() {
try {
this()
}
catch (t: Throwable) {
caught(t.message ?: "")
}
}
private fun indent(body: () -> Unit) {
val prevIndentation = indentation
indentation += " "
body()
indentation = prevIndentation
}
private var logHead: String = ""
private var lastRecord: String? = null
private var counter = 0
private fun writtenSince(num: Int) = counter > num
private fun record(s: String, replaceLast: Boolean = false): Int {
if (!replaceLast && lastRecord != null) {
logHead += lastRecord
}
lastRecord = indentation + s + "\n"
return ++counter
}
private fun optionalIgnore(ignored: Boolean) = if (ignored) ", true" else ""
}
fun checkLog(body: TestContext.() -> Unit): String {
val expectedContext = TestContext()
expectedContext.suite("") {
body()
}
if (context.log != expectedContext.log) {
return "Failed test structure check. Expected: ${expectedContext.log}; actual: ${context.log}."
}
else {
return "OK"
}
}
@@ -0,0 +1,55 @@
// EXPECTED_REACHABLE_NODES: 1183
import kotlin.test.Test
import kotlin.test.BeforeTest
import kotlin.test.AfterTest
class Simple {
@BeforeTest
fun before() {
call("before")
}
@AfterTest
fun after() {
call("after")
}
@Test
fun foo() {
call("foo")
}
@Test
fun bar() {
call("bar")
}
@Test
fun withException() {
call("withException")
raise("some exception")
call("never happens")
}
}
fun box() = checkLog {
suite("Simple") {
test("foo") {
call("before")
call("foo")
call("after")
}
test("bar") {
call("before")
call("bar")
call("after")
}
test("withException") {
call("before")
call("withException")
raised("some exception")
call("after")
caught("some exception")
}
}
}
+53
View File
@@ -0,0 +1,53 @@
// EXPECTED_REACHABLE_NODES: 1192
import kotlin.test.Test
import kotlin.test.Ignore
class A {
@Test
fun foo() {
}
@Ignore
@Test
fun bar() {
}
@Ignore
class B {
@Test
fun foo() {
}
@Ignore
@Test
fun bar() {
}
}
}
@Ignore
class C {
@Test
fun foo() {
}
@Ignore
@Test
fun bar() {
}
}
fun box() = checkLog {
suite("A") {
test("foo")
test("bar", true)
suite("B", true) {
test("foo")
test("bar", true)
}
}
suite("C", true) {
test("foo")
test("bar", true)
}
}
+55
View File
@@ -0,0 +1,55 @@
// EXPECTED_REACHABLE_NODES: 1197
import kotlin.test.Test
import kotlin.test.BeforeTest
import kotlin.test.AfterTest
interface TestyInterface {
@Test
fun someVarTest() {
call("TestyInterface.someVarTest")
}
}
abstract class AbstractTest : TestyInterface {
@Test abstract fun abstractTest()
@Test
fun someTest() {
call("AbstractTest.someTest")
}
}
interface BeforeAfterInterface {
@BeforeTest
@AfterTest
fun beforeAfter() {
call("beforeAfter")
}
}
class InheritedTest : AbstractTest(), BeforeAfterInterface {
@Test override fun abstractTest() {
call("InheritedTest.abstractTest")
}
}
fun box() = checkLog() {
suite("InheritedTest") {
test("abstractTest") {
call("beforeAfter")
call("InheritedTest.abstractTest")
call("beforeAfter")
}
test("someTest") {
call("beforeAfter")
call("AbstractTest.someTest")
call("beforeAfter")
}
test("someVarTest") {
call("beforeAfter")
call("TestyInterface.someVarTest")
call("beforeAfter")
}
}
}
+27
View File
@@ -0,0 +1,27 @@
// EXPECTED_REACHABLE_NODES: 1173
// MULTIPLATFORM
// MODULE: lib
// FILE: lib.kt
import kotlin.test.Test
expect class PlatformTest {
@Test fun platformTest()
}
// MODULE: main(lib)
// FILE: main.kt
import kotlin.test.Test
actual class PlatformTest {
@Test actual fun platformTest() {}
@Test fun someOtherTest() {}
}
fun box() = checkLog {
suite("PlatformTest") {
test("platformTest")
test("someOtherTest")
}
}
+87
View File
@@ -0,0 +1,87 @@
// EXPECTED_REACHABLE_NODES: 1200
import kotlin.test.Test
class Outer {
val prop = "prop"
@Test
fun test1() {
}
inner class Inner {
@Test fun innerTest() {
call(prop + "Inner")
}
inner class Inneer {
@Test fun inneerTest() {
call(prop + "Inneer")
}
}
}
class Nested {
@Test
fun a() {
}
@Test
fun b() {
}
class EvenDeeper {
@Test
fun c() {
}
}
}
@Test
fun test2() {
}
companion object {
@Test
fun companionTest() {
}
object InnerCompanion {
@Test
fun innerCompanionTest() {
}
}
}
}
fun box() = checkLog {
suite("Outer") {
test("test1")
suite("Inner") {
test("innerTest") {
call("propInner")
}
suite("Inneer") {
test("inneerTest") {
call("propInneer")
}
}
}
suite("Nested") {
test("a")
test("b")
suite("EvenDeeper") {
test("c")
}
}
test("test2")
suite("Companion") {
test("companionTest")
suite("InnerCompanion") {
test("innerCompanionTest")
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
// EXPECTED_REACHABLE_NODES: 1173
import kotlin.test.Test
class Simple {
@Test fun foo() {
call("foo")
}
}
fun box() = checkLog {
suite("Simple") {
test("foo") {
call("foo")
}
}
}