Custom Annotations


1. @Test

package com.kant.annotations.custom;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * NOTE: Method declarations must not have any parameters or a throws clause.
 * Return types are restricted to primitives, String, Class, enums, annotations,
 * and arrays of the preceding types.
 * 
 * @author shaskant
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
 public boolean enabled() default true;
}



2. @TesterInfo

/**
 * 
 */
package com.kant.annotations.custom;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author shaskant
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TesterInfo {

 public enum Priority {
  LOW, MEDIUM, HIGH
 }

 Priority priority() default Priority.MEDIUM;

 String[] tags() default "";

 String createdBy() default "kantsh";

 String lastModified() default "03/01/2016";

}


3. TestExample [Annotated with above custom annotation]

/**
 * 
 */
package com.kant.annotations.custom;

import com.kant.annotations.custom.TesterInfo.Priority;

/**
 * @author shaskant
 *
 */
@TesterInfo(priority = Priority.HIGH, createdBy = "kantsh", tags = { "sales",
  "test" }, lastModified = "18/03/2016")
public class TestExample {
 @Test
 void testA() {
  if (true)
   throw new RuntimeException("This test always failed");
 }

 @Test(enabled = false)
 void testB() {
  if (false)
   throw new RuntimeException("This test always passed");
 }

 @Test(enabled = true)
 void testC() {
  if (10 > 1) {
   // do nothing, this test always passed.
  }
 }

}

4. RunTests

Parse the class using Java reflections and process based on meta info provided from Annotations.
/**
 * 
 */
package com.kant.annotations.custom;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * Now read Annotations.
 * 
 * @author shaskant
 *
 */
public class RunTest {

 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println("Testing...");
  int passed = 0, failed = 0, count = 0, ignore = 0;
  Class<TestExample> obj = TestExample.class;

  // Process TesterInfo annotation
  if (obj.isAnnotationPresent(TesterInfo.class)) {
   Annotation annotation = obj.getAnnotation(TesterInfo.class);
   TesterInfo testerInfo = (TesterInfo) annotation;

   System.out.printf("%nPriority :%s", testerInfo.priority());
   System.out.printf("%nCreatedBy :%s", testerInfo.createdBy());
   System.out.printf("%nTags :");

   int tagLength = testerInfo.tags().length;
   for (String tag : testerInfo.tags()) {
    if (tagLength > 1) {
     System.out.print(tag + ", ");
    } else {
     System.out.print(tag);
    }
    tagLength--;
   }

   System.out.printf("%nLastModified :%s%n%n",
     testerInfo.lastModified());
  }

  // Process @Test [applicable on methods only]
  for (Method method : obj.getDeclaredMethods()) {
   if (method.isAnnotationPresent(Test.class)) {
    Annotation annotation = method.getAnnotation(Test.class);
    Test test = (Test) annotation;

    // if enabled = true (default)
    if (test.enabled()) {
     try {
      method.invoke(obj.newInstance());
      System.out.printf("%s - Test '%s' - passed %n",
        ++count, method.getName());
      passed++;
     } catch (Throwable ex) {
      System.out.printf("%s - Test '%s' - failed: %s %n",
        ++count, method.getName(), ex.getCause());
      failed++;
     }

    } else {
     System.out.printf("%s - Test '%s' - ignored%n", ++count,
       method.getName());
     ignore++;
    }
   }
  }

 }

}

Comments