JS: support @Before and @After annotations in kotlin.test

This commit is contained in:
Anton Bannykh
2017-09-01 19:56:52 +03:00
parent 8c5d18c1f2
commit f4b329a055
3 changed files with 67 additions and 13 deletions
@@ -62,9 +62,16 @@ class JSTestGenerator(val context: TranslationContext) {
val suiteFunction = JsFunction(context.scope(), JsBlock(), "suite function")
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS, MemberScope.ALL_NAME_FILTER).forEach {
if (it is FunctionDescriptor && it.isTest) {
generateCodeForTestMethod(it, classDescriptor, suiteFunction)
val descriptors = classDescriptor.unsubstitutedMemberScope
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS, MemberScope.ALL_NAME_FILTER)
.filterIsInstance<FunctionDescriptor>()
val beforeFunctions = descriptors.filter { it.isBefore }
val afterFunctions = descriptors.filter { it.isAfter }
descriptors.forEach {
if (it.isTest) {
generateCodeForTestMethod(it, beforeFunctions, afterFunctions, classDescriptor, suiteFunction)
}
}
@@ -75,19 +82,39 @@ class JSTestGenerator(val context: TranslationContext) {
}
}
private fun generateCodeForTestMethod(functionDescriptor: FunctionDescriptor, classDescriptor: ClassDescriptor, parentFun: JsFunction) {
val functionToTest = generateTestFunction(functionDescriptor, classDescriptor, parentFun.scope)
private fun generateCodeForTestMethod(functionDescriptor: FunctionDescriptor,
beforeDescriptors: List<FunctionDescriptor>,
afterDescriptors: List<FunctionDescriptor>,
classDescriptor: ClassDescriptor,
parentFun: JsFunction) {
val functionToTest = generateTestFunction(functionDescriptor, beforeDescriptors, afterDescriptors, classDescriptor, parentFun.scope)
val testName = JsStringLiteral(functionDescriptor.name.toString())
parentFun.body.statements += JsInvocation(testRef, testName, JsBooleanLiteral(functionDescriptor.isIgnored), functionToTest).makeStmt()
}
private fun generateTestFunction(functionDescriptor: FunctionDescriptor, classDescriptor: ClassDescriptor, scope: JsScope): JsFunction {
val expression = ReferenceTranslator.translateAsValueReference(classDescriptor, context)
private fun generateTestFunction(functionDescriptor: FunctionDescriptor,
beforeDescriptors: List<FunctionDescriptor>,
afterDescriptors: List<FunctionDescriptor>,
classDescriptor: ClassDescriptor,
scope: JsScope): JsFunction {
val functionToTest = JsFunction(scope, JsBlock(), "test function")
val innerContext = context.contextWithScope(functionToTest)
val expression = ReferenceTranslator.translateAsTypeReference(classDescriptor, innerContext)
val testClass = JsNew(expression)
val functionToTestCall = CallTranslator.buildCall(context, functionDescriptor, emptyList<JsExpression>(), testClass)
val functionToTest = JsFunction(scope, "test function")
functionToTest.body = JsBlock(functionToTestCall.makeStmt())
val classVal = innerContext.defineTemporary(testClass)
fun FunctionDescriptor.buildCall() = CallTranslator.buildCall(context, this, emptyList(), classVal).makeStmt()
functionToTest.body.statements += beforeDescriptors.map { it.buildCall() }
functionToTest.body.statements += if (afterDescriptors.isEmpty()) {
functionDescriptor.buildCall()
}
else {
JsTry(JsBlock(functionDescriptor.buildCall()), listOf(), JsBlock(afterDescriptors.map { it.buildCall() }))
}
return functionToTest
}
@@ -108,6 +135,12 @@ class JSTestGenerator(val context: TranslationContext) {
private val DeclarationDescriptor.isIgnored
get() = annotationFinder("Ignore", "kotlin.test")
private val FunctionDescriptor.isBefore
get() = annotationFinder("Before", "kotlin.test")
private val FunctionDescriptor.isAfter
get() = annotationFinder("After", "kotlin.test")
private fun DeclarationDescriptor.annotationFinder(shortName: String, vararg packages: String) = packages.any { packageName ->
annotations.hasAnnotation(FqName("$packageName.$shortName"))
}
@@ -1,13 +1,24 @@
import kotlin.test.*
var value = 5
class SimpleTest {
@Before fun beforeFun() {
value *= 2
}
@After fun afterFun() {
value /= 2
}
@Test fun testFoo() {
assertEquals(20, foo())
assertNotEquals(value, foo())
}
@Test fun testBar() {
assertEquals(10, foo())
assertEquals(value, foo())
}
@Ignore @Test fun testFooWrong() {
@@ -24,4 +24,14 @@ public annotation class Test
/**
* Marks a test or a suite as ignored/pending.
*/
public annotation class Ignore
public annotation class Ignore
/**
* Marks a function to be invoked before each test.
*/
public annotation class Before
/**
* Marks a function to be invoked after each test.
*/
public annotation class After