Loading ...
Sorry, an error occurred while loading the content.

Re: Regarding "Annotated descriptions" of new improvements in version 4.4

Expand Messages
  • Francesco
    ... Well, in the meanwhile I solved my needs picking directly the source code of the Ant JUnit task and patching :p So if my little patch solution can be
    Message 1 of 2 , Feb 7, 2008
    View Source
    • 0 Attachment
      --- In junit@yahoogroups.com, "Francesco" <won_espylacopa@...> wrote:
      >
      > Hello Everyone,
      >
      > I am interested if the "annotated description" feature can get the
      > javadoc method description and adding a textual description to its
      > relative generated report. Please can you point me on the right doc or
      > give me some sample of this new improvement usage?
      >
      > Thank You
      >

      Well, in the meanwhile I solved my needs picking directly the source
      code of the Ant JUnit task and patching :p

      So if my little patch solution can be useful for other newbies like
      me, I put here my solution as simple sample. Serious disclaimer: pick
      and use it but don't claim any nuclear disaster :)


      *** As note for who can help me, I noticed that a nice thing which I
      could do, would be to pick directly the test info content directly
      from the source javadoc code method, but I am still searching the
      right way to do it :), anyone could point me into the right direction?
      Thanks :) ***


      However, here It follows all steps to print out a title and a description:

      1) download last Ant sources and unpack it, then find XMLConstants,
      JUnitVersionHelper, XMLJUnitResultFormatter classes and modify them as
      the followings

      ===org.apache.tools.ant.taskdefs.optional.junit.XMLConstants===
      +++>

      [...]

      /**
      * title attribute for testcase element
      * @author rigel alias zetatau
      * TODO:
      */
      String ATTR_TITLE = "title";

      /**
      * desc attribute for testcase element
      * @author rigel alias zetatau
      * TODO:
      */
      String ATTR_DESC = "desc";

      [...]

      <+++


      ===org.apache.tools.ant.taskdefs.optional.junit.JUnitVersionHelper===
      +++>

      [...]

      public static String getTestCaseTitle(Test test, String
      annotationMatch, String annotationParameter) {
      if (test != null) {
      if (test.getClass().getName().equals(JUNIT_TESTFACADE))
      return
      helperMethodInvoke(test,annotationMatch,annotationParameter,UNKNOWN);
      else
      return "";
      }
      return UNKNOWN;
      }

      public static String getTestCaseDesc(Test test, String
      annotationMatch, String annotationParameter) {
      if (test != null) {
      if (test.getClass().getName().equals(JUNIT_TESTFACADE))
      return
      helperMethodInvoke(test,annotationMatch,annotationParameter,UNKNOWN);
      else
      return "";
      }
      return UNKNOWN;
      }


      private static Iterator helperDescriptorCollection(Test facade) {
      final String
      junitDescription="org.junit.runner.Description",
      methodOnFacade="getDescription",
      methodOnItem="getAnnotations";

      ArrayList empty = new ArrayList();
      if (!facade.getClass().getName().equals(JUNIT_TESTFACADE))
      return empty.iterator();
      try {

      Class.forName(junitDescription,false,ClassLoader.getSystemClassLoader());
      // otherwise throw an exception
      Method m = facade.getClass().getMethod(methodOnFacade, new Class[0]);
      Object itemInstance = m.invoke(facade, new Object[0]);
      if
      (itemInstance!=null&&junitDescription.equals(itemInstance.getClass().getName())){
      Method m1 = itemInstance.getClass().getMethod(methodOnItem, new
      Class[0]);
      Object rtObj = m1.invoke(itemInstance, new Object[0]);
      if (rtObj instanceof Collection)
      return ((Collection)rtObj).iterator();
      return empty.iterator();
      } else return empty.iterator();
      } catch (ClassNotFoundException e) {
      } catch (SecurityException e) {
      } catch (IllegalArgumentException e) {
      } catch (NoSuchMethodException e) {
      } catch (IllegalAccessException e) {
      } catch (InvocationTargetException e) {
      }
      return empty.iterator();
      }

      private static Object helperAnnotation(Test façade, String
      annotationMatch) {
      final String methodOnAnnotation="annotationType";
      Object item=null;
      Iterator it = helperDescriptorCollection(façade);
      while (it.hasNext()) {
      Object a = (Object)it.next();
      String match = "";
      try {
      Method m = a.getClass().getMethod(methodOnAnnotation, new Class[0]);
      Class out = (Class)m.invoke(a, new Object[0]);
      match=String.valueOf(out.getName());
      } catch (SecurityException e) {
      } catch (NoSuchMethodException e) {
      } catch (IllegalArgumentException e) {
      } catch (IllegalAccessException e) {
      } catch (InvocationTargetException e) {
      }
      if (annotationMatch.equals(match)) {
      item=a;
      break;
      }
      }
      return item;
      }

      private static String helperMethodInvoke(Test instance, String
      annotationMatch, String methodName, String defaultValue) {
      try {
      // ANNOTATIONS WORKS ONLY ABOVE JDK 1.5
      // Iterator it =
      ((junit.framework.JUnit4TestCaseFacade)instance).getDescription().getAnnotations().iterator();
      // java.lang.annotation.Annotation item=null;
      // while (it.hasNext()) {
      // java.lang.annotation.Annotation a =
      (java.lang.annotation.Annotation)it.next();
      // if (annotationMatch.equals(a.annotationType().getName())) {
      // item=a;
      // break;
      // }
      // }
      Object item = helperAnnotation(instance, annotationMatch);
      /* No appropriate annotation was found so returns defaultValue */
      if (item==null)
      return defaultValue;

      Method m = item.getClass().getMethod(methodName, new Class[0]);
      Object oOut = m.invoke(item, new Object[0]);
      if (oOut instanceof String) {
      String sOut = String.valueOf(oOut);
      if ("".equals(sOut)||sOut==null)
      return defaultValue;
      else
      return sOut;
      } else {
      return defaultValue;
      }
      } catch (SecurityException e) {
      } catch (IllegalArgumentException e) {
      } catch (NoSuchMethodException e) {
      } catch (IllegalAccessException e) {
      } catch (InvocationTargetException e) {
      }
      return defaultValue;
      }


      [...]

      <+++



      ===org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter===
      +++>
      public void endTest(Test test) {

      [...]

      /*
      * This adds additional info to the generated XML test case data,
      unfortunately I don't
      * know what ant helper class can give me some params from XML build,
      */
      String sTitle =
      JUnitVersionHelper.getTestCaseTitle(test,"test.TestInfo","title");
      String sDesc =
      JUnitVersionHelper.getTestCaseDesc(test,"test.TestInfo","desc");
      currentTest.setAttribute(ATTR_TITLE,UNKNOWN.equals(sTitle) ? "" : sTitle);
      currentTest.setAttribute(ATTR_DESC,UNKNOWN.equals(sDesc) ? "" : sDesc);

      }

      [...]

      <+++


      2) Now build all Ant sources and replace in your default Ant library
      environment the old "ant-junit.jar" with the new one.


      3) Now you can create an annotation class like this, the name is
      important because in the previous class "XMLJUnitResultFormatter" is
      literally wired as "test.TestInfo", and if you found a way to retrieve
      easily params from build.xml it could be easily parameterized:

      ===test.TestInfo===

      ===>
      package test;

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

      /**
      *
      * @author rigel alias zetatau
      *
      */
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.METHOD})
      public @interface TestInfo {
      /**
      * Optionally specify test <code>title</code>
      */
      public String title() default "Default test title";

      /**
      * Optionally specify test <code>description</code>
      */
      public String desc() default "Default test description";

      /**
      * Optionally specify test <code>error message descriptor</code>
      */
      public String errorMessage() default "Default error message descriptor";

      }
      <===


      4) Last step is your class under test, add a TestInfo annotation and
      it's all done for the XML testcase data generation (apart xml dtd
      another step would be to patch the junit-frames.xsl to show your new
      attributes):

      ===SomeClassUnderTest===

      +++>

      [...]
      /**
      * This test probes if a null argument causes a NPE
      * @...
      */
      @Test(expected=NullPointerException.class)
      @TestInfo(title="Null argument",
      desc="This test probes if a null argument causes a NPE")
      public final void beginTest1() {
      [...]
      }

      [...]

      <+++



      --
      Francesco V.
    Your message has been successfully submitted and would be delivered to recipients shortly.