-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UnitFormatter for cucumber-jvm #226
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
package cucumber.formatter; | ||
|
||
import cucumber.runtime.CucumberException; | ||
import gherkin.formatter.Formatter; | ||
import gherkin.formatter.Reporter; | ||
import gherkin.formatter.model.*; | ||
import org.w3c.dom.Document; | ||
import org.w3c.dom.Element; | ||
|
||
import javax.xml.parsers.DocumentBuilderFactory; | ||
import javax.xml.parsers.ParserConfigurationException; | ||
import javax.xml.transform.OutputKeys; | ||
import javax.xml.transform.Transformer; | ||
import javax.xml.transform.TransformerException; | ||
import javax.xml.transform.TransformerFactory; | ||
import javax.xml.transform.dom.DOMSource; | ||
import javax.xml.transform.stream.StreamResult; | ||
import java.io.File; | ||
import java.io.InputStream; | ||
import java.io.PrintWriter; | ||
import java.io.StringWriter; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
* @author Uladzimir Mihura | ||
* Date: 2/24/12 | ||
* Time: 4:02 PM | ||
*/ | ||
public class UnitFormatter implements Formatter, Reporter { | ||
private File out; | ||
private Document doc; | ||
private Element rootElement; | ||
private TestCase testCase; | ||
|
||
|
||
public UnitFormatter(File out) { | ||
this.out = out; | ||
try { | ||
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); | ||
rootElement = doc.createElement("testsuite"); | ||
doc.appendChild(rootElement); | ||
} catch (ParserConfigurationException e) { | ||
throw new CucumberException("Error while processing unit report", e); | ||
} | ||
} | ||
|
||
|
||
@Override | ||
public void feature(Feature feature) { | ||
TestCase.feature = feature; | ||
} | ||
|
||
@Override | ||
public void background(Background background) { | ||
testCase = new TestCase(); | ||
} | ||
|
||
@Override | ||
public void scenario(Scenario scenario) { | ||
if (testCase != null) { | ||
testCase.scenario = scenario; | ||
} else { | ||
testCase = new TestCase(scenario); | ||
} | ||
|
||
increaseAttributeValue(rootElement, "tests"); | ||
} | ||
|
||
@Override | ||
public void step(Step step) { | ||
if (testCase != null) testCase.steps.add(step); | ||
} | ||
|
||
|
||
@Override | ||
public void done() { | ||
try { | ||
//set up a transformer | ||
rootElement.setAttribute("failed", String.valueOf(rootElement.getElementsByTagName("failure").getLength())); | ||
TransformerFactory transfac = TransformerFactory.newInstance(); | ||
Transformer trans = transfac.newTransformer(); | ||
trans.setOutputProperty(OutputKeys.INDENT, "yes"); | ||
StreamResult result = new StreamResult(out); | ||
DOMSource source = new DOMSource(doc); | ||
trans.transform(source, result); | ||
} catch (TransformerException e) { | ||
new CucumberException("Error while transforming.", e); | ||
} | ||
} | ||
|
||
|
||
@Override | ||
public void result(Result result) { | ||
testCase.results.add(result); | ||
|
||
if (testCase.scenario != null && testCase.results.size() == testCase.steps.size()) { | ||
rootElement.appendChild(testCase.writeTo(doc)); | ||
testCase = null; | ||
} | ||
} | ||
|
||
private void increaseAttributeValue(Element element, String attribute) { | ||
int value = 0; | ||
if (element.hasAttribute(attribute)) { | ||
value = Integer.parseInt(element.getAttribute(attribute)); | ||
} | ||
element.setAttribute(attribute, String.valueOf(++value)); | ||
} | ||
|
||
@Override | ||
public void scenarioOutline(ScenarioOutline scenarioOutline) { | ||
} | ||
|
||
@Override | ||
public void examples(Examples examples) { | ||
TestCase.examples = examples.getRows().size()-1; | ||
} | ||
|
||
@Override | ||
public void match(Match match) { | ||
} | ||
|
||
@Override | ||
public void embedding(String mimeType, InputStream data) { | ||
} | ||
|
||
@Override | ||
public void write(String text) { | ||
} | ||
|
||
@Override | ||
public void uri(String uri) { | ||
} | ||
|
||
@Override | ||
public void close() { | ||
|
||
} | ||
|
||
@Override | ||
public void eof() { | ||
} | ||
|
||
@Override | ||
public void syntaxError(String state, String event, List<String> legalEvents, String uri, int line) { | ||
} | ||
|
||
private static class TestCase { | ||
private TestCase(Scenario scenario) { | ||
this.scenario = scenario; | ||
} | ||
|
||
private TestCase() { | ||
} | ||
|
||
Scenario scenario; | ||
static Feature feature; | ||
static int examples = 0; | ||
List<Step> steps = new ArrayList<Step>(); | ||
List<Result> results = new ArrayList<Result>(); | ||
|
||
private Element writeTo(Document doc) { | ||
Element tc = doc.createElement("testcase"); | ||
tc.setAttribute("classname", feature.getName()); | ||
tc.setAttribute("name", examples > 0 ? scenario.getName() + "_" + examples-- : scenario.getName()); | ||
long time = 0; | ||
for (Result r : results) { | ||
time += r.getDuration() != null ? r.getDuration() : 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What do you think - should I rename this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this this would be better if you need nanos somewhere else.
I just noticed that my tests running for years :) |
||
} | ||
tc.setAttribute("time", String.valueOf(time)); | ||
|
||
StringBuilder sb = new StringBuilder(); | ||
Result skipped = null, failed = null; | ||
for (int i = 0; i < steps.size(); i++) { | ||
int length = sb.length(); | ||
Step step = steps.get(i); | ||
Result result = results.get(i); | ||
if ("failed".equals(result.getStatus())) failed = result; | ||
if ("undefined".equals(result.getStatus()) || "pending".equals(result.getStatus())) skipped = result; | ||
sb.append(steps.get(i).getKeyword()); | ||
sb.append(steps.get(i).getName()); | ||
for (int j = 0; sb.length() - length + j < 140; j++) sb.append("."); | ||
sb.append(result.getStatus()); | ||
sb.append("\n"); | ||
} | ||
Element child; | ||
if (failed != null) { | ||
sb.append("\nStackTrace:\n"); | ||
StringWriter sw = new StringWriter(); | ||
failed.getError().printStackTrace(new PrintWriter(sw)); | ||
sb.append(sw.toString()); | ||
child = doc.createElement("failure"); | ||
child.setAttribute("message", failed.getErrorMessage()); | ||
child.appendChild(doc.createCDATASection(sb.toString())); | ||
} else if (skipped != null) { | ||
child = doc.createElement("skipped"); | ||
child.appendChild(doc.createCDATASection(sb.toString())); | ||
} else { | ||
child = doc.createElement("system-out"); | ||
child.appendChild(doc.createCDATASection(sb.toString())); | ||
} | ||
tc.appendChild(child); | ||
return tc; | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package cucumber.formatter; | ||
|
||
import cucumber.io.ClasspathResourceLoader; | ||
import cucumber.runtime.Backend; | ||
import cucumber.runtime.Runtime; | ||
import org.custommonkey.xmlunit.Diff; | ||
import org.custommonkey.xmlunit.XMLUnit; | ||
import org.junit.Test; | ||
import org.xml.sax.SAXException; | ||
|
||
import javax.xml.parsers.ParserConfigurationException; | ||
import java.io.*; | ||
import java.util.List; | ||
|
||
import static java.util.Arrays.asList; | ||
import static java.util.Collections.emptyList; | ||
import static junit.framework.Assert.assertTrue; | ||
import static org.mockito.Mockito.mock; | ||
|
||
/** | ||
* @author Uladzimir Mihura | ||
* Date: 2/25/12 | ||
* Time: 8:39 PM | ||
*/ | ||
public class UnitFormatterTest { | ||
|
||
@Test | ||
public void featureSimpleTest() throws Exception { | ||
runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_1.feature")); | ||
compareXML("cucumber/formatter/UnitFormatterTest_1.report.xml", "report.xml"); | ||
} | ||
|
||
@Test | ||
public void featureWithBackgroundTest() throws Exception { | ||
runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_2.feature")); | ||
compareXML("cucumber/formatter/UnitFormatterTest_2.report.xml", "report.xml"); | ||
} | ||
|
||
@Test | ||
public void featureWithOutlineTest() throws Exception { | ||
runFeaturesWithFormatter(asList("cucumber/formatter/UnitFormatterTest_3.feature")); | ||
compareXML("cucumber/formatter/UnitFormatterTest_3.report.xml", "report.xml"); | ||
} | ||
|
||
private void runFeaturesWithFormatter(final List<String> featurePaths) throws IOException { | ||
File report = new File("report.xml"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
// report.deleteOnExit(); | ||
final UnitFormatter f = new UnitFormatter(report); | ||
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | ||
final ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader(classLoader); | ||
final List<String> gluePaths = emptyList(); | ||
final cucumber.runtime.Runtime runtime = new Runtime(resourceLoader, gluePaths, classLoader, asList(mock(Backend.class)), false); | ||
runtime.run(featurePaths, emptyList(), f, f); | ||
f.done(); | ||
f.close(); | ||
} | ||
|
||
private void compareXML(String expected, String received) throws IOException, ParserConfigurationException, SAXException { | ||
XMLUnit.setIgnoreWhitespace(true); | ||
Diff diff = new Diff(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(expected)), new FileReader(received)); | ||
assertTrue("XML files are similar " + diff, diff.identical()); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Feature: Feature_1 | ||
Some description | ||
|
||
Scenario: Scenario_1 | ||
Given step_1 | ||
When step_2 | ||
Then step_3 | ||
|
||
Scenario: Scenario_2 | ||
Given step_1 | ||
When step_2 | ||
Then step_3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great if you could configure your IDE to not do star imports - see the README for coding standards
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I've noticed it after submitting pull request. Do I need another commit?