Added tag based reporting

This commit is contained in:
Kingsley Hendrickse 2012-05-09 17:05:58 +01:00
parent 726b711734
commit e971a554ac
13 changed files with 922 additions and 101 deletions

View File

@ -27,6 +27,7 @@ public class FeatureReportGenerator {
private List<Util.Status> totalSteps;
private String pluginUrlPath;
private List<Feature> allFeatures;
private List<TagObject> allTags;
private static final String charEncoding = "UTF-8";
public FeatureReportGenerator(List<String> jsonResultFiles, File reportDirectory, String pluginUrlPath, String buildNumber, String buildProject) throws IOException {
@ -37,6 +38,7 @@ public class FeatureReportGenerator {
this.buildNumber = buildNumber;
this.buildProject = buildProject;
this.pluginUrlPath = getPluginUrlPath(pluginUrlPath);
this.allTags = findTagsInFeatures();
}
private Map<String, List<Feature>> parseJsonResults(List<String> jsonResultFiles) throws IOException {
@ -52,6 +54,8 @@ public class FeatureReportGenerator {
public void generateReports() throws Exception {
generateFeatureReports();
generateFeatureOverview();
generateTagReports();
generateTagOverview();
}
public void generateFeatureOverview() throws Exception {
@ -75,19 +79,7 @@ public class FeatureReportGenerator {
generateReport("feature-overview.html", featureOverview, context);
}
private List<Feature> listAllFeatures() {
List<Feature> allFeatures = new ArrayList<Feature>();
Iterator it = jsonResultFiles.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
List<Feature> featureList = (List<Feature>) pairs.getValue();
allFeatures.addAll(featureList);
}
return allFeatures;
}
public void generateFeatureReports() throws Exception {
Iterator it = jsonResultFiles.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
@ -110,6 +102,120 @@ public class FeatureReportGenerator {
}
}
public void generateTagReports() throws Exception {
for(TagObject tagObject : allTags) {
VelocityEngine ve = new VelocityEngine();
ve.init(getProperties());
Template featureResult = ve.getTemplate("templates/tagReport.vm");
VelocityContext context = new VelocityContext();
context.put("tag", tagObject);
context.put("time_stamp", timeStamp());
context.put("jenkins_base", pluginUrlPath);
context.put("build_project", buildProject);
context.put("build_number", buildNumber);
context.put("report_status_colour", getTagReportStatusColour(tagObject));
generateReport(tagObject.getTagName().replace("@", "").trim() + ".html", featureResult, context);
}
}
public void generateTagOverview() throws Exception {
VelocityEngine ve = new VelocityEngine();
ve.init(getProperties());
Template featureOverview = ve.getTemplate("templates/tagOverview.vm");
VelocityContext context = new VelocityContext();
context.put("build_project", buildProject);
context.put("build_number", buildNumber);
context.put("tags", allTags);
context.put("total_tags", getTotalTags());
context.put("total_scenarios", getTotalTagScenarios());
context.put("total_steps", getTotalTagSteps());
context.put("total_passes", getTotalTagPasses());
context.put("total_fails", getTotalTagFails());
context.put("total_skipped", getTotalTagSkipped());
context.put("chart_data", XmlChartBuilder.StackedColumnChart(allTags));
context.put("total_duration", getTotalTagDuration());
context.put("time_stamp", timeStamp());
context.put("jenkins_base", pluginUrlPath);
generateReport("tag-overview.html", featureOverview, context);
}
private List<TagObject> findTagsInFeatures() {
List<TagObject> tagMap = new ArrayList<TagObject>();
for (Feature feature : allFeatures) {
List<ScenarioTag> scenarioList = new ArrayList<ScenarioTag>();
if (feature.hasTags()) {
for (Element scenario : feature.getElements()) {
scenarioList.add(new ScenarioTag(scenario, feature.getFileName()));
tagMap = createOrAppendToTagMap(tagMap, feature.getTagList(), scenarioList);
}
}
for (Element scenario : feature.getElements()) {
if (scenario.hasTags()) {
scenarioList = addScenarioUnlessExists(scenarioList, new ScenarioTag(scenario, feature.getFileName()));
}
tagMap = createOrAppendToTagMap(tagMap, scenario.getTagList(), scenarioList);
}
}
return tagMap;
}
private List<ScenarioTag> addScenarioUnlessExists(List<ScenarioTag> scenarioList, ScenarioTag scenarioTag) {
boolean exists = false;
for(ScenarioTag scenario : scenarioList){
if(scenario.getParentFeatureUri().equalsIgnoreCase(scenarioTag.getParentFeatureUri())
&& scenario.getScenario().getName().equalsIgnoreCase(scenarioTag.getScenario().getName())){
exists = true;
break;
}
}
if (!exists) {
scenarioList.add(scenarioTag);
}
return scenarioList;
}
private List<TagObject> createOrAppendToTagMap(List<TagObject> tagMap, List<String> tagList, List<ScenarioTag> scenarioList) {
for (String tag : tagList) {
boolean exists = false;
TagObject tagObj = null;
for(TagObject tagObject : tagMap){
if(tagObject.getTagName().equalsIgnoreCase(tag)){
exists = true;
tagObj = tagObject;
break;
}
}
if (exists) {
List<ScenarioTag> existingTagList = tagObj.getScenarios();
for(ScenarioTag scenarioTag : scenarioList){
existingTagList = addScenarioUnlessExists(existingTagList, scenarioTag);
}
tagMap.remove(tagObj);
tagObj.setScenarios(existingTagList);
tagMap.add(tagObj);
} else {
tagObj = new TagObject(tag, scenarioList);
tagMap.add(tagObj);
}
}
return tagMap;
}
private List<Feature> listAllFeatures() {
List<Feature> allFeatures = new ArrayList<Feature>();
Iterator it = jsonResultFiles.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
List<Feature> featureList = (List<Feature>) pairs.getValue();
allFeatures.addAll(featureList);
}
return allFeatures;
}
private static final Pattern p = Pattern.compile("\\\\u\\s*([0-9(A-F|a-f)]{4})", Pattern.MULTILINE);
public static String U2U(String s) {
@ -130,6 +236,16 @@ public class FeatureReportGenerator {
return totalSteps.size();
}
private int getTotalTagSteps() {
int steps = 0;
for(TagObject tag : allTags){
for(ScenarioTag scenarioTag : tag.getScenarios()){
steps += scenarioTag.getScenario().getSteps().length;
}
}
return steps;
}
private String getTotalDuration() {
Long duration = 0L;
for (Feature feature : allFeatures) {
@ -142,6 +258,18 @@ public class FeatureReportGenerator {
return Util.formatDuration(duration);
}
private String getTotalTagDuration() {
Long duration = 0L;
for (TagObject tagObject : allTags) {
for (ScenarioTag scenario : tagObject.getScenarios()) {
for (Step step : scenario.getScenario().getSteps()) {
duration = duration + step.getDuration();
}
}
}
return Util.formatDuration(duration);
}
private int getTotalPasses() {
return Util.findStatusCount(totalSteps, Util.Status.PASSED);
}
@ -154,6 +282,30 @@ public class FeatureReportGenerator {
return Util.findStatusCount(totalSteps, Util.Status.SKIPPED);
}
private int getTotalTagPasses() {
int passes = 0;
for(TagObject tag : allTags){
passes += tag.getNumberOfPasses();
}
return passes;
}
private int getTotalTagFails() {
int failed = 0;
for(TagObject tag : allTags){
failed += tag.getNumberOfFailures();
}
return failed;
}
private int getTotalTagSkipped() {
int skipped = 0;
for(TagObject tag : allTags){
skipped += tag.getNumberOfSkipped();
}
return skipped;
}
private List<Util.Status> getAllStepStatuses() {
List<Util.Status> steps = new ArrayList<Util.Status>();
for (Feature feature : allFeatures) {
@ -169,6 +321,10 @@ public class FeatureReportGenerator {
private int getTotalFeatures() {
return allFeatures.size();
}
private int getTotalTags(){
return allTags.size();
}
private int getTotalScenarios() {
int scenarios = 0;
@ -177,6 +333,14 @@ public class FeatureReportGenerator {
}
return scenarios;
}
private int getTotalTagScenarios(){
int scenarios = 0;
for (TagObject tag : allTags) {
scenarios = scenarios + tag.getScenarios().size();
}
return scenarios;
}
private void generateReport(String fileName, Template featureResult, VelocityContext context) throws Exception {
Writer writer = new FileWriter(new File(reportDirectory, fileName));
@ -196,6 +360,10 @@ public class FeatureReportGenerator {
return feature.getStatus() == Util.Status.PASSED ? "#C5D88A" : "#D88A8A";
}
private String getTagReportStatusColour(TagObject tag) {
return tag.getStatus() == Util.Status.PASSED ? "#C5D88A" : "#D88A8A";
}
private String timeStamp() {
return new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date());
}

View File

@ -1,22 +1,22 @@
//package net.masterthought.jenkins;
//
//
//import java.io.File;
//import java.util.ArrayList;
//import java.util.List;
//
//public class Runner {
//
// public static void main(String[] args) throws Exception {
// File rd = new File("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports");
// List<String> list = new ArrayList<String>();
// list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/french.json");
// list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/co_cucumber.json");
// list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/ccp_cucumber.json");
// list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/ss_cucumber.json");
//
// FeatureReportGenerator featureReportGenerator = new FeatureReportGenerator(list,rd,"","15","aaaa");
// featureReportGenerator.generateReports();
//
// }
//}
package net.masterthought.jenkins;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Runner {
public static void main(String[] args) throws Exception {
File rd = new File("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports");
List<String> list = new ArrayList<String>();
list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/french.json");
list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/co_cucumber.json");
list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/ccp_cucumber.json");
list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/15/cucumber-html-reports/ss_cucumber.json");
FeatureReportGenerator featureReportGenerator = new FeatureReportGenerator(list,rd,"","15","aaaaa");
featureReportGenerator.generateReports();
}
}

View File

@ -0,0 +1,23 @@
package net.masterthought.jenkins;
import net.masterthought.jenkins.json.Element;
public class ScenarioTag {
private Element scenario;
private String parentFeatureUri;
public ScenarioTag(Element scenario, String parentFeatureUri){
this.scenario = scenario;
this.parentFeatureUri = parentFeatureUri;
}
public Element getScenario(){
return scenario;
}
public String getParentFeatureUri(){
return parentFeatureUri;
}
}

View File

@ -0,0 +1,107 @@
package net.masterthought.jenkins;
import net.masterthought.jenkins.json.Closure;
import net.masterthought.jenkins.json.Element;
import net.masterthought.jenkins.json.Step;
import net.masterthought.jenkins.json.Util;
import java.util.ArrayList;
import java.util.List;
public class TagObject {
private String tagName;
private List<ScenarioTag> scenarios = new ArrayList<ScenarioTag>();
private List<Element> elements = new ArrayList<Element>();
public String getTagName() {
return tagName;
}
public String getFileName(){
return tagName.replace("@","").trim() + ".html";
}
public List<ScenarioTag> getScenarios() {
return scenarios;
}
public void setScenarios(List<ScenarioTag> scenarioTagList){
this.scenarios = scenarioTagList;
}
public TagObject(String tagName, List<ScenarioTag> scenarios){
this.tagName = tagName;
this.scenarios = scenarios;
}
private void getElements() {
for(ScenarioTag scenarioTag : scenarios){
elements.add(scenarioTag.getScenario());
}
}
public Integer getNumberOfScenarios(){
return this.scenarios.size();
}
public String getDurationOfSteps() {
Long duration = 0L;
for (ScenarioTag scenarioTag : scenarios) {
for (Step step : scenarioTag.getScenario().getSteps()) {
duration = duration + step.getDuration();
}
}
return Util.formatDuration(duration);
}
public int getNumberOfSteps(){
int totalSteps = 0;
for(ScenarioTag scenario : scenarios){
totalSteps += scenario.getScenario().getSteps().length;
}
return totalSteps;
}
public int getNumberOfPasses() {
return Util.findStatusCount(getStatuses(), Util.Status.PASSED);
}
public int getNumberOfFailures() {
return Util.findStatusCount(getStatuses(), Util.Status.FAILED);
}
public int getNumberOfSkipped() {
return Util.findStatusCount(getStatuses(), Util.Status.SKIPPED);
}
private List<Util.Status> getStatuses(){
List<Util.Status> statuses = new ArrayList<Util.Status>();
for(ScenarioTag scenarioTag : scenarios){
for (Step step : scenarioTag.getScenario().getSteps()) {
statuses.add(step.getStatus());
}
}
return statuses;
}
public Util.Status getStatus() {
getElements();
Closure<String, Element> scenarioStatus = new Closure<String, Element>() {
public Util.Status call(Element step) {
return step.getStatus();
}
};
Element[] elementList = new Element[elements.size()];
List<Util.Status> results = Util.collectScenarios(elements.toArray(elementList), scenarioStatus);
return results.contains(Util.Status.FAILED) ? Util.Status.FAILED : Util.Status.PASSED;
}
public String getRawStatus() {
return getStatus().toString().toLowerCase();
}
}

View File

@ -1,12 +1,64 @@
package net.masterthought.jenkins;
import java.util.List;
public class XmlChartBuilder {
public static String donutChart(int total_passed, int total_failed, int total_skipped){
// I was going to use XMLBuilder to generate the chart - but it's so long and boring and I already have the xml so .....
return "<chart><chart_data><row><null/><string>Passed</string><string>Failed</string><string>Skipped</string></row><row><string></string><number shadow='high' bevel='data' line_color='FFFFFF' line_thickness='3' line_alpha='75'>" + total_passed + "</number><number shadow='high' bevel='data' line_color='FFFFFF' line_thickness='3' line_alpha='75'>" + total_failed + "</number><number shadow='high' bevel='data' line_color='FFFFFF' line_thickness='3' line_alpha='75'>" + total_skipped + "</number></row></chart_data><chart_label shadow='low' color='ffffff' alpha='95' size='10' position='inside' as_percentage='true' /><chart_pref select='true' /><chart_rect x='90' y='85' width='300' height='175' /><chart_transition type='scale' delay='1' duration='.5' order='category' /><chart_type>donut</chart_type><draw><rect transition='dissolve' layer='background' x='60' y='100' width='360' height='150' fill_alpha='0' line_color='ffffff' line_alpha='25' line_thickness='40' corner_tl='40' corner_tr='40' corner_br='40' corner_bl='40' /><circle transition='dissolve' layer='background' x='240' y='150' radius='150' fill_color='ccddff' fill_alpha='100' line_thickness='0' bevel='bg' blur='blur1' /><rect transition='dissolve' layer='background' shadow='soft' x='80' y='10' width='320' height='35' fill_color='ddeeff' fill_alpha='90' corner_tl='10' corner_tr='10' corner_br='10' corner_bl='10' /></draw><filter><shadow id='low' distance='2' angle='45' color='0' alpha='40' blurX='5' blurY='5' /><shadow id='high' distance='5' angle='45' color='0' alpha='40' blurX='10' blurY='10' /><shadow id='soft' distance='2' angle='45' color='0' alpha='20' blurX='5' blurY='5' /><bevel id='data' angle='45' blurX='5' blurY='5' distance='3' highlightAlpha='15' shadowAlpha='25' type='inner' /><bevel id='bg' angle='45' blurX='50' blurY='50' distance='10' highlightAlpha='35' shadowColor='0000ff' shadowAlpha='25' type='full' /><blur id='blur1' blurX='75' blurY='75' quality='1' /></filter><context_menu full_screen='false' /><legend transition='dissolve' x='90' width='300' bevel='low' fill_alpha='0' line_alpha='0' bullet='circle' size='12' color='000000' alpha='100' /><series_color><color>88dd11</color><color>cc1134</color><color>88aaff</color></series_color><series_explode><number>25</number><number>0</number><number>0</number></series_explode><series transfer='true' /></chart>";
}
public static String StackedColumnChart(List<TagObject> tagObjectList){
return "<chart><axis_category shadow='low' size='10' color='FFFFFF' alpha='75' /><axis_ticks value_ticks='true' category_ticks='true' minor_count='1' /><axis_value shadow='low' size='10' color='FFFFFF' alpha='75' /><chart_border top_thickness='0' bottom_thickness='2' left_thickness='2' right_thickness='0' /><chart_data><row><null/>"+generateRowsForColumnChart(tagObjectList)+"</row>"+generateColumnsForColumnChart(tagObjectList)+"</chart_data><chart_grid_h thickness='1' type='solid' /><chart_grid_v thickness='1' type='solid' /><chart_rect x='80' y='60' width='320' height='150' positive_color='888888' positive_alpha='50' /><chart_pref rotation_x='15' rotation_y='0' min_x='0' max_x='80' min_y='0' max_y='60' /><chart_type>stacked 3d column</chart_type><filter><shadow id='high' distance='5' angle='45' alpha='35' blurX='15' blurY='15' /><shadow id='low' distance='2' angle='45' alpha='50' blurX='5' blurY='5' /></filter><legend shadow='high' x='35' y='250' width='410' height='50' margin='20' fill_color='000000' fill_alpha='7' line_color='000000' line_alpha='0' line_thickness='0' layout='horizontal' size='12' color='000000' alpha='50' /><tooltip color='ffffcc' alpha='80' size='12' background_color_1='444488' background_alpha='75' shadow='low' /><series_color><color>C5D88A</color><color>D88A8A</color><color>2DEAEC</color></series_color><series bar_gap='0' set_gap='20' /></chart>";
}
private static String generateRowsForColumnChart(List<TagObject> tagObjectList){
StringBuffer buffer = new StringBuffer();
for(TagObject tag : tagObjectList){
buffer.append("<string>"+tag.getTagName()+"</string>");
}
return buffer.toString();
}
private static String generateColumnsForColumnChart(List<TagObject> tagObjectList){
StringBuffer buffer = new StringBuffer();
buffer.append("<row>");
buffer.append("<string>Passed</string>");
for(TagObject tag : tagObjectList){
buffer.append("<number tooltip='" +tag.getNumberOfPasses()+"'>"+tag.getNumberOfPasses()+"</number>");
}
buffer.append("</row>");
buffer.append("<row>");
buffer.append("<string>Failed</string>");
for(TagObject tag : tagObjectList){
buffer.append("<number tooltip='" +tag.getNumberOfFailures()+"'>"+tag.getNumberOfFailures()+"</number>");
}
buffer.append("</row>");
buffer.append("<row>");
buffer.append("<string>Skipped</string>");
for(TagObject tag : tagObjectList){
buffer.append("<number tooltip='" +tag.getNumberOfSkipped()+"'>"+tag.getNumberOfSkipped()+"</number>");
}
buffer.append("</row>");
return buffer.toString();
}
/*
<row>
<string>Region 1</string>
<number tooltip='22'>22</number>
<number tooltip='15'>15</number>
<number tooltip='11'>11</number>
<number tooltip='15'>15</number>
<number tooltip='20'>20</number>
<number tooltip='22'>22</number>
<number tooltip='21'>21</number>
</row>
*/
}

View File

@ -47,17 +47,31 @@ public class Element {
return Util.itemExists(contentString) ? Util.result(getStatus()) + StringUtils.join(contentString.toArray(), " ") + Util.closeDiv() : "";
}
public String getTags() {
String result = "<div class=\"feature-tags\"></div>";
public List<String> getTagList(){
return processTags();
}
public boolean hasTags(){
return Util.itemExists(tags);
}
private List<String> processTags(){
List<String> results = new ArrayList<String>();
if (Util.itemExists(tags)) {
StringClosure<String, Tag> scenarioTags = new StringClosure<String, Tag>() {
public String call(Tag tag) {
return tag.getName();
}
};
List<Util.Status> results = Util.collectTags(tags, scenarioTags);
String tagList = StringUtils.join(results.toArray(), ",");
results = Util.collectTags(tags, scenarioTags);
}
return results;
}
public String getTags() {
String result = "<div class=\"feature-tags\"></div>";
if (Util.itemExists(tags)) {
String tagList = StringUtils.join(processTags().toArray(), ",");
result = "<div class=\"feature-tags\">" + tagList + "</div>";
}
return result;

View File

@ -1,5 +1,7 @@
package net.masterthought.jenkins.json;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.List;
@ -10,6 +12,7 @@ public class Feature {
private String description;
private String keyword;
private Element[] elements;
private Tag[] tags;
public Feature(String name, String uri, String description, String keyword) {
this.name = name;
@ -22,6 +25,27 @@ public class Feature {
return elements;
}
public boolean hasTags(){
return Util.itemExists(tags);
}
public List<String> getTagList(){
List<String> tagList = new ArrayList<String>();
for(Tag tag : tags){
tagList.add(tag.getName());
}
return tagList;
}
public String getTags() {
String result = "<div class=\"feature-tags\"></div>";
if (Util.itemExists(tags)) {
String tagList = StringUtils.join(getTagList().toArray(), ",");
result = "<div class=\"feature-tags\">" + tagList + "</div>";
}
return result;
}
public Util.Status getStatus() {
Closure<String, Element> scenarioStatus = new Closure<String, Element>() {
public Util.Status call(Element step) {

View File

@ -1,5 +1,6 @@
package net.masterthought.jenkins.json;
import net.masterthought.jenkins.ScenarioTag;
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

View File

@ -73,6 +73,7 @@ table.stats-table td {
<div class="grid_6" id="nav">
<ul>
<li><a href="${jenkins_base}job/$build_project/$build_number">Back To Jenkins</a></li>
<li><a href="tag-overview.html">Tag Overview</a></li>
</ul>
</div>
</div>

View File

@ -96,7 +96,8 @@ table.data-table td {
<div class="grid_6" id="nav">
<ul>
<li><a href="${jenkins_base}job/$build_project/$build_number">Back To Jenkins</a></li>
<li><a href="feature-overview.html">Back To Overview</a></li>
<li><a href="tag-overview.html">Tag Overview</a></li>
<li><a href="feature-overview.html">Feature Overview</a></li>
</ul>
</div>
</div>
@ -105,15 +106,43 @@ table.data-table td {
<div class="container_12">
<div class="grid_9 heading">
<h2>Feature Result for Build: $build_number</h2>
<span class="subhead">Below are the results for this feature:</span>
</div>
</div>
</div>
<div class="container_12">
<div class="grid_12">
<div>
<table class="stats-table">
<tr>
<th>Feature</th>
<th>Scenarios</th>
<th>Steps</th>
<th>Passed</th>
<th>Failed</th>
<th>Skipped</th>
<th>Duration</th>
<th>Status</th>
</tr>
<tr>
<td><a href="$feature.getFileName()">$feature.getRawName()</a></td>
<td>$feature.getNumberOfScenarios()</td>
<td>$feature.getNumberOfSteps()</td>
<td>$feature.getNumberOfPasses()</td>
<td>$feature.getNumberOfFailures()</td>
<td>$feature.getNumberOfSkipped()</td>
<td>$feature.getDurationOfSteps()</td>
<td style="background-color: $report_status_colour;">$feature.getRawStatus()</td></tr>
</table>
</div>
<div style="color:black;">
$feature.getTags()
$feature.getName()
$feature.getDescription()
@ -138,38 +167,6 @@ table.data-table td {
#end
#end
<div>
<br/>
<h2>Feature Statistics</h2>
<table class="stats-table">
<tr>
<th>Feature</th>
<th>Scenarios</th>
<th>Steps</th>
<th>Passed</th>
<th>Failed</th>
<th>Skipped</th>
<th>Duration</th>
<th>Status</th>
</tr>
<tr>
<td><a href="$feature.getFileName()">$feature.getRawName()</a></td>
<td>$feature.getNumberOfScenarios()</td>
<td>$feature.getNumberOfSteps()</td>
<td>$feature.getNumberOfPasses()</td>
<td>$feature.getNumberOfFailures()</td>
<td>$feature.getNumberOfSkipped()</td>
<td>$feature.getDurationOfSteps()</td>
<td style="background-color: $report_status_colour;">$feature.getRawStatus()</td></tr>
</table>
</div>
</div>
</div>

View File

@ -0,0 +1,257 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script language="javascript">AC_FL_RunContent = 0;</script>
<script language="javascript"> DetectFlashVer = 0; </script>
<script src="${jenkins_base}plugin/cucumber-reports/charts/AC_RunActiveContent.js" language="javascript"></script>
<script language="JavaScript" type="text/javascript">
<!--
var requiredMajorVersion = 10;
var requiredMinorVersion = 0;
var requiredRevision = 45;
-->
</script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Cucumber-JVM Html Reports - Tag Overview</title>
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/style.css" type="text/css"
media="screen"/>
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/skin/style.css" type="text/css"
media="screen"/>
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/960.css" type="text/css"
media="screen"/>
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/reset.css" type="text/css"
media="screen"/>
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/text.css" type="text/css"
media="screen"/>
<link rel="shortcut icon" href="${jenkins_base}plugin/cucumber-reports/blue/favicon.ico"/>
<style>
.feature-keyword {
font-weight: bold;
}
.feature-description {
padding-left: 15px;
font-style: italic;
background-color: beige;
}
.feature-role {
font-weight: bold;
}
.feature-action {
font-weight: bold;
}
.feature-value {
font-weight: bold;
}
.feature-tags {
padding-top: 10px;
padding-left: 15px;
color: darkblue;
}
.scenario-keyword {
font-weight: bold;
padding-left: 15px;
}
.scenario-scenario_name {
padding-left: 15px;
}
.step-keyword {
font-weight: bold;
padding-left: 50px;
}
.step-error-message {
background-color: #FFEEEE;
padding-left: 50px;
border: 1px solid #D88A8A;
}
.passed {
background-color: #C5D88A;
}
.failed {
background-color: #D88A8A;
}
.skipped {
background-color: #2DEAEC;
}
.undefined {
background-color: #ebcc81;
}
table.stats-table {
color: black;
border-width: 1px;
border-spacing: 2px;
border-style: outset;
border-color: gray;
border-collapse: collapse;
background-color: white;
}
table.stats-table th {
color: black;
border-width: 1px;
padding: 5px;
border-style: inset;
border-color: gray;
background-color: #66CCEE;
-moz-border-radius:;
}
table.stats-table td {
color: black;
text-align: center;
border-width: 1px;
padding: 5px;
border-style: inset;
border-color: gray;
background-color: white;
-moz-border-radius:;
}
</style>
</head>
<body id="top">
<div id="fullwidth_header">
<div class="container_12">
<h1 class="grid_4 logo"><a href="feature-overview.html" class='ie6fix'>Cucumber</a></h1>
<div class="grid_6" id="nav">
<ul>
<li><a href="${jenkins_base}job/$build_project/$build_number">Back To Jenkins</a></li>
<li><a href="feature-overview.html">Feature Overview</a></li>
</ul>
</div>
</div>
</div>
<div id="fullwidth_gradient">
<div class="container_12">
<div class="grid_9 heading">
<h2>Tag Overview for Build: $build_number</h2>
<span class="subhead">The following graph shows number of steps passing, failing and skipped for this build:</span>
</div>
</div>
</div>
<div class="container_12">
<div class="grid_12">
<div style="text-align:center;"><script language="JavaScript" type="text/javascript">
<!--
if (AC_FL_RunContent == 0 || DetectFlashVer == 0) {
alert("This page requires AC_RunActiveContent.js.");
} else {
var hasRightVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
if(hasRightVersion) {
AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,45,2',
'width', '480',
'height', '300',
'scale', 'noscale',
'salign', 'TL',
'bgcolor', '#777788',
'wmode', 'opaque',
'movie', '${jenkins_base}plugin/cucumber-reports/charts/charts',
'src', '${jenkins_base}plugin/cucumber-reports/charts/charts',
'FlashVars', "library_path=${jenkins_base}plugin/cucumber-reports/charts/charts_library&xml_data=$chart_data",
'id', 'my_chart',
'name', 'my_chart',
'menu', 'true',
'allowFullScreen', 'true',
'allowScriptAccess','sameDomain',
'quality', 'high',
'align', 'middle',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'play', 'true',
'devicefont', 'false'
);
} else {
var alternateContent = 'This content requires the Adobe Flash Player. '
+ '<u><a href=http://www.macromedia.com/go/getflash/>Get Flash</a></u>.';
document.write(alternateContent);
}
}
// -->
</script>
<noscript>
<P>This content requires JavaScript.</P>
</noscript>
</div>
<br/>
<div class="grid_12 hr"></div>
<div>
<br/>
<h2>Tag Statistics</h2>
<table class="stats-table">
<tr>
<th>Tag</th>
<th>Scenarios</th>
<th>Steps</th>
<th>Passed</th>
<th>Failed</th>
<th>Skipped</th>
<th>Duration</th>
<th>Status</th>
</tr>
#foreach($tag in $tags)
#if($tag.getStatus().toString() == "PASSED")
#set($bgcolour = "#C5D88A")
#else
#set($bgcolour = "#D88A8A")
#end
<tr>
<td style="text-align:left;"><a href="$tag.getFileName()">$tag.getTagName()</a></td>
<td>$tag.getNumberOfScenarios()</td>
<td>$tag.getNumberOfSteps()</td>
<td>$tag.getNumberOfPasses()</td>
<td>$tag.getNumberOfFailures()</td>
<td>$tag.getNumberOfSkipped()</td>
<td>$tag.getDurationOfSteps()</td>
<td style="background-color: $bgcolour;">$tag.getRawStatus()</td>
</tr>
#end
<tr>
<td style="background-color:lightgray;font-weight:bold;">$total_tags</td>
<td style="background-color:lightgray;font-weight:bold;">$total_scenarios</td>
<td style="background-color:lightgray;font-weight:bold;">$total_steps</td>
<td style="background-color:lightgray;font-weight:bold;">$total_passes</td>
<td style="background-color:lightgray;font-weight:bold;">$total_fails</td>
<td style="background-color:lightgray;font-weight:bold;">$total_skipped</td>
<td style="background-color:lightgray;font-weight:bold;">$total_duration</td>
<td style="background-color:lightgray;font-weight:bold;">Totals</td>
</tr>
</table>
</div>
</div>
</div>
<div class="container_12">
<div class="grid_12 hr"></div>
<div class="grid_12 footer">
<p style="text-align:center;">Cucumber-JVM Jenkins Report Plugin - $time_stamp</p>
</div>
</div>
<div class="clear"></div>
</body>
</html>

View File

@ -0,0 +1,177 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Cucumber-JVM Html Reports - Tag: $tag.getTagName() </title>
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/style.css" type="text/css" media="screen" />
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/skin/style.css" type="text/css" media="screen" />
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/960.css" type="text/css" media="screen" />
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/reset.css" type="text/css" media="screen" />
<link rel="stylesheet" href="${jenkins_base}plugin/cucumber-reports/blue/css/text.css" type="text/css" media="screen" />
<link rel="shortcut icon" href="${jenkins_base}plugin/cucumber-reports/blue/favicon.ico" />
<style>
.feature-keyword{font-weight:bold;}
.feature-description{padding-left:15px;font-style:italic;background-color:beige;}
.feature-role{font-weight:bold;}
.feature-action{font-weight:bold;}
.feature-value{font-weight:bold;}
.feature-tags{padding-top:10px;padding-left:15px;color:darkblue;}
.scenario-keyword{font-weight:bold;padding-left:15px;}
.scenario-scenario_name{padding-left:15px;}
.step-keyword{font-weight:bold;padding-left:50px;}
.step-error-message{background-color:#FFEEEE;padding-left:50px;border: 1px solid #D88A8A;}
.passed{background-color:#C5D88A;}
.failed{background-color:#D88A8A;}
.skipped{background-color:#2DEAEC;}
.undefined{background-color: #ebcc81;}
table.stats-table {
color:black;
border-width: 1px;
border-spacing: 2px;
border-style: outset;
border-color: gray;
border-collapse: collapse;
background-color: white;
}
table.stats-table th {
color:black;
border-width: 1px;
padding: 5px;
border-style: inset;
border-color: gray;
background-color: #66CCEE;
-moz-border-radius: ;
}
table.stats-table td {
color:black;
text-align: center;
border-width: 1px;
padding: 5px;
border-style: inset;
border-color: gray;
background-color: white;
-moz-border-radius: ;
}
table.data-table {
color: black;
border-width: 1px;
border-spacing: 2px;
border-style: outset;
border-color: #d6d6d6;
border-collapse: collapse;
background-color: beige;
}
table.data-table th {
color:black;
border-width: 1px;
padding: 5px;
border-style: inset;
border-color: #d6d6d6;
background-color: #66CCEE;
}
table.data-table td {
color:black;
text-align: center;
border-width: 1px;
padding: 5px;
border-style: inset;
border-color: #d6d6d6;
background-color: beige;
}
.data {
padding-left:50px;
padding-bottom: 10px;
padding-top: 10px;
}
</style>
</head>
<body id="top">
<div id="fullwidth_header">
<div class="container_12">
<h1 class="grid_4 logo"><a href="feature-overview.html" class='ie6fix'>Cucumber</a></h1>
<div class="grid_6" id="nav">
<ul>
<li><a href="${jenkins_base}job/$build_project/$build_number">Back To Jenkins</a></li>
<li><a href="feature-overview.html">Feature Overview</a></li>
<li><a href="tag-overview.html">Tag Overview</a></li>
</ul>
</div>
</div>
</div>
<div id="fullwidth_gradient">
<div class="container_12">
<div class="grid_9 heading">
<h2>Result for <span style="color:#66CCEE;">$tag.getTagName()</span> in Build: $build_number</h2>
</div>
</div>
</div>
<div class="container_12">
<div class="grid_12">
<div>
<table class="stats-table">
<tr>
<th>Tag</th>
<th>Scenarios</th>
<th>Steps</th>
<th>Passed</th>
<th>Failed</th>
<th>Skipped</th>
<th>Duration</th>
<th>Status</th>
</tr>
<tr>
<td><a href="$tag.getFileName()">$tag.getTagName()</a></td>
<td>$tag.getNumberOfScenarios()</td>
<td>$tag.getNumberOfSteps()</td>
<td>$tag.getNumberOfPasses()</td>
<td>$tag.getNumberOfFailures()</td>
<td>$tag.getNumberOfSkipped()</td>
<td>$tag.getDurationOfSteps()</td>
<td style="background-color: $report_status_colour;">$tag.getRawStatus()</td></tr>
</table>
</div>
<div style="color:black;">
#foreach($scenario in $tag.getScenarios())
<div style="margin-bottom:20px;padding:15px;">
<div><a href="$scenario.getParentFeatureUri()">View Feature File</a></div>
$scenario.getScenario().getName()
#foreach($step in $scenario.getScenario().getSteps())
$step.getName()
#if($step.hasRows())
<div class="data $step.getDataTableClass()">
<table class="data-table">
#foreach($row in $step.getRows())
<tr>
#foreach($cell in $row.getCells())
<td>$cell</td>
#end
</tr>
#end
</table>
</div>
#end
#end
</div>
#end
</div>
</div>
<div class="container_12">
<div class="grid_12 hr"></div>
<div class="grid_12 footer">
<p style="text-align:center;">Cucumber-JVM Jenkins Report Plugin - $time_stamp</p>
</div>
</div>
<div class="clear"></div>
</body>

View File

@ -1,28 +1,28 @@
Fri Apr 27 15:48:26 BST 2012 [debug] AvalonLogChute initialized using file 'velocity.log'
Fri Apr 27 15:48:26 BST 2012 [trace] *******************************************************************
Fri Apr 27 15:48:26 BST 2012 [debug] Starting Jakarta Velocity v1.5-SNAPSHOT (compiled: 2006-07-21 06:25:35)
Fri Apr 27 15:48:26 BST 2012 [trace] RuntimeInstance initializing.
Fri Apr 27 15:48:26 BST 2012 [debug] Default Properties File: org/apache/velocity/runtime/defaults/velocity.properties
Fri Apr 27 15:48:26 BST 2012 [debug] Trying to use logger class org.apache.velocity.runtime.log.AvalonLogChute
Fri Apr 27 15:48:26 BST 2012 [debug] Using logger class org.apache.velocity.runtime.log.AvalonLogChute
Fri Apr 27 15:48:26 BST 2012 [debug] Default ResourceManager initializing. (class org.apache.velocity.runtime.resource.ResourceManagerImpl)
Fri Apr 27 15:48:26 BST 2012 [debug] ResourceLoader instantiated: org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
Fri Apr 27 15:48:26 BST 2012 [trace] ClasspathResourceLoader : initialization complete.
Fri Apr 27 15:48:26 BST 2012 [debug] ResourceCache: initialized (class org.apache.velocity.runtime.resource.ResourceCacheImpl)
Fri Apr 27 15:48:26 BST 2012 [trace] Default ResourceManager initialization complete.
Fri Apr 27 15:48:26 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Literal
Fri Apr 27 15:48:26 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Macro
Fri Apr 27 15:48:26 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Parse
Fri Apr 27 15:48:26 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Include
Fri Apr 27 15:48:26 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Foreach
Fri Apr 27 15:48:26 BST 2012 [debug] Created '20' parsers.
Fri Apr 27 15:48:26 BST 2012 [trace] Velocimacro : initialization starting.
Fri Apr 27 15:48:26 BST 2012 [debug] Velocimacro : "velocimacro.library" is not set. Trying default library: VM_global_library.vm
Fri Apr 27 15:48:26 BST 2012 [debug] Velocimacro : Default library not found.
Fri Apr 27 15:48:26 BST 2012 [debug] Velocimacro : allowInline = true : VMs can be defined inline in templates
Fri Apr 27 15:48:26 BST 2012 [debug] Velocimacro : allowInlineToOverride = false : VMs defined inline may NOT replace previous VM definitions
Fri Apr 27 15:48:26 BST 2012 [debug] Velocimacro : allowInlineLocal = false : VMs defined inline will be global in scope if allowed.
Fri Apr 27 15:48:26 BST 2012 [debug] Velocimacro : autoload off : VM system will not automatically reload global library macros
Fri Apr 27 15:48:26 BST 2012 [trace] Velocimacro : initialization complete.
Fri Apr 27 15:48:26 BST 2012 [trace] RuntimeInstance successfully initialized.
Fri Apr 27 15:48:27 BST 2012 [debug] ResourceManager : found templates/featureOverview.vm with loader org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
Wed May 09 17:01:28 BST 2012 [debug] AvalonLogChute initialized using file 'velocity.log'
Wed May 09 17:01:28 BST 2012 [trace] *******************************************************************
Wed May 09 17:01:28 BST 2012 [debug] Starting Jakarta Velocity v1.5-SNAPSHOT (compiled: 2006-07-21 06:25:35)
Wed May 09 17:01:28 BST 2012 [trace] RuntimeInstance initializing.
Wed May 09 17:01:28 BST 2012 [debug] Default Properties File: org/apache/velocity/runtime/defaults/velocity.properties
Wed May 09 17:01:28 BST 2012 [debug] Trying to use logger class org.apache.velocity.runtime.log.AvalonLogChute
Wed May 09 17:01:28 BST 2012 [debug] Using logger class org.apache.velocity.runtime.log.AvalonLogChute
Wed May 09 17:01:28 BST 2012 [debug] Default ResourceManager initializing. (class org.apache.velocity.runtime.resource.ResourceManagerImpl)
Wed May 09 17:01:28 BST 2012 [debug] ResourceLoader instantiated: org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
Wed May 09 17:01:28 BST 2012 [trace] ClasspathResourceLoader : initialization complete.
Wed May 09 17:01:28 BST 2012 [debug] ResourceCache: initialized (class org.apache.velocity.runtime.resource.ResourceCacheImpl)
Wed May 09 17:01:28 BST 2012 [trace] Default ResourceManager initialization complete.
Wed May 09 17:01:28 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Literal
Wed May 09 17:01:28 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Macro
Wed May 09 17:01:28 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Parse
Wed May 09 17:01:28 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Include
Wed May 09 17:01:28 BST 2012 [debug] Loaded System Directive: org.apache.velocity.runtime.directive.Foreach
Wed May 09 17:01:28 BST 2012 [debug] Created '20' parsers.
Wed May 09 17:01:28 BST 2012 [trace] Velocimacro : initialization starting.
Wed May 09 17:01:28 BST 2012 [debug] Velocimacro : "velocimacro.library" is not set. Trying default library: VM_global_library.vm
Wed May 09 17:01:28 BST 2012 [debug] Velocimacro : Default library not found.
Wed May 09 17:01:28 BST 2012 [debug] Velocimacro : allowInline = true : VMs can be defined inline in templates
Wed May 09 17:01:28 BST 2012 [debug] Velocimacro : allowInlineToOverride = false : VMs defined inline may NOT replace previous VM definitions
Wed May 09 17:01:28 BST 2012 [debug] Velocimacro : allowInlineLocal = false : VMs defined inline will be global in scope if allowed.
Wed May 09 17:01:28 BST 2012 [debug] Velocimacro : autoload off : VM system will not automatically reload global library macros
Wed May 09 17:01:28 BST 2012 [trace] Velocimacro : initialization complete.
Wed May 09 17:01:28 BST 2012 [trace] RuntimeInstance successfully initialized.
Wed May 09 17:01:28 BST 2012 [debug] ResourceManager : found templates/tagOverview.vm with loader org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader