Skip to content
This repository

UnitFormatter for cucumber-jvm #226

Merged
merged 3 commits into from over 2 years ago

3 participants

Uladzimir Mihura Jan Stamer Aslak Hellesøy
Uladzimir Mihura

This unit formatter can be used while running cucumber via cli.

Also, with this it is become possible to generate html and unit reports and the same time. Previously we have to decide - html via cli or unit via cucumber-junit.

Jan Stamer

Hi,

how can you use that to create both standard unit test reports and html reports? That's exactly what I am looking for!

Thanx

Uladzimir Mihura

Yeah,

Just run in the following way:

-f pretty -f unit -o reports/unit.xml -f html -o reports/

I'm doing this for jenkins.

-vova

Jan Stamer

I am a bit confused that you don't use the cucumber HtmlFormatter. So your Html report contains the unit tests but not the feature information am I right?

Uladzimir Mihura

nope, to create multiply reports you just need to type all required formatters. Please, note -f html later in the line.

-vova

Aslak Hellesøy

Looks great. I'll probably merge this in next week.

Aslak Hellesøy aslakhellesoy commented on the diff
core/src/main/java/cucumber/formatter/HTMLFormatter.java
((6 lines not shown))
12   -import gherkin.formatter.model.Feature;
13   -import gherkin.formatter.model.Match;
14   -import gherkin.formatter.model.Result;
15   -import gherkin.formatter.model.Scenario;
16   -import gherkin.formatter.model.ScenarioOutline;
17   -import gherkin.formatter.model.Step;
18   -
19   -import java.io.File;
20   -import java.io.FileNotFoundException;
21   -import java.io.FileOutputStream;
22   -import java.io.IOException;
23   -import java.io.InputStream;
24   -import java.io.OutputStream;
25   -import java.io.OutputStreamWriter;
26   -import java.io.UnsupportedEncodingException;
  10 +import gherkin.formatter.model.*;
2
Aslak Hellesøy Owner

It would be great if you could configure your IDE to not do star imports - see the README for coding standards

Uladzimir Mihura
trnl added a note

