Monday, August 20, 2012

get feature and scenario name with cucumber-jvm

cucumber-jvm does not provide an easy way to get the feature name, scenario name or the step that is being executed. I had to find a workaround for this. For reference it is listed here. I am using the mirage project that I created a while back that provides a few utility classes around reflection. The ReflectionUtils.getFieldInObject uses that.

I created an aspect and weaved the info.cukes:cucumber-junit jar file with the aspect.
 public aspect ReportFeatureScenarioStep {  
      pointcut running_feature() : execution(public * cucumber.junit.FeatureRunner.run(..));  
      pointcut running_scenario() : execution(public * cucumber.junit.ExecutionUnitRunner.run(..));  
      pointcut running_step() : execution(public * cucumber.junit.JUnitReporter.match(..));  
 // Not used. These are here for reference only  
 //     pointcut completing_feature() : execution(public * cucumber.junit.FeatureRunner.run(..));  
 //     pointcut completing_scenario() : execution(public * cucumber.junit.ExecutionUnitRunner.run(..));  
 //     pointcut completing_step() : execution(public * cucumber.junit.JUnitReporter.result(..));  
      before() : running_feature() {  
           ParentRunner pr = (ParentRunner) thisJoinPoint.getTarget();  
           System.out.println(pr.getDescription().toString());  
      }  
      before() : running_scenario() {  
           ParentRunner pr = (ParentRunner) thisJoinPoint.getTarget();  
           System.out.println(pr.getDescription().toString());  
      }  
      before() : running_step() {  
           StepDefinitionMatch m = (StepDefinitionMatch) thisJoinPoint.getArgs()[0];  
           Step step = (Step) ReflectionUtils.getFieldInObject(m, "step");  
           System.out.println(step.getKeyword() + " " + m.getStepName());  
      }  
 // Not used. These are here for reference only       
 //     after() : completing_feature() {  
 //          ParentRunner pr = (ParentRunner) thisJoinPoint.getTarget();  
 //          System.out.println("AFTER FEATURE : -->" + pr.getDescription() + "<--");  
 //     }  
 //       
 //     after() : completing_scenario() {  
 //          ParentRunner pr = (ParentRunner) thisJoinPoint.getTarget();  
 //          System.out.println("AFTER SCENARIO : -->" + pr.getDescription() + "<--");  
 //     }  
 //       
 //     after() : completing_step() {  
 //          System.out.println("AFTER STEP ");  
 //     }  
 }  

This aspect is weaved into the cucumber-junit by doing this:

               <plugin>  
                   <groupId>org.codehaus.mojo</groupId>  
                     <artifactId>aspectj-maven-plugin</artifactId>  
                     <version>1.4</version>  
                     <executions>  
                          <execution>  
                               <goals>  
                                    <goal>compile</goal>  
                                    <goal>test-compile</goal>  
                               </goals>  
                          </execution>  
                     </executions>  
                     <configuration>  
                          <source>1.6</source>  
                          <complianceLevel>1.6</complianceLevel>  
                          <verbose>false</verbose>  
                          <showWeaveInfo>false</showWeaveInfo>  
                          <target>1.6</target>  
                          <weaveDependencies>  
                               <weaveDependency>  
                                    <groupId>info.cukes</groupId>  
                                    <artifactId>cucumber-junit</artifactId>  
                               </weaveDependency>  
                               <weaveDependency>  
                                    <groupId>info.cukes</groupId>  
                                    <artifactId>cucumber-java</artifactId>  
                               </weaveDependency>  
                          </weaveDependencies>  
                     </configuration>  
                </plugin>  

6 comments:

  1. It worked well for me. The only thing I had to do was to change the compiler of the project to be the ajc (in IntelliJ).
    Thanks a lot!

    ReplyDelete
  2. Glad I can help. It you used the Mirage library it is now hosted on maven central - http://search.maven.org/#artifactdetails%7Ccom.daveayan%7Cmirage%7C1.1%7Cjar

    ReplyDelete
  3. Is there way to do this using Java and not with aspectJ?

    ReplyDelete
  4. Since cucumber-jvm does not provide a way to hook into the calls I don't know of other ways to achieve this using Java.

    ReplyDelete
  5. I am using eclipse. Why do I always get The artifact info.cukes:cucumber-junit referenced in aspectj plugin as dependencies and/or directories to weave, is not found the project dependencies -> [Help 1]

    I checked and in POM.xml the dependency is there.

    ReplyDelete
    Replies
    1. I got it. I was using the wrong scope on this jar.

      Delete