Skip to content

Commit

Permalink
Extend @as with a provider mechanism.
Browse files Browse the repository at this point in the history
This change extends the @as annotation for step / stage methods and classes
with an AsProvider provider() method to allow a more flexible way of
customizing the result.

fixes TNG#189
  • Loading branch information
Airblader committed Jul 11, 2016
1 parent e162dcf commit 8eff753
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Added a new CurrentScenario interface similar to CurrentStep.
* The CurrentScenario interface allows adding tags programmatically, see [#172](https://github.com/TNG/JGiven/issues/172).
* Allow tag annotations on step methods and step classes.
* Extended the @As annotation with a provider mechanism, see [#189](https://github.com/TNG/JGiven/issues/189).

## Breaking Changes in the JSON model

Expand Down
27 changes: 23 additions & 4 deletions jgiven-core/src/main/java/com/tngtech/jgiven/annotation/As.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package com.tngtech.jgiven.annotation;

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

import com.tngtech.jgiven.impl.params.DefaultAsProvider;

/**
* This annotation can be used to override the default
* representation for a step method, test method or class name in the report.
*
*
* <p>
* Note that the '$' character keeps its special meaning and will be
* replaced with step arguments
Expand All @@ -24,8 +30,8 @@
* ...
* }
* </pre>
*
*
*
*
* @since 0.7.4. Since 0.9.0 this annotation can be applied to test classes as well
*/
@Retention( RetentionPolicy.RUNTIME )
Expand All @@ -38,4 +44,17 @@
*/
String value();

/**
* An optional provider to generate the representation of the stage method, scenario or scenario class.
* <p>
* The class that implements {@link AsProvider} interface must
* be a public non-abstract class that is not a non-static inner class and must have a public default constructor.
* </p>
* <p>
* If this attribute is set, the {@link #value()} attribute is ignored.
* </p>
* @since 0.12.0
*/
Class<? extends AsProvider> provider() default DefaultAsProvider.class;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.tngtech.jgiven.annotation;

import java.lang.reflect.Method;

/**
* Provides a representation of a stage method, scenario or scenario class.
* @since 0.12.0
*/
public interface AsProvider {

/**
* Provide the representation for a stage method or scenario.
* @param annotation The {@link As} annotation using this provider.
* @param method The method of which a representation is requested.
* @return A representation of the method.
*
* @since 0.12.0
*/
String as( As annotation, Method method );

/**
* Provide the representation for a scenario class.
* @param annotation The {@link As} annotation using this provider.
* @param scenarioClass The scenario class of which a representation is requested.
* @return A representation of the scenario class.
*
* @since 0.12.0
*/
String as( As annotation, Class<?> scenarioClass );

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
package com.tngtech.jgiven.impl;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.CaseFormat;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
Expand All @@ -21,12 +33,6 @@
import com.tngtech.jgiven.impl.util.ReflectionUtil;
import com.tngtech.jgiven.impl.util.WordUtil;
import com.tngtech.jgiven.report.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class ScenarioModelBuilder implements ScenarioListener {
private static final Logger log = LoggerFactory.getLogger( ScenarioModelBuilder.class );
Expand Down Expand Up @@ -212,7 +218,8 @@ private String getDescription( Method paramMethod ) {
}
As as = paramMethod.getAnnotation( As.class );
if( as != null ) {
return as.value();
AsProvider provider = ReflectionUtil.newInstance( as.provider() );
return provider.as( as, paramMethod );
}

return nameWithSpaces( paramMethod );
Expand Down Expand Up @@ -365,7 +372,10 @@ private void readAnnotations( Class<?> testClass, Method method ) {
if( method.isAnnotationPresent( Description.class ) ) {
scenarioDescription = method.getAnnotation( Description.class ).value();
} else if( method.isAnnotationPresent( As.class ) ) {
scenarioDescription = method.getAnnotation( As.class ).value();
As as = method.getAnnotation( As.class );

AsProvider provider = ReflectionUtil.newInstance( as.provider() );
scenarioDescription = provider.as( as, method );
}

scenarioStarted( scenarioDescription );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.tngtech.jgiven.impl.params;

import java.lang.reflect.Method;

import com.tngtech.jgiven.annotation.As;
import com.tngtech.jgiven.annotation.AsProvider;

/**
* The default provider for a stage method, scenario or scenario class.
*
*/
public class DefaultAsProvider implements AsProvider {

/**
* Returns the value of the {@link As} annotation.
*/
@Override
public String as( As annotation, Method method ) {
return annotation.value();
}

/**
* Returns the value of the {@link As} annotation.
*/
@Override
public String as( As annotation, Class<?> scenarioClass ) {
return annotation.value();
}

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.tngtech.jgiven.report.model;

import java.util.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tngtech.jgiven.annotation.As;
import com.tngtech.jgiven.annotation.AsProvider;
import com.tngtech.jgiven.annotation.Description;
import com.tngtech.jgiven.config.AbstractJGivenConfiguration;
import com.tngtech.jgiven.config.ConfigurationUtil;
import com.tngtech.jgiven.impl.util.AssertionUtil;
import com.tngtech.jgiven.impl.util.ReflectionUtil;
import com.tngtech.jgiven.impl.util.WordUtil;

public class ReportModel {
Expand Down Expand Up @@ -179,7 +185,10 @@ public synchronized void setTestClass( Class<?> testClass ) {
}

if( testClass.isAnnotationPresent( As.class ) ) {
name = testClass.getAnnotation( As.class ).value();
As as = testClass.getAnnotation( As.class );

AsProvider provider = ReflectionUtil.newInstance( as.provider() );
name = provider.as( as, testClass );
} else {
name = getTestNameToReadableString( testClass );
}
Expand Down

0 comments on commit 8eff753

Please sign in to comment.