Sure, I've noticed it after submitting pull request. Do I need another commit?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Aslak Hellesøy aslakhellesoy commented on the diff
core/src/main/java/cucumber/formatter/UnitFormatter.java
((154 lines not shown))
  154 + private TestCase() {
  155 + }
  156 +
  157 + Scenario scenario;
  158 + static Feature feature;
  159 + static int examples = 0;
  160 + List<Step> steps = new ArrayList<Step>();
  161 + List<Result> results = new ArrayList<Result>();
  162 +
  163 + private Element writeTo(Document doc) {
  164 + Element tc = doc.createElement("testcase");
  165 + tc.setAttribute("classname", feature.getName());
  166 + tc.setAttribute("name", examples > 0 ? scenario.getName() + "_" + examples-- : scenario.getName());
  167 + long time = 0;
  168 + for (Result r : results) {
  169 + time += r.getDuration() != null ? r.getDuration() : 0;
2
Aslak Hellesøy Owner

Result.getDuration() is currently in nanoseconds. I'm not sure what the JUnit report contract is, but I assume millis.

What do you think - should I rename this to getDurationNanos() ? That would make it more obvious that people who want millis (you?) have to divide by 1000000.

Uladzimir Mihura
trnl added a note

I think this this would be better if you need nanos somewhere else.

public long getDuration() {
    this. getDurationNanos()/1000000
}

I just noticed that my tests running for years :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Aslak Hellesøy aslakhellesoy commented on the diff
...c/test/java/cucumber/formatter/UnitFormatterTest.java
((31 lines not shown))
  31 + }
  32 +
  33 + @Test
  34 + public void featureWithBackgroundTest() throws Exception {
  35 + runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_2.feature"));
  36 + compareXML("cucumber/formatter/UnitFormatterTest_2.report.xml", "report.xml");
  37 + }
  38 +
  39 + @Test
  40 + public void featureWithOutlineTest() throws Exception {
  41 + runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_3.feature"));
  42 + compareXML("cucumber/formatter/UnitFormatterTest_3.report.xml", "report.xml");
  43 + }
  44 +
  45 + private void runFeaturesWithFormatter(final List<String> featurePaths) throws IOException {
  46 + File report = new File("report.xml");
1
Aslak Hellesøy Owner

I think File.createTempFile would be better here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Aslak Hellesøy aslakhellesoy commented on the diff
core/src/test/resources/cucumber/formatter/test.xsd
... ... @@ -0,0 +1,91 @@
1
Aslak Hellesøy Owner

Can you add a comment pointing to where this file comes from? I'm assuming Ant's source code, but not sure...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Uladzimir Mihura trnl commented on the diff
core/src/test/resources/cucumber/formatter/test.xsd
((76 lines not shown))
  76 + <xs:element name="testsuites">
  77 + <xs:complexType>
  78 + <xs:sequence>
  79 + <xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded"/>
  80 + </xs:sequence>
  81 + <xs:attribute name="name" type="xs:string" use="optional"/>
  82 + <xs:attribute name="time" type="xs:string" use="optional"/>
  83 + <xs:attribute name="tests" type="xs:string" use="optional"/>
  84 + <xs:attribute name="failures" type="xs:string" use="optional"/>
  85 + <xs:attribute name="disabled" type="xs:string" use="optional"/>
  86 + <xs:attribute name="errors" type="xs:string" use="optional"/>
  87 + </xs:complexType>
  88 + </xs:element>
  89 +
  90 +
  91 +</xs:schema>
4
Uladzimir Mihura
trnl added a note

This file is not used. Should be removed.

But we can use it while testing. Haven't done this yet. Do you think it will be helpful?

Aslak Hellesøy Owner

I definitely think it would be helpful for testing - as long as this is the official schema. Is it? Did you write it or does it come from JUnit or Ant?

Aslak Hellesøy Owner

The latter one looks more thorough, but it's LGPL and we can't have LGPL code in cucumber-jvm.

I'm asking the author (whom I happen to know) to waive the LGPL for us. Will update here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Aslak Hellesøy aslakhellesoy merged commit 6bf58e6 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
6 .gitignore
@@ -18,3 +18,9 @@ report.js
18 18 chromedriver.log
19 19 .scala_dependencies
20 20 nexus.properties
  21 +
  22 +# OS generated files
  23 +.DS_Store*
  24 +ehthumbs.db
  25 +Icon?
  26 +Thumbs.db
6 core/pom.xml
@@ -46,6 +46,12 @@
46 46 <scope>test</scope>
47 47 </dependency>
48 48 <dependency>
  49 + <groupId>xmlunit</groupId>
  50 + <artifactId>xmlunit</artifactId>
  51 + <version>1.3</version>
  52 + <scope>test</scope>
  53 + </dependency>
  54 + <dependency>
49 55 <groupId>org.mockito</groupId>
50 56 <artifactId>mockito-all</artifactId>
51 57 <scope>test</scope>
11 core/src/main/java/cucumber/formatter/FormatterFactory.java
@@ -7,7 +7,6 @@
7 7 import gherkin.formatter.PrettyFormatter;
8 8
9 9 import java.io.File;
10   -import java.io.FileWriter;
11 10 import java.util.HashMap;
12 11 import java.util.Map;
13 12
@@ -21,6 +20,7 @@
21 20 put("json", JSONFormatter.class.getName());
22 21 put("json-pretty", JSONPrettyFormatter.class.getName());
23 22 put("pretty", PrettyFormatter.class.getName());
  23 + put("unit", UnitFormatter.class.getName());
24 24 }};
25 25
26 26 public FormatterFactory(ClassLoader classLoader) {
@@ -37,13 +37,10 @@ private Formatter createFormatterFromClassName(String className, Object out) {
37 37 Class ctorArgClass = Appendable.class;
38 38 if (out instanceof File) {
39 39 File file = (File) out;
40   - if (file.isDirectory()) {
41   - out = file;
42   - ctorArgClass = File.class;
43   - } else {
44   - out = new FileWriter(file);
45   - }
  40 + out = file;
  41 + ctorArgClass = File.class;
46 42 }
  43 +
47 44 Class<Formatter> formatterClass = getFormatterClass(className);
48 45 // TODO: Remove these if statements. We should fix PrettyFormatter and ProgressFormatter to only take a single Appendable arg.
49 46 // Whether or not to use Monochrome is tricky. Maybe always enforce another 2nd argument for that
21 core/src/main/java/cucumber/formatter/HTMLFormatter.java
@@ -7,23 +7,9 @@
7 7 import gherkin.formatter.Mappable;
8 8 import gherkin.formatter.NiceAppendable;
9 9 import gherkin.formatter.Reporter;
10   -import gherkin.formatter.model.Background;
11   -import gherkin.formatter.model.Examples;
12   -import gherkin.formatter.model.Feature;
13   -import gherkin.formatter.model.Match;
14   -import gherkin.formatter.model.Result;
15   -import gherkin.formatter.model.Scenario;
16   -import gherkin.formatter.model.ScenarioOutline;
17   -import gherkin.formatter.model.Step;
18   -
19   -import java.io.File;
20   -import java.io.FileNotFoundException;
21   -import java.io.FileOutputStream;
22   -import java.io.IOException;
23   -import java.io.InputStream;
24   -import java.io.OutputStream;
25   -import java.io.OutputStreamWriter;
26   -import java.io.UnsupportedEncodingException;
  10 +import gherkin.formatter.model.*;
  11 +
  12 +import java.io.*;
27 13 import java.util.HashMap;
28 14 import java.util.List;
29 15 import java.util.Map;
@@ -181,6 +167,7 @@ private NiceAppendable jsOut() {
181 167 }
182 168
183 169 private OutputStream reportFileOutputStream(String fileName) {
  170 + htmlReportDir.mkdirs();
184 171 File file = new File(htmlReportDir, fileName);
185 172 try {
186 173 return new FileOutputStream(file);
208 core/src/main/java/cucumber/formatter/UnitFormatter.java
... ... @@ -0,0 +1,208 @@
  1 +package cucumber.formatter;
  2 +
  3 +import cucumber.runtime.CucumberException;
  4 +import gherkin.formatter.Formatter;
  5 +import gherkin.formatter.Reporter;
  6 +import gherkin.formatter.model.*;
  7 +import org.w3c.dom.Document;
  8 +import org.w3c.dom.Element;
  9 +
  10 +import javax.xml.parsers.DocumentBuilderFactory;
  11 +import javax.xml.parsers.ParserConfigurationException;
  12 +import javax.xml.transform.OutputKeys;
  13 +import javax.xml.transform.Transformer;
  14 +import javax.xml.transform.TransformerException;
  15 +import javax.xml.transform.TransformerFactory;
  16 +import javax.xml.transform.dom.DOMSource;
  17 +import javax.xml.transform.stream.StreamResult;
  18 +import java.io.File;
  19 +import java.io.InputStream;
  20 +import java.io.PrintWriter;
  21 +import java.io.StringWriter;
  22 +import java.util.ArrayList;
  23 +import java.util.List;
  24 +
  25 +/**
  26 + * @author Uladzimir Mihura
  27 + * Date: 2/24/12
  28 + * Time: 4:02 PM
  29 + */
  30 +public class UnitFormatter implements Formatter, Reporter {
  31 + private File out;
  32 + private Document doc;
  33 + private Element rootElement;
  34 + private TestCase testCase;
  35 +
  36 +
  37 + public UnitFormatter(File out) {
  38 + this.out = out;
  39 + try {
  40 + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
  41 + rootElement = doc.createElement("testsuite");
  42 + doc.appendChild(rootElement);
  43 + } catch (ParserConfigurationException e) {
  44 + throw new CucumberException("Error while processing unit report", e);
  45 + }
  46 + }
  47 +
  48 +
  49 + @Override
  50 + public void feature(Feature feature) {
  51 + TestCase.feature = feature;
  52 + }
  53 +
  54 + @Override
  55 + public void background(Background background) {
  56 + testCase = new TestCase();
  57 + }
  58 +
  59 + @Override
  60 + public void scenario(Scenario scenario) {
  61 + if (testCase != null) {
  62 + testCase.scenario = scenario;
  63 + } else {
  64 + testCase = new TestCase(scenario);
  65 + }
  66 +
  67 + increaseAttributeValue(rootElement, "tests");
  68 + }
  69 +
  70 + @Override
  71 + public void step(Step step) {
  72 + if (testCase != null) testCase.steps.add(step);
  73 + }
  74 +
  75 +
  76 + @Override
  77 + public void done() {
  78 + try {
  79 + //set up a transformer
  80 + rootElement.setAttribute("failed", String.valueOf(rootElement.getElementsByTagName("failure").getLength()));
  81 + TransformerFactory transfac = TransformerFactory.newInstance();
  82 + Transformer trans = transfac.newTransformer();
  83 + trans.setOutputProperty(OutputKeys.INDENT, "yes");
  84 + StreamResult result = new StreamResult(out);
  85 + DOMSource source = new DOMSource(doc);
  86 + trans.transform(source, result);
  87 + } catch (TransformerException e) {
  88 + new CucumberException("Error while transforming.", e);
  89 + }
  90 + }
  91 +
  92 +
  93 + @Override
  94 + public void result(Result result) {
  95 + testCase.results.add(result);
  96 +
  97 + if (testCase.scenario != null && testCase.results.size() == testCase.steps.size()) {
  98 + rootElement.appendChild(testCase.writeTo(doc));
  99 + testCase = null;
  100 + }
  101 + }
  102 +
  103 + private void increaseAttributeValue(Element element, String attribute) {
  104 + int value = 0;
  105 + if (element.hasAttribute(attribute)) {
  106 + value = Integer.parseInt(element.getAttribute(attribute));
  107 + }
  108 + element.setAttribute(attribute, String.valueOf(++value));
  109 + }
  110 +
  111 + @Override
  112 + public void scenarioOutline(ScenarioOutline scenarioOutline) {
  113 + }
  114 +
  115 + @Override
  116 + public void examples(Examples examples) {
  117 + TestCase.examples = examples.getRows().size()-1;
  118 + }
  119 +
  120 + @Override
  121 + public void match(Match match) {
  122 + }
  123 +
  124 + @Override
  125 + public void embedding(String mimeType, InputStream data) {
  126 + }
  127 +
  128 + @Override
  129 + public void write(String text) {
  130 + }
  131 +
  132 + @Override
  133 + public void uri(String uri) {
  134 + }
  135 +
  136 + @Override
  137 + public void close() {
  138 +
  139 + }
  140 +
  141 + @Override
  142 + public void eof() {
  143 + }
  144 +
  145 + @Override
  146 + public void syntaxError(String state, String event, List<String> legalEvents, String uri, int line) {
  147 + }
  148 +
  149 + private static class TestCase {
  150 + private TestCase(Scenario scenario) {
  151 + this.scenario = scenario;
  152 + }
  153 +
  154 + private TestCase() {
  155 + }
  156 +
  157 + Scenario scenario;
  158 + static Feature feature;
  159 + static int examples = 0;
  160 + List<Step> steps = new ArrayList<Step>();
  161 + List<Result> results = new ArrayList<Result>();
  162 +
  163 + private Element writeTo(Document doc) {
  164 + Element tc = doc.createElement("testcase");
  165 + tc.setAttribute("classname", feature.getName());
  166 + tc.setAttribute("name", examples > 0 ? scenario.getName() + "_" + examples-- : scenario.getName());
  167 + long time = 0;
  168 + for (Result r : results) {
  169 + time += r.getDuration() != null ? r.getDuration() : 0;
  170 + }
  171 + tc.setAttribute("time", String.valueOf(time));
  172 +
  173 + StringBuilder sb = new StringBuilder();
  174 + Result skipped = null, failed = null;
  175 + for (int i = 0; i < steps.size(); i++) {
  176 + int length = sb.length();
  177 + Step step = steps.get(i);
  178 + Result result = results.get(i);
  179 + if ("failed".equals(result.getStatus())) failed = result;
  180 + if ("undefined".equals(result.getStatus()) || "pending".equals(result.getStatus())) skipped = result;
  181 + sb.append(steps.get(i).getKeyword());
  182 + sb.append(steps.get(i).getName());
  183 + for (int j = 0; sb.length() - length + j < 140; j++) sb.append(".");
  184 + sb.append(result.getStatus());
  185 + sb.append("\n");
  186 + }
  187 + Element child;
  188 + if (failed != null) {
  189 + sb.append("\nStackTrace:\n");
  190 + StringWriter sw = new StringWriter();
  191 + failed.getError().printStackTrace(new PrintWriter(sw));
  192 + sb.append(sw.toString());
  193 + child = doc.createElement("failure");
  194 + child.setAttribute("message", failed.getErrorMessage());
  195 + child.appendChild(doc.createCDATASection(sb.toString()));
  196 + } else if (skipped != null) {
  197 + child = doc.createElement("skipped");
  198 + child.appendChild(doc.createCDATASection(sb.toString()));
  199 + } else {
  200 + child = doc.createElement("system-out");
  201 + child.appendChild(doc.createCDATASection(sb.toString()));
  202 + }
  203 + tc.appendChild(child);
  204 + return tc;
  205 + }
  206 + }
  207 +
  208 +}
5 core/src/test/java/cucumber/formatter/FormatterFactoryTest.java
@@ -43,6 +43,11 @@ public void shouldInstantiateHtmlFormatter() {
43 43 }
44 44
45 45 @Test
  46 + public void shouldInstantiateUnitFormatter() {
  47 + assertThat(formatterFactory.createFormatter("unit", new File(System.getProperty("user.dir")+"report.xml")), is(UnitFormatter.class));
  48 + }
  49 +
  50 + @Test
46 51 public void shouldInstantiateCustomFormatterFromClassNameWithAppender() {
47 52 StringWriter writer = new StringWriter();
48 53 Formatter formatter = formatterFactory.createFormatter(TestFormatter.class.getName(), writer);
64 core/src/test/java/cucumber/formatter/UnitFormatterTest.java
... ... @@ -0,0 +1,64 @@
  1 +package cucumber.formatter;
  2 +
  3 +import cucumber.io.ClasspathResourceLoader;
  4 +import cucumber.runtime.Backend;
  5 +import cucumber.runtime.Runtime;
  6 +import org.custommonkey.xmlunit.Diff;
  7 +import org.custommonkey.xmlunit.XMLUnit;
  8 +import org.junit.Test;
  9 +import org.xml.sax.SAXException;
  10 +
  11 +import javax.xml.parsers.ParserConfigurationException;
  12 +import java.io.*;
  13 +import java.util.List;
  14 +
  15 +import static java.util.Arrays.asList;
  16 +import static java.util.Collections.emptyList;
  17 +import static junit.framework.Assert.assertTrue;
  18 +import static org.mockito.Mockito.mock;
  19 +
  20 +/**
  21 + * @author Uladzimir Mihura
  22 + * Date: 2/25/12
  23 + * Time: 8:39 PM
  24 + */
  25 +public class UnitFormatterTest {
  26 +
  27 + @Test
  28 + public void featureSimpleTest() throws Exception {
  29 + runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_1.feature"));
  30 + compareXML("cucumber/formatter/UnitFormatterTest_1.report.xml", "report.xml");
  31 + }
  32 +
  33 + @Test
  34 + public void featureWithBackgroundTest() throws Exception {
  35 + runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_2.feature"));
  36 + compareXML("cucumber/formatter/UnitFormatterTest_2.report.xml", "report.xml");
  37 + }
  38 +
  39 + @Test
  40 + public void featureWithOutlineTest() throws Exception {
  41 + runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_3.feature"));
  42 + compareXML("cucumber/formatter/UnitFormatterTest_3.report.xml", "report.xml");
  43 + }
  44 +
  45 + private void runFeaturesWithFormatter(final List<String> featurePaths) throws IOException {
  46 + File report = new File("report.xml");
  47 +// report.deleteOnExit();
  48 + final UnitFormatter f = new UnitFormatter(report);
  49 + final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  50 + final ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader(classLoader);
  51 + final List<String> gluePaths = emptyList();
  52 + final cucumber.runtime.Runtime runtime = new Runtime(resourceLoader, gluePaths, classLoader, asList(mock(Backend.class)), false);
  53 + runtime.run(featurePaths, emptyList(), f, f);
  54 + f.done();
  55 + f.close();
  56 + }
  57 +
  58 + private void compareXML(String expected, String received) throws IOException, ParserConfigurationException, SAXException {
  59 + XMLUnit.setIgnoreWhitespace(true);
  60 + Diff diff = new Diff(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(expected)), new FileReader(received));
  61 + assertTrue("XML files are similar " + diff, diff.identical());
  62 + }
  63 +
  64 +}
12 core/src/test/resources/cucumber/formatter/UnitFormatterTest_1.feature
... ... @@ -0,0 +1,12 @@
  1 +Feature: Feature_1
  2 + Some description
  3 +
  4 + Scenario: Scenario_1
  5 + Given step_1
  6 + When step_2
  7 + Then step_3
  8 +
  9 + Scenario: Scenario_2
  10 + Given step_1
  11 + When step_2
  12 + Then step_3
15 core/src/test/resources/cucumber/formatter/UnitFormatterTest_1.report.xml
... ... @@ -0,0 +1,15 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<testsuite tests="2" failed="0">
  3 + <testcase classname="Feature_1" name="Scenario_1" time="0">
  4 + <skipped><![CDATA[Given step_1................................................................undefined
  5 +When step_2.................................................................undefined
  6 +Then step_3.................................................................undefined
  7 +]]></skipped>
  8 + </testcase>
  9 + <testcase classname="Feature_1" name="Scenario_2" time="0">
  10 + <skipped><![CDATA[Given step_1................................................................undefined
  11 +When step_2.................................................................undefined
  12 +Then step_3.................................................................undefined
  13 +]]></skipped>
  14 + </testcase>
  15 +</testsuite>
17 core/src/test/resources/cucumber/formatter/UnitFormatterTest_2.feature
... ... @@ -0,0 +1,17 @@
  1 +Feature: Feature_2
  2 +
  3 + Background:
  4 + Given bg_1
  5 + When bg_2
  6 + Then bg_3
  7 +
  8 + Scenario: Scenario_1
  9 + Given step_1
  10 + When step_2
  11 + Then step_3
  12 +
  13 + Scenario: Scenario_2
  14 + Given step_1
  15 + When step_2
  16 + Then step_3
  17 +
21 core/src/test/resources/cucumber/formatter/UnitFormatterTest_2.report.xml
... ... @@ -0,0 +1,21 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<testsuite tests="2" failed="0">
  3 + <testcase classname="Feature_2" name="Scenario_1" time="0">
  4 + <skipped><![CDATA[Given bg_1.................................................................undefined
  5 +When bg_2..................................................................undefined
  6 +Then bg_3..................................................................undefined
  7 +Given step_1................................................................undefined
  8 +When step_2.................................................................undefined
  9 +Then step_3.................................................................undefined
  10 +]]></skipped>
  11 + </testcase>
  12 + <testcase classname="Feature_2" name="Scenario_2" time="0">
  13 + <skipped><![CDATA[Given bg_1.................................................................undefined
  14 +When bg_2..................................................................undefined
  15 +Then bg_3..................................................................undefined
  16 +Given step_1................................................................undefined
  17 +When step_2.................................................................undefined
  18 +Then step_3.................................................................undefined
  19 +]]></skipped>
  20 + </testcase>
  21 +</testsuite>
27 core/src/test/resources/cucumber/formatter/UnitFormatterTest_3.feature
... ... @@ -0,0 +1,27 @@
  1 +Feature: Feature_3
  2 +
  3 + Background:
  4 + Given bg_1
  5 + When bg_2
  6 + Then bg_3
  7 +
  8 + Scenario: Scenario_1
  9 + Given step_1
  10 + When step_2
  11 + Then step_3
  12 +
  13 + Scenario Outline: ScenarioOutline_1
  14 + Given so_1 <a>
  15 + When so_2 <c> cucumbers
  16 + Then <b> so_3
  17 +
  18 + Examples:
  19 + | a | b | c |
  20 + | 12 | 5 | 7 |
  21 + | 20 | 5 | 15 |
  22 +
  23 + Scenario: Scenario_2
  24 + Given a
  25 + Then b
  26 + When c
  27 +
39 core/src/test/resources/cucumber/formatter/UnitFormatterTest_3.report.xml
... ... @@ -0,0 +1,39 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<testsuite failed="0" tests="4">
  3 + <testcase classname="Feature_3" name="Scenario_1" time="0">
  4 + <skipped><![CDATA[Given bg_1.................................................................undefined
  5 +When bg_2..................................................................undefined
  6 +Then bg_3..................................................................undefined
  7 +Given step_1................................................................undefined
  8 +When step_2.................................................................undefined
  9 +Then step_3.................................................................undefined
  10 +]]></skipped>
  11 + </testcase>
  12 + <testcase classname="Feature_3" name="ScenarioOutline_1_2" time="0">
  13 + <skipped><![CDATA[Given bg_1.................................................................undefined
  14 +When bg_2..................................................................undefined
  15 +Then bg_3..................................................................undefined
  16 +Given so_1 12................................................................undefined
  17 +When so_2 7 cucumbers............................................................undefined
  18 +Then 5 so_3.................................................................undefined
  19 +]]></skipped>
  20 + </testcase>
  21 + <testcase classname="Feature_3" name="ScenarioOutline_1_1" time="0">
  22 + <skipped><![CDATA[Given bg_1.................................................................undefined
  23 +When bg_2..................................................................undefined
  24 +Then bg_3..................................................................undefined
  25 +Given so_1 20................................................................undefined
  26 +When so_2 15 cucumbers...........................................................undefined
  27 +Then 5 so_3.................................................................undefined
  28 +]]></skipped>
  29 + </testcase>
  30 + <testcase classname="Feature_3" name="Scenario_2" time="0">
  31 + <skipped><![CDATA[Given bg_1.................................................................undefined
  32 +When bg_2..................................................................undefined
  33 +Then bg_3..................................................................undefined
  34 +Given a...................................................................undefined
  35 +Then b...................................................................undefined
  36 +When c...................................................................undefined
  37 +]]></skipped>
  38 + </testcase>
  39 +</testsuite>
91 core/src/test/resources/cucumber/formatter/test.xsd
... ... @@ -0,0 +1,91 @@
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  3 +
  4 + <xs:element name="failure">
  5 + <xs:complexType mixed="true">
  6 + <xs:attribute name="type" type="xs:string" use="optional"/>
  7 + <xs:attribute name="message" type="xs:string" use="optional"/>
  8 + </xs:complexType>
  9 + </xs:element>
  10 +
  11 + <xs:element name="error">
  12 + <xs:complexType mixed="true">
  13 + <xs:attribute name="type" type="xs:string" use="optional"/>
  14 + <xs:attribute name="message" type="xs:string" use="optional"/>
  15 + </xs:complexType>
  16 + </xs:element>
  17 +
  18 + <xs:element name="properties">
  19 + <xs:complexType>
  20 + <xs:sequence>
  21 + <xs:element ref="property" maxOccurs="unbounded"/>
  22 + </xs:sequence>
  23 + </xs:complexType>
  24 + </xs:element>
  25 +
  26 + <xs:element name="property">
  27 + <xs:complexType>
  28 + <xs:attribute name="name" type="xs:string" use="required"/>
  29 + <xs:attribute name="value" type="xs:string" use="required"/>
  30 + </xs:complexType>
  31 + </xs:element>
  32 +
  33 + <xs:element name="skipped" type="xs:string"/>
  34 + <xs:element name="system-err" type="xs:string"/>
  35 + <xs:element name="system-out" type="xs:string"/>
  36 +
  37 + <xs:element name="testcase">
  38 + <xs:complexType>
  39 + <xs:sequence>
  40 + <xs:element ref="skipped" minOccurs="0" maxOccurs="1"/>
  41 + <xs:element ref="error" minOccurs="0" maxOccurs="unbounded"/>
  42 + <xs:element ref="failure" minOccurs="0" maxOccurs="unbounded"/>
  43 + <xs:element ref="system-out" minOccurs="0" maxOccurs="unbounded"/>
  44 + <xs:element ref="system-err" minOccurs="0" maxOccurs="unbounded"/>
  45 + </xs:sequence>
  46 + <xs:attribute name="name" type="xs:string" use="required"/>
  47 + <xs:attribute name="assertions" type="xs:string" use="optional"/>
  48 + <xs:attribute name="time" type="xs:string" use="optional"/>
  49 + <xs:attribute name="classname" type="xs:string" use="optional"/>
  50 + <xs:attribute name="status" type="xs:string" use="optional"/>
  51 + </xs:complexType>
  52 + </xs:element>
  53 +
  54 + <xs:element name="testsuite">
  55 + <xs:complexType>
  56 + <xs:sequence>
  57 + <xs:element ref="properties" minOccurs="0" maxOccurs="1"/>
  58 + <xs:element ref="testcase" minOccurs="0" maxOccurs="unbounded"/>
  59 + <xs:element ref="system-out" minOccurs="0" maxOccurs="1"/>
  60 + <xs:element ref="system-err" minOccurs="0" maxOccurs="1"/>
  61 + </xs:sequence>
  62 + <xs:attribute name="name" type="xs:string" use="required"/>
  63 + <xs:attribute name="tests" type="xs:string" use="required"/>
  64 + <xs:attribute name="failures" type="xs:string" use="optional"/>
  65 + <xs:attribute name="errors" type="xs:string" use="optional"/>
  66 + <xs:attribute name="time" type="xs:string" use="optional"/>
  67 + <xs:attribute name="disabled" type="xs:string" use="optional"/>
  68 + <xs:attribute name="skipped" type="xs:string" use="optional"/>
  69 + <xs:attribute name="timestamp" type="xs:string" use="optional"/>
  70 + <xs:attribute name="hostname" type="xs:string" use="optional"/>
  71 + <xs:attribute name="id" type="xs:string" use="optional"/>
  72 + <xs:attribute name="package" type="xs:string" use="optional"/>
  73 + </xs:complexType>
  74 + </xs:element>
  75 +
  76 + <xs:element name="testsuites">
  77 + <xs:complexType>
  78 + <xs:sequence>
  79 + <xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded"/>
  80 + </xs:sequence>
  81 + <xs:attribute name="name" type="xs:string" use="optional"/>
  82 + <xs:attribute name="time" type="xs:string" use="optional"/>
  83 + <xs:attribute name="tests" type="xs:string" use="optional"/>
  84 + <xs:attribute name="failures" type="xs:string" use="optional"/>
  85 + <xs:attribute name="disabled" type="xs:string" use="optional"/>
  86 + <xs:attribute name="errors" type="xs:string" use="optional"/>
  87 + </xs:complexType>
  88 + </xs:element>
  89 +
  90 +
  91 +</xs:schema>
1  core/src/test/resources/cucumber/test/a.feature
... ... @@ -1,3 +1,4 @@
1 1 Feature: fa
2 2 Scenario: sa
3 3 Given ga
  4 +

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.