Create Kotlin annotation from Java #Test TestNG annotation - kotlin

I am using Java TestNG annotation:
#Test(groups = ['integration'])
And I would like to create Kotlin annotation like:
#IntegrationTest
Is it doable ?

No, as of now Kotlin language doesn't have builtin tools that enable such use case.
You can resort to the annotation processing technique: write an annotation processor that replaces your custom #IntegrationTest with #Test from TestNG.
One drawback of annotation processing is that a processor is a black box to the tooling. For example, IDE won't treat the methods annotated with #IntegrationTest as tests because it doesn't know that they are going to be post-processed later.
Also annotation processing is a JVM-specific tool, so it isn't supported on other platforms.

Related

Is there a way to add an annotation to a class at runtime with Kotlin?

Due to a third-party library requirement I have to do some finagling with annotations.
Using Kotlin, is there a way to dynamically add an annotation to class metadata at runtime like you can in Java?
e.g. something like:
clazz.annotations.set(idx, myAnnotation)

Is there a way to use an annotation class as a decorator on a function in Kotlin?

I am very new to Kotlin development and I came across custom annotation classes in the documentation.
Is there a way for me to use an annotation on a function as a way to pre-populate some variables, or to run a decorator function before running the annotated function?
Something like:
class TestClass {
#Friendly("Hello World")
private fun testFun() {
greet()
//does something else
}
}
with an annotation class like
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.BINARY)
annotation class Friendly(val message: String) {
fun greet() {
println(message)
}
}
I know this isn't valid Kotlin code, but I can't find any examples on how to actually use values from annotations without using reflection (if it's even possible)
Please let me know if I can do something like this, and more usefully, a better resource on annotation classes for Kotlin?
To make use of your custom annotations, you need to either create your own annotation processor (and use kapt Kotlin compiler plugin) to generate some new sources (but not modify existing!) at compile time, or use #Retention(AnnotationRetention.RUNTIME) meta-annotation (which is default in Kotlin), so that they could be accessed via reflection in runtime.
#Retention(AnnotationRetention.BINARY) meta-annotation you're using is equivalent of #Retention(RetentionPolicy.CLASS) in java, which is mostly useless (see https://stackoverflow.com/a/5971247/13968673).
What you're trying to do with annotations (call some additional code before/after method execution) reminds me aspect-oriented programming. Take a look at Spring AOP and AspectJ frameworks, following this paradigm, and their approach for annotations processing. TL;DR: Spring AOP is processing annotations in runtime, generating proxy-classes with respectful code, while AspectJ is using its own compiler (even not an annotation processor, cause it also introduces its own syntactic extension for java language), and can generate respectful bytecode at compile-time. They both are originally java-oriented, but with some configurational pain could be used with Kotlin too.

modify a Kotlin class

I'd like to write a plugin for Intellij IDEA that should modify a Java and Kotlin code.
I use the method
PsiClass.getMethods()
in order to get all methods of Java and Kotlin classes. So far so good, so then I use methods like
PsiClass.add(), PsiClass.addAfter(), PsiClass.addBefore()
that all work fine once they are called on Java files, but start to throw an exception
IncorrectOperationException
once I called them on a Kotlin class.
I'd appreciate any hint on how I can modify Kotlin and Java classes (preferably using the same approach).
When you search for a Kotlin class via the JavaPsiFacade, it returns the light class which is a shallow representation that is just based on the information in the class file. In order to add PSI elements, you have to call navigationElement on it. Then, IJ will parse the source and build a full PSI tree that can be modified.
However, if the class is a Kotlin class, navigationElement will return a KtClass which is not derived from PsiClass. You will have to use the facilities in the Kotlin hierarchy to modify it. Method instances in Kotlin are also not instances of PsiMethod, but instances of KtMethod.
For analyzing Java and Kotlin sources in a common fashion there is a different syntax tree called "UAST", but for modifications you need a language-specific approach.

How to change tests execution order in JUnit5?

JUnit4 has #FixMethodOrder annotation which allows to use alphabetical order of test methods execution. Is there analogous JUnit5 mechanism?
Edit: JUnit 5.4 is officially released now, so no need to use snapshots anymore.
This is now possible with JUnit 5.4.
https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order
To control the order in which test methods are executed, annotate your
test class or test interface with #TestMethodOrder and specify the
desired MethodOrderer implementation. You can implement your own
custom MethodOrderer or use one of the following built-in
MethodOrderer implementations.
Alphanumeric: sorts test methods alphanumerically based on their names
and formal parameter lists.
OrderAnnotation: sorts test methods numerically based on values
specified via the #Order annotation.
No, not yet. For unit tests, execution order should be irrelevant. For more complex tests, JUnit is aiming to provide explicit support - test ordering would be part of that.
With version 5.8.0 onwards, test classes can be ordered too.
src/test/resources/junit-platform.properties:
# ClassOrderer$OrderAnnotation sorts classes based on their #Order annotation
junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$OrderAnnotation
Other Junit built-in class orderer implementations:
org.junit.jupiter.api.ClassOrderer$ClassName
org.junit.jupiter.api.ClassOrderer$DisplayName
org.junit.jupiter.api.ClassOrderer$Random
For other ways (beside junit-platform.properties file) to set configuration parameters refer here.
You can also provide your own orderer. It must implement ClassOrderer interface:
package foo;
public class MyOrderer implements ClassOrderer {
#Override
public void orderClasses(ClassOrdererContext context) {
Collections.shuffle(context.getClassDescriptors());
}
}
junit.jupiter.testclass.order.default=foo.MyOrderer
Note that #Nested test classes cannot be ordered by a ClassOrderer.
Refer to JUnit 5 documentations and ClassOrderer api docs to learn more about ordering test classes.

Difference between Testng class and normal Java class

What is the difference between Testng Class and a normal Java class. While creating an Automation suite in Selenium should we use Testng class or normal java class in Eclipse.
TestNg is not language it's a testing framework. See this
TestNG is a testing framework inspired from JUnit and NUnit
This is a framework to handle different kind of testing such as unit,end to end, functional and so more. It uses Java and provide supports and annotations to drive testings. That's it!
A TestNg class is a Java class, but a Java class does not have to be a TestNg class.
The following is from the TestNg documentation and gives an understanding what you can do with the TestNg class:
This class is the main entry point for running tests in the TestNG
framework. Users can create their own TestNG object and invoke it in
many different ways:
On an existing testng.xml
On a synthetic testng.xml, created entirely from Java
By directly setting the test classes
You can also define which groups to include or exclude, assign
parameters, etc...
From: http://testng.org/javadoc/org/testng/TestNG.html
TestNg is basically is a set of code written in Java that allows you to create tests.
A TestNG class is a Java class that contains a method annotated by this class: org.testng.annotations.Test;
Testng Class and a normal Java class
TestNG Class: TestNg class is nothing but any normal class with TestNG annotation and Annotation is a tag that represents the metadata which gives the addition information about class, methods and interface.
To know more about annotation Please refer this https://docs.oracle.com/javase/tutorial/java/annotations/
While creating Automation suite we use either JUNIT or TestNG. JUNIT or TestNG are testing framework. They have their own set of libraries and annotations which is useful to run our automation suite. JUNIT or TestNG makes easy to run automation suite or generate reports of build run. They provide the feature to setup or cleanup activity using Before and After annotation which is require in almost every autoamtion suite.
TestNG also provide us flexibility to execute our automation script based on our requirement like we can group of test cases, we can include or exclude methods, parallel execution of test methods and many more.
Please refer this to know more about TestNG.
http://testng.org/doc/documentation-main.html
I hope this will help.