Skip to content

Commit

Permalink
Generate page for pending scenarios and fix calculation of failed sce…
Browse files Browse the repository at this point in the history
…narios (fixed #33)
  • Loading branch information
Jan Schäfer committed Oct 5, 2014
1 parent 440b54c commit c44ca88
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.google.common.collect.Ordering;
import com.tngtech.jgiven.report.html.PackageTocBuilder.PackageToc;
import com.tngtech.jgiven.report.html.StaticHtmlReportGenerator.ModelFile;
import com.tngtech.jgiven.report.model.ReportStatistics;
import com.tngtech.jgiven.report.model.ScenarioModel;
import com.tngtech.jgiven.report.model.Tag;

Expand All @@ -24,10 +25,12 @@ public class HtmlTocWriter {
private final Map<Tag, List<ScenarioModel>> tagMap;
private final PackageToc packageToc;
private final ImmutableListMultimap<String, Tag> groupedTags;
private final ReportStatistics totalStatistics;

public HtmlTocWriter( Map<Tag, List<ScenarioModel>> tagMap, PackageToc packageToc ) {
public HtmlTocWriter( Map<Tag, List<ScenarioModel>> tagMap, PackageToc packageToc, ReportStatistics totalStatistics ) {
this.tagMap = tagMap;
this.packageToc = packageToc;
this.totalStatistics = totalStatistics;
groupedTags = getGroupedTags();
}

Expand All @@ -48,11 +51,19 @@ public void writeToc( PrintWriter writer ) {
private void writeSummary() {
writer.println( "<h3><a href='index.html'>Summary</a></h3>" );
writer.println( "<ul>" );
writer.println( "<li><a href='all.html'>All Scenarios</a>" );
writer.println( "<li><a href='failed.html'>Failed Scenarios</a>" );
writeLink( totalStatistics.numScenarios, "all.html", "All Scenarios" );
writeLink( totalStatistics.numPendingScenarios, "pending.html", "Pending Scenarios" );
writeLink( totalStatistics.numFailedScenarios, "failed.html", "Failed Scenarios" );
writer.println( "</ul>" );
}

private void writeLink( int count, String fileName, String title ) {
if( count > 0 ) {
writer.print( "<li><a href='" + fileName + "'>" + title );
writer.println( " <span class='badge count'>" + count + "</span></a>" );
}
}

private void writeSearchInput() {
writer.println( "<input class='search-input' id='toc-search-input' "
+ "placeholder='enter regexp to search in toc' onkeydown='searchChanged(event)'></input>" );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ void writeHeader( ReportModel reportModel ) {
className = Files.getFileExtension( reportModel.getClassName() );
}

if( !Strings.isNullOrEmpty( packageName ) ) {
writer.println( format( "<div class='packagename'>%s</div>", packageName ) );
}
writer.println( format( "<div class='packagename'>%s</div>", packageName ) );

writer.println( format( "<h2>%s</h2>", className ) );
writer.println( "</div> <!-- #header-title -->" );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class StaticHtmlReportGenerator implements ReportModelFileHandler {
static class ModelFile {
ReportModel model;
File file;
ReportStatistics statistics;
}

private final List<ModelFile> models = Lists.newArrayList();
Expand Down Expand Up @@ -93,28 +94,40 @@ public void handleReportModel( ReportModel model, File file ) {
}

public void writeEnd() {
ReportStatistics totalStatistics = calulcateStatistics();

PackageToc packageToc = new PackageTocBuilder( models ).getRootPackageToc();
HtmlTocWriter tocWriter = new HtmlTocWriter( tagMap, packageToc );
ReportStatistics totalStatistics = new ReportStatistics();
HtmlTocWriter tocWriter = new HtmlTocWriter( tagMap, packageToc, totalStatistics );
List<ScenarioModel> failedScenarios = Lists.newArrayList();
List<ScenarioModel> pendingScenarios = Lists.newArrayList();
List<ScenarioModel> allScenarios = Lists.newArrayList();

for( ModelFile modelFile : models ) {
ReportModelHtmlWriter modelWriter = ReportModelHtmlWriter.writeModelToFile( modelFile.model, tocWriter, modelFile.file );
totalStatistics = totalStatistics.add( modelWriter.getStatistics() );
failedScenarios.addAll( modelFile.model.getFailedScenarios() );
pendingScenarios.addAll( modelFile.model.getPendingScenarios() );
allScenarios.addAll( modelFile.model.getScenarios() );
}

writeTagFiles( tocWriter );
writeScenarios( tocWriter, failedScenarios, ".Failed Scenarios", "failed.html" );
writeScenarios( tocWriter, allScenarios, ".All Scenarios", "all.html" );
writeScenarios( tocWriter, failedScenarios, "Failed Scenarios", "failed.html" );
writeScenarios( tocWriter, pendingScenarios, "Pending Scenarios", "pending.html" );
writeScenarios( tocWriter, allScenarios, "All Scenarios", "all.html" );

StatisticsPageHtmlWriter statisticsPageHtmlWriter = new StatisticsPageHtmlWriter( tocWriter, totalStatistics );
statisticsPageHtmlWriter.write( toDir );

}

private ReportStatistics calulcateStatistics() {
ReportStatistics totalStatistics = new ReportStatistics();
for( ModelFile modelFile : models ) {
modelFile.statistics = new StatisticsCalculator().getStatistics( modelFile.model );
totalStatistics = totalStatistics.add( modelFile.statistics );
}
return totalStatistics;
}

private void writeScenarios( HtmlTocWriter tocWriter, List<ScenarioModel> failedScenarios, String name, String fileName ) {
ReportModel reportModel = new ReportModel();
reportModel.setScenarios( failedScenarios );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,28 @@ private void writeStatistics() {
printWriter.write( "<div class='statistics-line'>" );
writeStatisticNumber( statistics.numClasses, "classes" );

printWriter.write( "<div class='statistics-number'><a href='all.html'><i>"
+ statistics.numScenarios + "</i><br/><b>scenarios</b></a></div>" );
writeStatisticsNumberWithLink( statistics.numScenarios, "scenarios", "all.html" );

writeStatisticNumber( statistics.numCases, "cases" );
writeStatisticNumber( statistics.numSteps, "steps" );

String failedClass = statistics.numFailedCases > 0 ? "failed" : "";
writeStatisticsNumberWithLink( statistics.numPendingScenarios, "pending scenarios", "pending.html" );

String failedClass = statistics.numFailedScenarios > 0 ? "failed" : "";
printWriter.write( "<div class='statistics-number " + failedClass + "'><a href='failed.html'><i>"
+ statistics.numFailedCases + "</i><br/><b>failed cases</b></a></div>" );
+ statistics.numFailedScenarios + "</i><br/><b>failed scenarios</b></a></div>" );

writeStatisticNumber( DurationFormatter.format( statistics.durationInNanos ), "total time" );
long averageNanos = statistics.numCases != 0 ? statistics.durationInNanos / statistics.numCases : 0;
writeStatisticNumber( DurationFormatter.format( averageNanos ), "time / case" );
printWriter.println( "</div>" );
}

private void writeStatisticsNumberWithLink( int number, String title, String fileName ) {
printWriter.write( "<div class='statistics-number'><a href='" + fileName + "'><i>"
+ number + "</i><br/><b>" + title + "</b></a></div>" );
}

private void writeStatisticNumber( int number, String name ) {
writeStatisticNumber( number + "", name );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ public void visit( ScenarioModel scenarioModel ) {
}
}

@Override
public void visit( ScenarioCaseModel scenarioCase ) {
if( !scenarioCase.success ) {
status = ExecutionStatus.FAILED;
}
}

@Override
public void visit( StepModel stepModel ) {
if( stepModel.isFailed() ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

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

import com.google.common.base.Optional;
Expand Down Expand Up @@ -101,13 +102,22 @@ public String getPackageName() {
}

public List<ScenarioModel> getFailedScenarios() {
return getScenariosWithStatus( ExecutionStatus.FAILED );
}

public List<ScenarioModel> getPendingScenarios() {
return getScenariosWithStatus( ExecutionStatus.NONE_IMPLEMENTED, ExecutionStatus.PARTIALLY_IMPLEMENTED );
}

public List<ScenarioModel> getScenariosWithStatus( ExecutionStatus first, ExecutionStatus... rest ) {
EnumSet<ExecutionStatus> stati = EnumSet.of( first, rest );
List<ScenarioModel> result = Lists.newArrayList();
for( ScenarioModel m : scenarios ) {
if( m.getExecutionStatus() == ExecutionStatus.FAILED ) {
ExecutionStatus executionStatus = m.getExecutionStatus();
if( stati.contains( executionStatus ) ) {
result.add( m );
}
}
return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
public class ReportStatistics {
public int numClasses;
public int numScenarios;
public int numFailedScenarios;
public int numCases;
public int numFailedCases;
public int numSteps;
public long durationInNanos;
public int numPendingScenarios;
public int numSuccessfulScenarios;

public ReportStatistics add( ReportStatistics statistics ) {
ReportStatistics copy = new ReportStatistics();
Expand All @@ -18,6 +21,9 @@ public ReportStatistics add( ReportStatistics statistics ) {
private void addModifying( ReportStatistics statistics ) {
this.numClasses += statistics.numClasses;
this.numScenarios += statistics.numScenarios;
this.numFailedScenarios += statistics.numFailedScenarios;
this.numPendingScenarios += statistics.numPendingScenarios;
this.numSuccessfulScenarios += statistics.numSuccessfulScenarios;
this.numCases += statistics.numCases;
this.numFailedCases += statistics.numFailedCases;
this.numSteps += statistics.numSteps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class ScenarioModel {
private boolean casesAsTable;
private final List<ScenarioCaseModel> scenarioCases = Lists.newArrayList();
private long durationInNanos;
private ExecutionStatus executionStatus;

public void accept( ReportModelVisitor visitor ) {
visitor.visit( this );
Expand All @@ -34,9 +35,12 @@ public void addCase( ScenarioCaseModel scenarioCase ) {
}

public ExecutionStatus getExecutionStatus() {
ExecutionStatusCalculator executionStatusCalculator = new ExecutionStatusCalculator();
this.accept( executionStatusCalculator );
return executionStatusCalculator.executionStatus();
if( executionStatus == null ) {
ExecutionStatusCalculator executionStatusCalculator = new ExecutionStatusCalculator();
this.accept( executionStatusCalculator );
executionStatus = executionStatusCalculator.executionStatus();
}
return executionStatus;
}

public ScenarioCaseModel getCase( int i ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ public void visit( ReportModel reportModel ) {
public void visit( ScenarioModel scenarioModel ) {
statistics.numScenarios++;
statistics.durationInNanos += scenarioModel.getDurationInNanos();
ExecutionStatus executionStatus = scenarioModel.getExecutionStatus();
if( executionStatus == ExecutionStatus.FAILED ) {
statistics.numFailedScenarios += 1;
} else if( executionStatus == ExecutionStatus.NONE_IMPLEMENTED || executionStatus == ExecutionStatus.PARTIALLY_IMPLEMENTED ) {
statistics.numPendingScenarios += 1;
} else {
statistics.numSuccessfulScenarios += 1;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tngtech.jgiven.examples.notimplementedyet;

import org.assertj.core.api.Assertions;
import org.junit.Test;

import com.tngtech.jgiven.annotation.Description;
Expand All @@ -14,20 +15,37 @@ public class NotImplementYetExampleTest extends SimpleScenarioTest<NotImplementY

@Test
@FeatureNotImplementedYet
@NotImplementedYet
// @NotImplementedYet
public void tests_that_are_not_implemented_yet_can_be_annotated_with_the_NotImplementedYet_annotation() {
given().some_state();
when().some_action();
then().some_result();

Assertions.assertThat( true ).isFalse();
}

@Test
@FeatureNotImplementedYet
@NotImplementedYet
public void a_tests_that_are_not_implemented_yet_can_be_annotated_with_the_NotImplementedYet_annotation() {
given().some_state();
when().some_action();
then().some_result();
}

public static class TestSteps {

public void some_state() {}
public TestSteps some_state() {
return this;
}

public void some_result() {}
public TestSteps some_result() {
return this;
}

public void some_action() {}
public TestSteps some_action() {
return this;
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.tngtech.jgiven.junit.de;
package com.tngtech.jgiven.junit;

import org.junit.Test;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import com.tngtech.jgiven.Stage;
import com.tngtech.jgiven.annotation.ExpectedScenarioState;
import com.tngtech.jgiven.report.model.ReportModel;
import com.tngtech.jgiven.report.model.ScenarioModel;

public class ThenReportGenerator<SELF extends ThenReportGenerator<?>> extends Stage<SELF> {

Expand All @@ -21,4 +28,24 @@ public class ThenReportGenerator<SELF extends ThenReportGenerator<?>> extends St
assertThat( new File( targetReportDir, name ) ).exists();
return self();
}

public SELF file_$_contains_scenario_$( String fileName, int scenarioNr ) throws IOException {
final ScenarioModel scenarioModel = reportModels.get( 0 ).getScenarios().get( 0 );
final String regex = "<div class='scenario-footer'>.*" + scenarioModel.className + "</a></div>";
return file_$_contains( fileName, regex );
}

public SELF file_$_contains( String fileName, final String regex ) throws IOException {
ImmutableList<String> content = Files.asCharSource( new File( targetReportDir, fileName ), Charset.forName( "utf8" ) ).readLines();

boolean match = FluentIterable.from( content ).anyMatch( new Predicate<String>() {
@Override
public boolean apply( String input ) {
return input.matches( regex );
}
} );

assertThat( match ).as( "file " + fileName + " does not contain " + regex ).isTrue();
return self();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.tngtech.jgiven.JGivenScenarioTest;
import com.tngtech.jgiven.report.WhenReportGenerator;
import com.tngtech.jgiven.report.json.GivenJsonReports;
import com.tngtech.jgiven.report.model.StepStatus;
import com.tngtech.jgiven.tags.FeatureHtmlReport;
import com.tngtech.jgiven.tags.FeatureTags;
import com.tngtech.jgiven.tags.Issue;
Expand Down Expand Up @@ -68,4 +69,33 @@ public void the_static_HTML_report_generates_one_file_for_all_failed_scenarios()
when().the_static_HTML_reporter_is_executed();
then().a_file_with_name_$_exists( "failed.html" );
}

@Test
@Issue( "#33" )
public void the_failed_file_generated_by_the_static_HTML_report_generator_contains_scenarios_where_some_cases_are_failed()
throws IOException {
given().a_report_model()
.and().the_report_has_$_scenarios( 1 )
.and().the_scenario_has_$_default_cases( 2 )
.and().case_$_of_scenario_$_has_failed( 1, 1 )
.and().step_$_of_case_$_has_status( 1, 1, StepStatus.FAILED )
.and().the_report_exist_as_JSON_file();
when().the_static_HTML_reporter_is_executed();
then().a_file_with_name_$_exists( "failed.html" )
.and().file_$_contains_scenario_$( "failed.html", 1 );
}

@Test
@Issue( "#33" )
public void the_failed_file_generated_by_the_static_HTML_report_generator_contains_failed_scenarios_where_all_steps_are_successful()
throws IOException {
given().a_report_model()
.and().the_report_has_$_scenarios( 1 )
.and().case_$_of_scenario_$_has_failed( 1, 1 )
.and().the_report_exist_as_JSON_file();
when().the_static_HTML_reporter_is_executed();
then().a_file_with_name_$_exists( "failed.html" )
.and().file_$_contains_scenario_$( "failed.html", 1 );
}

}
Loading

0 comments on commit c44ca88

Please sign in to comment.