From 979abc7b1ed83eac7c08acd1e9af5fa4391b78c3 Mon Sep 17 00:00:00 2001 From: Kingsley Hendrickse Date: Fri, 27 Apr 2012 15:51:46 +0100 Subject: [PATCH] Added in durations and fixed unicode bug when parsing --- cucumber-reports.iml | 1 + pom.xml | 7 ++- .../jenkins/FeatureReportGenerator.java | 49 ++++++++++++---- .../net/masterthought/jenkins/Runner.java | 42 +++++++------- .../masterthought/jenkins/json/Feature.java | 10 ++++ .../masterthought/jenkins/json/Result.java | 8 ++- .../net/masterthought/jenkins/json/Step.java | 12 ++-- .../net/masterthought/jenkins/json/Util.java | 53 +++++++++++++++++- .../resources/templates/featureOverview.vm | 8 ++- src/main/resources/templates/featureReport.vm | 3 + velocity.log | 56 +++++++++---------- 11 files changed, 174 insertions(+), 75 deletions(-) diff --git a/cucumber-reports.iml b/cucumber-reports.iml index 439a0c8..838d5af 100644 --- a/cucumber-reports.iml +++ b/cucumber-reports.iml @@ -39,6 +39,7 @@ + diff --git a/pom.xml b/pom.xml index da0db5a..2a2f25f 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ net.masterthought.jenkins cucumber-reports - 0.0.3 + 0.0.5 hpi @@ -49,5 +49,10 @@ java-xmlbuilder 0.4 + + joda-time + joda-time + 2.1 + diff --git a/src/main/java/net/masterthought/jenkins/FeatureReportGenerator.java b/src/main/java/net/masterthought/jenkins/FeatureReportGenerator.java index 0e2e0fe..83ad8b2 100644 --- a/src/main/java/net/masterthought/jenkins/FeatureReportGenerator.java +++ b/src/main/java/net/masterthought/jenkins/FeatureReportGenerator.java @@ -1,6 +1,7 @@ package net.masterthought.jenkins; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import net.masterthought.jenkins.json.Element; import net.masterthought.jenkins.json.Feature; import net.masterthought.jenkins.json.Step; @@ -8,10 +9,15 @@ import net.masterthought.jenkins.json.Util; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; +import org.joda.time.Period; +import org.joda.time.format.PeriodFormatter; +import org.joda.time.format.PeriodFormatterBuilder; import java.io.*; import java.text.SimpleDateFormat; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class FeatureReportGenerator { @@ -22,6 +28,7 @@ public class FeatureReportGenerator { private List totalSteps; private String pluginUrlPath; private List allFeatures; + private static final String charEncoding = "UTF-8"; public FeatureReportGenerator(List jsonResultFiles, File reportDirectory, String pluginUrlPath, String buildNumber, String buildProject) throws IOException { this.jsonResultFiles = parseJsonResults(jsonResultFiles); @@ -33,11 +40,12 @@ public class FeatureReportGenerator { this.pluginUrlPath = getPluginUrlPath(pluginUrlPath); } - private Map> parseJsonResults(List jsonResultFiles) throws FileNotFoundException { + private Map> parseJsonResults(List jsonResultFiles) throws IOException { Map> featureResults = new HashMap>(); for (String jsonFile : jsonResultFiles) { - FileReader reader = new FileReader(jsonFile); - featureResults.put(jsonFile, Arrays.asList(new Gson().fromJson(reader, Feature[].class))); + String fileContent = U2U(Util.readFileAsString(jsonFile)); + Feature[] features = new Gson().fromJson(fileContent, Feature[].class); + featureResults.put(jsonFile, Arrays.asList(features)); } return featureResults; } @@ -63,11 +71,12 @@ public class FeatureReportGenerator { context.put("total_skipped", getTotalSkipped()); context.put("chart_data", XmlChartBuilder.donutChart(getTotalPasses(), getTotalFails(), getTotalSkipped())); context.put("time_stamp", timeStamp()); + context.put("total_duration", getTotalDuration()); context.put("jenkins_base", pluginUrlPath); generateReport("feature-overview.html", featureOverview, context); } - private List listAllFeatures(){ + private List listAllFeatures() { List allFeatures = new ArrayList(); Iterator it = jsonResultFiles.entrySet().iterator(); while (it.hasNext()) { @@ -77,7 +86,7 @@ public class FeatureReportGenerator { } return allFeatures; } - + public void generateFeatureReports() throws Exception { Iterator it = jsonResultFiles.entrySet().iterator(); @@ -100,10 +109,19 @@ public class FeatureReportGenerator { generateReport(feature.getFileName(), featureResult, context); } } - - } + private static final Pattern p = Pattern.compile("\\\\u\\s*([0-9(A-F|a-f)]{4})", Pattern.MULTILINE); + + public static String U2U(String s) { + String res = s; + Matcher m = p.matcher(res); + while (m.find()) { + res = res.replaceAll("\\" + m.group(0), + Character.toString((char) Integer.parseInt(m.group(1), 16))); + } + return res; + } private String getPluginUrlPath(String path) { return path.isEmpty() ? "/" : path; @@ -113,6 +131,18 @@ public class FeatureReportGenerator { return totalSteps.size(); } + private String getTotalDuration() { + Long duration = 0L; + for (Feature feature : allFeatures) { + for (Element scenario : feature.getElements()) { + for (Step step : scenario.getSteps()) { + duration = duration + step.getDuration(); + } + } + } + return Util.formatDuration(duration); + } + private int getTotalPasses() { return Util.findStatusCount(totalSteps, Util.Status.PASSED); } @@ -167,11 +197,6 @@ public class FeatureReportGenerator { return feature.getStatus() == Util.Status.PASSED ? "#C5D88A" : "#D88A8A"; } -// private List parseJson(String jsonResultFile) throws FileNotFoundException { -// FileReader reader = new FileReader(jsonResultFile); -// return Arrays.asList(new Gson().fromJson(reader, Feature[].class)); -// } - private String timeStamp() { return new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date()); } diff --git a/src/main/java/net/masterthought/jenkins/Runner.java b/src/main/java/net/masterthought/jenkins/Runner.java index ff856a7..04bb2c7 100644 --- a/src/main/java/net/masterthought/jenkins/Runner.java +++ b/src/main/java/net/masterthought/jenkins/Runner.java @@ -1,20 +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/3/cucumber-html-reports"); -// List list = new ArrayList(); -// list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/3/cucumber-html-reports/ss_cucumber.json"); -// list.add("/Users/kings/.jenkins/jobs/aaaaa/builds/3/cucumber-html-reports/co_cucumber.json"); -// -// FeatureReportGenerator featureReportGenerator = new FeatureReportGenerator(list,rd,"","3","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 list = new ArrayList(); + 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(); + + } +} diff --git a/src/main/java/net/masterthought/jenkins/json/Feature.java b/src/main/java/net/masterthought/jenkins/json/Feature.java index f50dc15..d24e811 100644 --- a/src/main/java/net/masterthought/jenkins/json/Feature.java +++ b/src/main/java/net/masterthought/jenkins/json/Feature.java @@ -89,6 +89,16 @@ public class Feature { public String getRawStatus() { return getStatus().toString().toLowerCase(); } + + public String getDurationOfSteps(){ + Long totalDuration = 0L; + for(Element element : elements){ + for(Step step : element.getSteps()){ + totalDuration = totalDuration + step.getDuration(); + } + } + return Util.formatDuration(totalDuration); + } } diff --git a/src/main/java/net/masterthought/jenkins/json/Result.java b/src/main/java/net/masterthought/jenkins/json/Result.java index 2ab24b8..356c111 100644 --- a/src/main/java/net/masterthought/jenkins/json/Result.java +++ b/src/main/java/net/masterthought/jenkins/json/Result.java @@ -4,9 +4,9 @@ public class Result { private String status; private String error_message; - private int duration; + private Long duration; - public Result(String status, String error_message, int duration){ + public Result(String status, String error_message, Long duration){ this.status = status; this.error_message = error_message; this.duration = duration; @@ -16,6 +16,10 @@ public class Result { return status; } + public Long getDuration(){ + return duration == null ? 0L : duration; + } + public String getErrorMessage(){ return error_message; } diff --git a/src/main/java/net/masterthought/jenkins/json/Step.java b/src/main/java/net/masterthought/jenkins/json/Step.java index 725d3ac..e8ffc77 100644 --- a/src/main/java/net/masterthought/jenkins/json/Step.java +++ b/src/main/java/net/masterthought/jenkins/json/Step.java @@ -15,14 +15,6 @@ public class Step { this.keyword = keyword; } - -// public Row getTitleRow(){ -// return rows[0]; -// } - -// public List getRows(){ -// return Arrays.asList(rows).subList(1, -1); -// } public Row[] getRows(){ return rows; @@ -38,6 +30,10 @@ public class Step { return result; } + public Long getDuration(){ + return result.getDuration(); + } + public Util.Status getStatus() { return Util.resultMap.get(result.getStatus()); } diff --git a/src/main/java/net/masterthought/jenkins/json/Util.java b/src/main/java/net/masterthought/jenkins/json/Util.java index 348e465..ab423ab 100644 --- a/src/main/java/net/masterthought/jenkins/json/Util.java +++ b/src/main/java/net/masterthought/jenkins/json/Util.java @@ -3,7 +3,16 @@ package net.masterthought.jenkins.json; import net.masterthought.jenkins.json.Closure; import net.masterthought.jenkins.json.Element; import net.masterthought.jenkins.json.Step; +import org.joda.time.DateTime; +import org.joda.time.Duration; +import org.joda.time.Period; +import org.joda.time.format.PeriodFormatter; +import org.joda.time.format.PeriodFormatterBuilder; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,22 +44,25 @@ public class Util { put("passed", Util.Status.PASSED); put("failed", Util.Status.FAILED); put("skipped", Util.Status.SKIPPED); + put("undefined", Util.Status.UNDEFINED); }}; public static String result(Status status) { - String result = ""; + String result = "
"; if (status == Status.PASSED) { result = "
"; } else if (status == Status.FAILED) { result = "
"; } else if (status == Status.SKIPPED) { result = "
"; + } else if (status == Status.UNDEFINED){ + result = "
"; } return result; } public static enum Status { - PASSED, FAILED, SKIPPED + PASSED, FAILED, SKIPPED, UNDEFINED } public static List collectScenarios(Element[] list, Closure clo) { @@ -90,4 +102,41 @@ public class Util { } return occurrence; } + + public static String readFileAsString(String filePath) throws java.io.IOException { + byte[] buffer = new byte[(int) new File(filePath).length()]; + BufferedInputStream f = null; + try { + f = new BufferedInputStream(new FileInputStream(filePath)); + f.read(buffer); + } finally { + if (f != null) try { + f.close(); + } catch (IOException ignored) { + } + } + return new String(buffer); + } + + public static String formatDuration(Long duration){ + PeriodFormatter formatter = new PeriodFormatterBuilder() + .appendDays() + .appendSuffix(" day", " days") + .appendSeparator(" and ") + .appendHours() + .appendSuffix(" hour", " hours") + .appendSeparator(" and ") + .appendMinutes() + .appendSuffix(" min", " mins") + .appendSeparator(" and ") + .appendSeconds() + .appendSuffix(" sec", " secs") + .appendSeparator(" and ") + .appendMillis() + .appendSuffix(" ms", " ms") + .toFormatter(); + return formatter.print(new Period(0, duration/1000000)); + + + } } diff --git a/src/main/resources/templates/featureOverview.vm b/src/main/resources/templates/featureOverview.vm index 16bfcbb..636cb9b 100644 --- a/src/main/resources/templates/featureOverview.vm +++ b/src/main/resources/templates/featureOverview.vm @@ -33,6 +33,7 @@ var requiredRevision = 45; .passed{background-color:#C5D88A;} .failed{background-color:#D88A8A;} .skipped{background-color:#2DEAEC;} +.undefined{background-color: #ebcc81;} table.stats-table { color:black; @@ -86,7 +87,7 @@ table.stats-table td {
-
+