Skip to content

Commit

Permalink
Merge pull request #99 from TNG/hierarchical-tags
Browse files Browse the repository at this point in the history
Hierarchical tags
  • Loading branch information
janschaefer committed Aug 2, 2015
2 parents d4e49b6 + 9ef757a commit 477ded1
Show file tree
Hide file tree
Showing 81 changed files with 3,341 additions and 1,777 deletions.
19 changes: 17 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,28 @@

## New Features

### Hierarchical Tags

Tags can now have parent tags by tagging a tag annotation. This allows you to define tag hierarchies.

#### Example

The following example tags the `FeatureHtml5Report` annotation with the `FeatureReport` annotation:

```
@FeatureReport
@IsTag( name = "HTML5 Report" )
@Retention( RetentionPolicy.RUNTIME )
public @interface FeatureHtml5Report { }
```

### Enhanced Spring Support [#94](https://github.com/TNG/JGiven/pull/94)

* The Spring support has been greatly improved. JGiven Stages can now be directly managed by the Spring framework, resulting in a much better Spring integration.
** Note that the usage of Spring is optional and is provided by the `jgiven-spring` module.
* Introduced `@JGivenStage` to ease writing spring beans that act as JGiven stage

### HTML5 Report
### Hierarchical Package Structure in the HTML5 Report

* Classes are shown now in hierarchical navigation tree and scenarios can be listed by package [#91](https://github.com/TNG/JGiven/pull/91)

Expand All @@ -17,7 +32,7 @@
* HTML5 Report: tables with duplicate entries cannot be used as step parameters [#89](https://github.com/TNG/JGiven/issues/89)
* Fixed an issue that the `@Description` annotation was not regarded for methods with the `@IntroWord` [#87](https://github.com/TNG/JGiven/issues/87)

## New Annotation
## New Annotations

* Introduced the `@As` annotation that replaces the `@Description` annotation when used on step methods and test methods. The `@Description` annotation should only be used for descriptions of test classes.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,21 @@
Class<? extends TagDescriptionGenerator> descriptionGenerator() default DefaultTagDescriptionGenerator.class;

/**
* An optional type description that overrides the default which is the name of the annotation.
* @deprecated use {@link #name()} instead
*/
@Deprecated
String type() default "";

/**
* An optional name that overrides the default which is the name of the annotation.
* <p>
* It is possible that multiple annotations have the same type name. However, in this case every
* annotation must have a specified value that must be unique.
* </p>
* @since 0.7.4
*/
String name() default "";

/**
* Whether the type should be prepended to the tag if the tag has a value.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.tngtech.jgiven.annotation;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Marks methods of step definitions as not implemented yet.
* Such steps will not be executed, but will appear in
* the report as not implemented yet.
* <p>
* This is useful if one already wants to define the scenario without
* already implementing all steps, for example, to verify that
* all acceptance criteria of a story are covered by the scenario.
* <p>
* Annotating a stage class indicates
* that no step is implemented yet.
* <p>
* Finally, a test method can be annotated to indicate that the whole
* test is not implemented yet. The test will then be ignored by the testing-framework.
* (In fact an AssumptionException is thrown. It depends on the test runner how this
* is interpreted)
* <i>Currently only works for JUnit</i>
*
* <h2>Example</h2>
* <pre>
* {@literal @}NotImplementedYet
* public void my_cool_new_feature() {
*
* }
* </pre>
*
*/
@Documented
@Inherited
@Retention( RUNTIME )
@Target( { METHOD, TYPE } )
@IsTag( ignoreValue = true, description = "Not implemented Scenarios" )
public @interface Pending {
/**
* Optional description to describe when the implementation will be done.
*/
String value() default "";

/**
* Instead of only reporting not implemented yet steps,
* the steps are actually executed.
* This is useful to see whether some steps fail, for example.
* Failing steps, however, have no influence on the overall test result.
*/
boolean executeSteps() default false;

/**
* If <b>no</b> step fails during the execution of the test,
* the test will fail.
* <p>
* This makes sense if one ensures that a not implemented feature
* always leads to failing tests in the spirit of test-driven development.
* <p>
* If this is true, the <code>executeSteps</code> attribute is implicitly <code>true</code>.
*/
boolean failIfPass() default false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public abstract class AbstractJGivenConfiguraton {
private final Map<Class<? extends Annotation>, TagConfiguration> tagConfigurations = Maps.newHashMap();

public final TagConfiguration.Builder configureTag( Class<? extends Annotation> tagAnnotation ) {
TagConfiguration configuration = new TagConfiguration();
TagConfiguration configuration = new TagConfiguration( tagAnnotation );
tagConfigurations.put( tagAnnotation, configuration );
return new TagConfiguration.Builder( configuration );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.tngtech.jgiven.config;

import java.lang.annotation.Annotation;
import java.util.List;

import com.google.common.collect.Lists;
import com.tngtech.jgiven.annotation.DefaultTagDescriptionGenerator;
import com.tngtech.jgiven.annotation.IsTag;
import com.tngtech.jgiven.annotation.TagDescriptionGenerator;

/**
Expand All @@ -10,6 +13,7 @@
* @see com.tngtech.jgiven.annotation.IsTag for a documentation of the different values.
*/
public class TagConfiguration {
private final String annotationType;
private boolean ignoreValue;
private boolean explodeArray = true;
private boolean prependType;
Expand All @@ -18,7 +22,16 @@ public class TagConfiguration {
private String color = "";
private String cssClass = "";
private Class<? extends TagDescriptionGenerator> descriptionGenerator = DefaultTagDescriptionGenerator.class;
private String type = "";
private String name = "";
private List<String> tags = Lists.newArrayList();

public TagConfiguration( Class<? extends Annotation> tagAnnotation ) {
this.annotationType = tagAnnotation.getSimpleName();
}

public static Builder builder( Class<? extends Annotation> tagAnnotation ) {
return new Builder( new TagConfiguration( tagAnnotation ) );
}

public static class Builder {
final TagConfiguration configuration;
Expand Down Expand Up @@ -52,8 +65,17 @@ public Builder descriptionGenerator( Class<? extends TagDescriptionGenerator> de
return this;
}

/**
* @deprecated use {@link #name(String)} instead
*/
@Deprecated
public Builder type( String s ) {
configuration.type = s;
configuration.name = s;
return this;
}

public Builder name( String s ) {
configuration.name = s;
return this;
}

Expand All @@ -72,6 +94,15 @@ public Builder color( String color ) {
return this;
}

public Builder tags( List<String> tags ) {
configuration.tags = tags;
return this;
}

public TagConfiguration build() {
return configuration;
}

}

/**
Expand Down Expand Up @@ -100,10 +131,20 @@ public Class<? extends TagDescriptionGenerator> getDescriptionGenerator() {

/**
* {@link com.tngtech.jgiven.annotation.IsTag#type()}
* @deprecated use {@link #getName()} instead
* @see com.tngtech.jgiven.annotation.IsTag
*/
@Deprecated
public String getType() {
return type;
return name;
}

/**
* {@link com.tngtech.jgiven.annotation.IsTag#name()}
* @see com.tngtech.jgiven.annotation.IsTag
*/
public String getName() {
return name;
}

/**
Expand Down Expand Up @@ -146,17 +187,12 @@ public String getCssClass() {
return cssClass;
}

public static TagConfiguration fromIsTag( IsTag isTag ) {
TagConfiguration result = new TagConfiguration();
result.defaultValue = isTag.value();
result.description = isTag.description();
result.explodeArray = isTag.explodeArray();
result.ignoreValue = isTag.ignoreValue();
result.prependType = isTag.prependType();
result.type = isTag.type();
result.descriptionGenerator = isTag.descriptionGenerator();
result.cssClass = isTag.cssClass();
result.color = isTag.color();
return result;
public List<String> getTags() {
return tags;
}

public String getAnnotationType() {
return annotationType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void setModel( ReportModel scenarioCollectionModel ) {
}

public ReportModel getModel() {
return modelBuilder.getScenarioCollectionModel();
return modelBuilder.getReportModel();
}

public <T> T addStage( Class<T> stepsClass ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

import java.io.PrintWriter;

import com.tngtech.jgiven.report.model.ScenarioCaseModel;
import com.tngtech.jgiven.report.model.ScenarioModel;
import com.tngtech.jgiven.report.model.StepModel;
import com.tngtech.jgiven.report.model.Word;
import com.tngtech.jgiven.report.model.*;

public class DataTableScenarioHtmlWriter extends ScenarioHtmlWriter {

public DataTableScenarioHtmlWriter( PrintWriter writer ) {
super( writer );
public DataTableScenarioHtmlWriter( PrintWriter writer, ReportModel reportModel ) {
super( writer, reportModel );
}

@Override
Expand Down Expand Up @@ -74,7 +71,7 @@ public void visit( StepModel stepModel ) {
}

@Override
String formatValue(Word value) {
String formatValue( Word value ) {
String paramName = findParameterName( value );
return "&lt;" + paramName + "&gt;";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import java.io.PrintWriter;

import com.tngtech.jgiven.report.model.ReportModel;

public class MultiCaseScenarioHtmlWriter extends ScenarioHtmlWriter {

public MultiCaseScenarioHtmlWriter( PrintWriter writer ) {
super( writer );
public MultiCaseScenarioHtmlWriter( PrintWriter writer, ReportModel reportModel ) {
super( writer, reportModel );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

import static java.lang.String.format;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.*;
import java.text.DateFormat;
import java.util.Date;

Expand All @@ -19,16 +14,13 @@
import com.tngtech.jgiven.impl.util.PrintWriterUtil;
import com.tngtech.jgiven.impl.util.ResourceUtil;
import com.tngtech.jgiven.impl.util.Version;
import com.tngtech.jgiven.report.model.ReportModel;
import com.tngtech.jgiven.report.model.ReportModelVisitor;
import com.tngtech.jgiven.report.model.ReportStatistics;
import com.tngtech.jgiven.report.model.ScenarioModel;
import com.tngtech.jgiven.report.model.StatisticsCalculator;
import com.tngtech.jgiven.report.model.*;

public class ReportModelHtmlWriter extends ReportModelVisitor {
protected final PrintWriter writer;
protected final HtmlWriterUtils utils;
private ReportStatistics statistics;
private ReportModel reportModel;

public ReportModelHtmlWriter( PrintWriter writer ) {
this.writer = writer;
Expand Down Expand Up @@ -61,7 +53,7 @@ private void closeDiv() {
}

public void write( ScenarioModel model ) {
writeHtmlHeader(model.getClassName());
writeHtmlHeader( model.getClassName() );
model.accept( this );
writeHtmlFooter();
}
Expand Down Expand Up @@ -142,6 +134,7 @@ public static void writeToFile( File file, ReportModel model, HtmlTocWriter html

@Override
public void visit( ReportModel reportModel ) {
this.reportModel = reportModel;
writer.println( "<div id='rightpane'>" );
writeHeader( reportModel );
writer.println( "<div id='content'>" );
Expand Down Expand Up @@ -191,9 +184,9 @@ public void visitEnd( ReportModel reportModel ) {
public void visit( ScenarioModel scenarioModel ) {
ScenarioHtmlWriter scenarioHtmlWriter;
if( scenarioModel.isCasesAsTable() ) {
scenarioHtmlWriter = new DataTableScenarioHtmlWriter( writer );
scenarioHtmlWriter = new DataTableScenarioHtmlWriter( writer, reportModel );
} else {
scenarioHtmlWriter = new MultiCaseScenarioHtmlWriter( writer );
scenarioHtmlWriter = new MultiCaseScenarioHtmlWriter( writer, reportModel );
}
scenarioModel.accept( scenarioHtmlWriter );
}
Expand Down
Loading

0 comments on commit 477ded1

Please sign in to comment.