Create tester-junit reporter for Nette Tester tool

This commit is contained in:
Jozef Izso
2026-01-01 18:29:37 +01:00
parent 68967725f7
commit 63870298f5
13 changed files with 1339 additions and 1 deletions

View File

@@ -0,0 +1,20 @@
![Tests passed successfully](https://img.shields.io/badge/tests-4%20passed-success)
<details><summary>Expand for details</summary>
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/nette-tester/BootstrapFormRenderer-report.xml](#user-content-r0)|4 ✅|||300ms|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/nette-tester/BootstrapFormRenderer-report.xml</a>
**4** tests were completed in **300ms** with **4** passed, **0** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[BootstrapFormRenderer-report.xml](#user-content-r0s0)|4 ✅|||300ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">BootstrapFormRenderer-report.xml</a>
```
KdybyTests/BootstrapFormRenderer
✅ BootstrapRendererTest.phpt::testRenderingBasics
✅ BootstrapRendererTest.phpt::testRenderingIndividual
✅ BootstrapRendererTest.phpt::testRenderingComponents
✅ BootstrapRendererTest.phpt::testMultipleFormsInTemplate
```
</details>

View File

@@ -0,0 +1,87 @@
![Tests failed](https://img.shields.io/badge/tests-61%20passed%2C%201%20failed%2C%203%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/nette-tester/tester-v1.7-report.xml](#user-content-r0)|61 ✅|1 ❌|3 ⚪|2s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/nette-tester/tester-v1.7-report.xml</a>
**65** tests were completed in **2s** with **61** passed, **1** failed and **3** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[tester-v1.7-report.xml](#user-content-r0s0)|61 ✅|1 ❌|3 ⚪|2s|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">tester-v1.7-report.xml</a>
```
tests/Framework
⚪ Dumper.toPhp.php7.phpt
✅ Assert.contains.phpt
✅ Assert.count.phpt
✅ Assert.equal.phpt
✅ Assert.equal.recursive.phpt::testSimple
✅ Assert.equal.recursive.phpt::testMultiple
✅ Assert.equal.recursive.phpt::testDeep
✅ Assert.equal.recursive.phpt::testCross
✅ Assert.equal.recursive.phpt::testThirdParty
✅ Assert.error.phpt
✅ Assert.exception.phpt
✅ Assert.false.phpt
✅ Assert.match.phpt
✅ Assert.match.regexp.phpt
✅ Assert.nan.phpt
✅ Assert.noError.phpt
✅ Assert.same.phpt
✅ Assert.null.phpt
✅ Assert.true.phpt
✅ Assert.truthy.phpt
✅ DataProvider.load.phpt
✅ Assert.type.phpt
✅ DataProvider.parseAnnotation.phpt
✅ DataProvider.testQuery.phpt
✅ DomQuery.css2Xpath.phpt
✅ DomQuery.fromHtml.phpt
✅ DomQuery.fromXml.phpt
✅ Dumper.dumpException.phpt
✅ Dumper.color.phpt
✅ Dumper.toLine.phpt
✅ Dumper.toPhp.recursion.phpt
✅ Dumper.toPhp.phpt
✅ FileMock.phpt
✅ Helpers.escapeArg.phpt
✅ Helpers.parseDocComment.phpt
✅ TestCase.annotationThrows.phpt
✅ TestCase.annotationThrows.setUp.tearDown.phpt
✅ TestCase.annotationThrows.syntax.phpt
✅ TestCase.basic.phpt
✅ TestCase.dataProvider.generator.phpt
✅ TestCase.dataProvider.phpt
✅ TestCase.invalidMethods.phpt
✅ TestCase.invalidProvider.phpt
✅ TestCase.order.error.phpt
✅ TestCase.order.errorMuted.phpt
✅ TestCase.order.phpt
✅ Prevent loop in error handling. The #268 regression. (TestCase.ownErrorHandler.phpt)
tests/CodeCoverage
⚪ Collector.start.phpt
✅ PhpParser.parse.lines.phpt
✅ PhpParser.parse.methods.phpt
✅ CloverXMLGenerator.phpt
✅ PhpParser.parse.edge.phpt
✅ PhpParser.parse.lines-of-code.phpt
✅ PhpParser.parse.namespaces.phpt
tests/Runner
✅ CommandLine.phpt
⚪ HhvmPhpInterpreter.phpt
✅ Runner.find-tests.phpt
✅ Job.phpt
✅ ZendPhpExecutable.phpt
✅ Runner.multiple.phpt
✅ Runner.edge.phpt
✅ Runner.stop-on-fail.phpt
❌ Runner.multiple-fails.phpt
Failed: '... in /Users/izso/Developer/nette/tester/tests/Runner/multiple-fails/...' should match
... '..., unexpected end of file in %a%testcase-syntax-error.phptx on line ...'
diff '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.expected' '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.actual'
in tests/Runner/Runner.multiple-fails.phpt(78) Tester\Assert::match()
✅ Runner.annotations.phpt
tests/RunnerOutput
✅ JUnitPrinter.phpt
```

View File

@@ -0,0 +1,20 @@
![Tests passed successfully](https://img.shields.io/badge/tests-4%20passed-success)
<details><summary>Expand for details</summary>
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/nette-tester/BootstrapFormRenderer-report.xml](#user-content-r0)|4 ✅|||300ms|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/nette-tester/BootstrapFormRenderer-report.xml</a>
**4** tests were completed in **300ms** with **4** passed, **0** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[BootstrapFormRenderer-report.xml](#user-content-r0s0)|4 ✅|||300ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">BootstrapFormRenderer-report.xml</a>
```
KdybyTests/BootstrapFormRenderer
✅ BootstrapRendererTest.phpt::testRenderingBasics
✅ BootstrapRendererTest.phpt::testRenderingIndividual
✅ BootstrapRendererTest.phpt::testRenderingComponents
✅ BootstrapRendererTest.phpt::testMultipleFormsInTemplate
```
</details>

View File

@@ -0,0 +1,87 @@
![Tests failed](https://img.shields.io/badge/tests-61%20passed%2C%201%20failed%2C%203%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/nette-tester/tester-v1.7-report.xml](#user-content-r0)|61 ✅|1 ❌|3 ⚪|2s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/nette-tester/tester-v1.7-report.xml</a>
**65** tests were completed in **2s** with **61** passed, **1** failed and **3** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[tester-v1.7-report.xml](#user-content-r0s0)|61 ✅|1 ❌|3 ⚪|2s|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">tester-v1.7-report.xml</a>
```
tests/Framework
⚪ Dumper.toPhp.php7.phpt
✅ Assert.contains.phpt
✅ Assert.count.phpt
✅ Assert.equal.phpt
✅ Assert.equal.recursive.phpt::testSimple
✅ Assert.equal.recursive.phpt::testMultiple
✅ Assert.equal.recursive.phpt::testDeep
✅ Assert.equal.recursive.phpt::testCross
✅ Assert.equal.recursive.phpt::testThirdParty
✅ Assert.error.phpt
✅ Assert.exception.phpt
✅ Assert.false.phpt
✅ Assert.match.phpt
✅ Assert.match.regexp.phpt
✅ Assert.nan.phpt
✅ Assert.noError.phpt
✅ Assert.same.phpt
✅ Assert.null.phpt
✅ Assert.true.phpt
✅ Assert.truthy.phpt
✅ DataProvider.load.phpt
✅ Assert.type.phpt
✅ DataProvider.parseAnnotation.phpt
✅ DataProvider.testQuery.phpt
✅ DomQuery.css2Xpath.phpt
✅ DomQuery.fromHtml.phpt
✅ DomQuery.fromXml.phpt
✅ Dumper.dumpException.phpt
✅ Dumper.color.phpt
✅ Dumper.toLine.phpt
✅ Dumper.toPhp.recursion.phpt
✅ Dumper.toPhp.phpt
✅ FileMock.phpt
✅ Helpers.escapeArg.phpt
✅ Helpers.parseDocComment.phpt
✅ TestCase.annotationThrows.phpt
✅ TestCase.annotationThrows.setUp.tearDown.phpt
✅ TestCase.annotationThrows.syntax.phpt
✅ TestCase.basic.phpt
✅ TestCase.dataProvider.generator.phpt
✅ TestCase.dataProvider.phpt
✅ TestCase.invalidMethods.phpt
✅ TestCase.invalidProvider.phpt
✅ TestCase.order.error.phpt
✅ TestCase.order.errorMuted.phpt
✅ TestCase.order.phpt
✅ Prevent loop in error handling. The #268 regression. (TestCase.ownErrorHandler.phpt)
tests/CodeCoverage
⚪ Collector.start.phpt
✅ PhpParser.parse.lines.phpt
✅ PhpParser.parse.methods.phpt
✅ CloverXMLGenerator.phpt
✅ PhpParser.parse.edge.phpt
✅ PhpParser.parse.lines-of-code.phpt
✅ PhpParser.parse.namespaces.phpt
tests/Runner
✅ CommandLine.phpt
⚪ HhvmPhpInterpreter.phpt
✅ Runner.find-tests.phpt
✅ Job.phpt
✅ ZendPhpExecutable.phpt
✅ Runner.multiple.phpt
✅ Runner.edge.phpt
✅ Runner.stop-on-fail.phpt
❌ Runner.multiple-fails.phpt
Failed: '... in /Users/izso/Developer/nette/tester/tests/Runner/multiple-fails/...' should match
... '..., unexpected end of file in %a%testcase-syntax-error.phptx on line ...'
diff '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.expected' '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.actual'
in tests/Runner/Runner.multiple-fails.phpt(78) Tester\Assert::match()
✅ Runner.annotations.phpt
tests/RunnerOutput
✅ JUnitPrinter.phpt
```

View File

@@ -0,0 +1,485 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`tester-junit tests parses complex test names from BootstrapFormRenderer-report.xml 1`] = `
TestRunResult {
"path": "fixtures/nette-tester/BootstrapFormRenderer-report.xml",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": "KdybyTests/BootstrapFormRenderer",
"tests": [
TestCaseResult {
"error": undefined,
"name": "BootstrapRendererTest.phpt::testRenderingBasics",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "BootstrapRendererTest.phpt::testRenderingIndividual",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "BootstrapRendererTest.phpt::testRenderingComponents",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "BootstrapRendererTest.phpt::testMultipleFormsInTemplate",
"result": "success",
"time": 0,
},
],
},
],
"name": "BootstrapFormRenderer-report.xml",
"totalTime": 300,
},
],
"totalTime": undefined,
}
`;
exports[`tester-junit tests report from tester-v1.7-report.xml matches snapshot 1`] = `
TestRunResult {
"path": "fixtures/nette-tester/tester-v1.7-report.xml",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": "tests/Framework",
"tests": [
TestCaseResult {
"error": undefined,
"name": "Dumper.toPhp.php7.phpt",
"result": "skipped",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.contains.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.count.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.equal.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.equal.recursive.phpt::testSimple",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.equal.recursive.phpt::testMultiple",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.equal.recursive.phpt::testDeep",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.equal.recursive.phpt::testCross",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.equal.recursive.phpt::testThirdParty",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.error.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.exception.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.false.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.match.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.match.regexp.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.nan.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.noError.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.same.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.null.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.true.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.truthy.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "DataProvider.load.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Assert.type.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "DataProvider.parseAnnotation.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "DataProvider.testQuery.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "DomQuery.css2Xpath.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "DomQuery.fromHtml.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "DomQuery.fromXml.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Dumper.dumpException.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Dumper.color.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Dumper.toLine.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Dumper.toPhp.recursion.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Dumper.toPhp.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "FileMock.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Helpers.escapeArg.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Helpers.parseDocComment.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.annotationThrows.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.annotationThrows.setUp.tearDown.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.annotationThrows.syntax.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.basic.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.dataProvider.generator.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.dataProvider.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.invalidMethods.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.invalidProvider.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.order.error.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.order.errorMuted.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "TestCase.order.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Prevent loop in error handling. The #268 regression. (TestCase.ownErrorHandler.phpt)",
"result": "success",
"time": 0,
},
],
},
TestGroupResult {
"name": "tests/CodeCoverage",
"tests": [
TestCaseResult {
"error": undefined,
"name": "Collector.start.phpt",
"result": "skipped",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "PhpParser.parse.lines.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "PhpParser.parse.methods.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "CloverXMLGenerator.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "PhpParser.parse.edge.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "PhpParser.parse.lines-of-code.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "PhpParser.parse.namespaces.phpt",
"result": "success",
"time": 0,
},
],
},
TestGroupResult {
"name": "tests/Runner",
"tests": [
TestCaseResult {
"error": undefined,
"name": "CommandLine.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "HhvmPhpInterpreter.phpt",
"result": "skipped",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Runner.find-tests.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Job.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "ZendPhpExecutable.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Runner.multiple.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Runner.edge.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Runner.stop-on-fail.phpt",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": {
"details": "Failed: '... in /Users/izso/Developer/nette/tester/tests/Runner/multiple-fails/...' should match
... '..., unexpected end of file in %a%testcase-syntax-error.phptx on line ...'
diff '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.expected' '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.actual'
in tests/Runner/Runner.multiple-fails.phpt(78) Tester\\Assert::match()",
"line": undefined,
"message": "Failed: '... in /Users/izso/Developer/nette/tester/tests/Runner/multiple-fails/...' should match
... '..., unexpected end of file in %a%testcase-syntax-error.phptx on line ...'
diff '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.expected' '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.actual'
in tests/Runner/Runner.multiple-fails.phpt(78) Tester\\Assert::match()",
"path": undefined,
},
"name": "Runner.multiple-fails.phpt",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "Runner.annotations.phpt",
"result": "success",
"time": 0,
},
],
},
TestGroupResult {
"name": "tests/RunnerOutput",
"tests": [
TestCaseResult {
"error": undefined,
"name": "JUnitPrinter.phpt",
"result": "success",
"time": 0,
},
],
},
],
"name": "tester-v1.7-report.xml",
"totalTime": 2100,
},
],
"totalTime": undefined,
}
`;

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite errors="0" skipped="0" tests="4" time="0.3" timestamp="2026-01-01T16:36:10">
<testcase classname="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testRenderingBasics]" name="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testRenderingBasics]"/>
<testcase classname="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testRenderingIndividual]" name="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testRenderingIndividual]"/>
<testcase classname="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testRenderingComponents]" name="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testRenderingComponents]"/>
<testcase classname="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testMultipleFormsInTemplate]" name="Kdyby\BootstrapFormRenderer\BootstrapRenderer. | KdybyTests/BootstrapFormRenderer/BootstrapRendererTest.phpt [method=testMultipleFormsInTemplate]"/>
</testsuite>
</testsuites>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite errors="1" skipped="3" tests="65" time="2.1" timestamp="2026-01-01T16:50:52">
<testcase classname="tests/Framework/Dumper.toPhp.php7.phpt" name="tests/Framework/Dumper.toPhp.php7.phpt">
<skipped/>
</testcase>
<testcase classname="tests/CodeCoverage/Collector.start.phpt" name="tests/CodeCoverage/Collector.start.phpt">
<skipped/>
</testcase>
<testcase classname="tests/CodeCoverage/PhpParser.parse.lines.phpt" name="tests/CodeCoverage/PhpParser.parse.lines.phpt"/>
<testcase classname="tests/CodeCoverage/PhpParser.parse.methods.phpt" name="tests/CodeCoverage/PhpParser.parse.methods.phpt"/>
<testcase classname="tests/CodeCoverage/CloverXMLGenerator.phpt" name="tests/CodeCoverage/CloverXMLGenerator.phpt"/>
<testcase classname="tests/CodeCoverage/PhpParser.parse.edge.phpt" name="tests/CodeCoverage/PhpParser.parse.edge.phpt"/>
<testcase classname="tests/CodeCoverage/PhpParser.parse.lines-of-code.phpt" name="tests/CodeCoverage/PhpParser.parse.lines-of-code.phpt"/>
<testcase classname="tests/CodeCoverage/PhpParser.parse.namespaces.phpt" name="tests/CodeCoverage/PhpParser.parse.namespaces.phpt"/>
<testcase classname="tests/Framework/Assert.contains.phpt" name="tests/Framework/Assert.contains.phpt"/>
<testcase classname="tests/Framework/Assert.count.phpt" name="tests/Framework/Assert.count.phpt"/>
<testcase classname="tests/Framework/Assert.equal.phpt" name="tests/Framework/Assert.equal.phpt"/>
<testcase classname="tests/Framework/Assert.equal.recursive.phpt [method=testSimple]" name="tests/Framework/Assert.equal.recursive.phpt [method=testSimple]"/>
<testcase classname="tests/Framework/Assert.equal.recursive.phpt [method=testMultiple]" name="tests/Framework/Assert.equal.recursive.phpt [method=testMultiple]"/>
<testcase classname="tests/Framework/Assert.equal.recursive.phpt [method=testDeep]" name="tests/Framework/Assert.equal.recursive.phpt [method=testDeep]"/>
<testcase classname="tests/Framework/Assert.equal.recursive.phpt [method=testCross]" name="tests/Framework/Assert.equal.recursive.phpt [method=testCross]"/>
<testcase classname="tests/Framework/Assert.equal.recursive.phpt [method=testThirdParty]" name="tests/Framework/Assert.equal.recursive.phpt [method=testThirdParty]"/>
<testcase classname="tests/Framework/Assert.error.phpt" name="tests/Framework/Assert.error.phpt"/>
<testcase classname="tests/Framework/Assert.exception.phpt" name="tests/Framework/Assert.exception.phpt"/>
<testcase classname="tests/Framework/Assert.false.phpt" name="tests/Framework/Assert.false.phpt"/>
<testcase classname="tests/Framework/Assert.match.phpt" name="tests/Framework/Assert.match.phpt"/>
<testcase classname="tests/Framework/Assert.match.regexp.phpt" name="tests/Framework/Assert.match.regexp.phpt"/>
<testcase classname="tests/Framework/Assert.nan.phpt" name="tests/Framework/Assert.nan.phpt"/>
<testcase classname="tests/Framework/Assert.noError.phpt" name="tests/Framework/Assert.noError.phpt"/>
<testcase classname="tests/Framework/Assert.same.phpt" name="tests/Framework/Assert.same.phpt"/>
<testcase classname="tests/Framework/Assert.null.phpt" name="tests/Framework/Assert.null.phpt"/>
<testcase classname="tests/Framework/Assert.true.phpt" name="tests/Framework/Assert.true.phpt"/>
<testcase classname="tests/Framework/Assert.truthy.phpt" name="tests/Framework/Assert.truthy.phpt"/>
<testcase classname="tests/Framework/DataProvider.load.phpt" name="tests/Framework/DataProvider.load.phpt"/>
<testcase classname="tests/Framework/Assert.type.phpt" name="tests/Framework/Assert.type.phpt"/>
<testcase classname="tests/Framework/DataProvider.parseAnnotation.phpt" name="tests/Framework/DataProvider.parseAnnotation.phpt"/>
<testcase classname="tests/Framework/DataProvider.testQuery.phpt" name="tests/Framework/DataProvider.testQuery.phpt"/>
<testcase classname="tests/Framework/DomQuery.css2Xpath.phpt" name="tests/Framework/DomQuery.css2Xpath.phpt"/>
<testcase classname="tests/Framework/DomQuery.fromHtml.phpt" name="tests/Framework/DomQuery.fromHtml.phpt"/>
<testcase classname="tests/Framework/DomQuery.fromXml.phpt" name="tests/Framework/DomQuery.fromXml.phpt"/>
<testcase classname="tests/Framework/Dumper.dumpException.phpt" name="tests/Framework/Dumper.dumpException.phpt"/>
<testcase classname="tests/Framework/Dumper.color.phpt" name="tests/Framework/Dumper.color.phpt"/>
<testcase classname="tests/Framework/Dumper.toLine.phpt" name="tests/Framework/Dumper.toLine.phpt"/>
<testcase classname="tests/Framework/Dumper.toPhp.recursion.phpt" name="tests/Framework/Dumper.toPhp.recursion.phpt"/>
<testcase classname="tests/Framework/Dumper.toPhp.phpt" name="tests/Framework/Dumper.toPhp.phpt"/>
<testcase classname="tests/Framework/FileMock.phpt" name="tests/Framework/FileMock.phpt"/>
<testcase classname="tests/Framework/Helpers.escapeArg.phpt" name="tests/Framework/Helpers.escapeArg.phpt"/>
<testcase classname="tests/Framework/Helpers.parseDocComment.phpt" name="tests/Framework/Helpers.parseDocComment.phpt"/>
<testcase classname="tests/Framework/TestCase.annotationThrows.phpt" name="tests/Framework/TestCase.annotationThrows.phpt"/>
<testcase classname="tests/Framework/TestCase.annotationThrows.setUp.tearDown.phpt" name="tests/Framework/TestCase.annotationThrows.setUp.tearDown.phpt"/>
<testcase classname="tests/Framework/TestCase.annotationThrows.syntax.phpt" name="tests/Framework/TestCase.annotationThrows.syntax.phpt"/>
<testcase classname="tests/Framework/TestCase.basic.phpt" name="tests/Framework/TestCase.basic.phpt"/>
<testcase classname="tests/Framework/TestCase.dataProvider.generator.phpt" name="tests/Framework/TestCase.dataProvider.generator.phpt"/>
<testcase classname="tests/Framework/TestCase.dataProvider.phpt" name="tests/Framework/TestCase.dataProvider.phpt"/>
<testcase classname="tests/Framework/TestCase.invalidMethods.phpt" name="tests/Framework/TestCase.invalidMethods.phpt"/>
<testcase classname="tests/Framework/TestCase.invalidProvider.phpt" name="tests/Framework/TestCase.invalidProvider.phpt"/>
<testcase classname="tests/Framework/TestCase.order.error.phpt" name="tests/Framework/TestCase.order.error.phpt"/>
<testcase classname="tests/Framework/TestCase.order.errorMuted.phpt" name="tests/Framework/TestCase.order.errorMuted.phpt"/>
<testcase classname="tests/Framework/TestCase.order.phpt" name="tests/Framework/TestCase.order.phpt"/>
<testcase classname="Prevent loop in error handling. The #268 regression. | tests/Framework/TestCase.ownErrorHandler.phpt" name="Prevent loop in error handling. The #268 regression. | tests/Framework/TestCase.ownErrorHandler.phpt"/>
<testcase classname="tests/Runner/CommandLine.phpt" name="tests/Runner/CommandLine.phpt"/>
<testcase classname="tests/Runner/HhvmPhpInterpreter.phpt" name="tests/Runner/HhvmPhpInterpreter.phpt">
<skipped/>
</testcase>
<testcase classname="tests/Runner/Runner.find-tests.phpt" name="tests/Runner/Runner.find-tests.phpt"/>
<testcase classname="tests/Runner/Job.phpt" name="tests/Runner/Job.phpt"/>
<testcase classname="tests/Runner/ZendPhpExecutable.phpt" name="tests/Runner/ZendPhpExecutable.phpt"/>
<testcase classname="tests/Runner/Runner.multiple.phpt" name="tests/Runner/Runner.multiple.phpt"/>
<testcase classname="tests/Runner/Runner.edge.phpt" name="tests/Runner/Runner.edge.phpt"/>
<testcase classname="tests/Runner/Runner.stop-on-fail.phpt" name="tests/Runner/Runner.stop-on-fail.phpt"/>
<testcase classname="tests/Runner/Runner.multiple-fails.phpt" name="tests/Runner/Runner.multiple-fails.phpt">
<failure message="Failed: '... in /Users/izso/Developer/nette/tester/tests/Runner/multiple-fails/...' should match
... '..., unexpected end of file in %a%testcase-syntax-error.phptx on line ...'
diff '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.expected' '/Users/izso/Developer/nette/tester/tests/Runner/output/Runner.multiple-fails.actual'
in tests/Runner/Runner.multiple-fails.phpt(78) Tester\Assert::match()"/>
</testcase>
<testcase classname="tests/RunnerOutput/JUnitPrinter.phpt" name="tests/RunnerOutput/JUnitPrinter.phpt"/>
<testcase classname="tests/Runner/Runner.annotations.phpt" name="tests/Runner/Runner.annotations.phpt"/>
</testsuite>
</testsuites>

View File

@@ -0,0 +1,224 @@
import * as fs from 'fs'
import * as path from 'path'
import {NetteTesterJunitParser} from '../src/parsers/tester-junit/tester-junit-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('tester-junit tests', () => {
it('produces empty test run result when there are no test cases', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'phpunit-empty.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
})
it('report from tester-v1.7-report.xml matches snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const outputPath = path.join(__dirname, '__outputs__', 'tester-v1.7-test-results.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('parses tester-v1.7-report.xml correctly', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Verify test counts from XML: tests="65" errors="1" skipped="3"
expect(result.tests).toBe(65)
expect(result.failed).toBe(1)
expect(result.skipped).toBe(3)
expect(result.passed).toBe(61)
// Verify suite name uses file name
expect(result.suites.length).toBe(1)
expect(result.suites[0].name).toBe('tester-v1.7-report.xml')
})
it('groups tests by directory structure', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Get all group names
const groupNames = result.suites[0].groups.map(g => g.name)
// Verify expected directory groups exist
expect(groupNames).toContain('tests/Framework')
expect(groupNames).toContain('tests/CodeCoverage')
expect(groupNames).toContain('tests/Runner')
expect(groupNames).toContain('tests/RunnerOutput')
})
it('parses test names with method suffixes correctly', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Find the Framework group which has tests with method suffixes
const frameworkGroup = result.suites[0].groups.find(g => g.name === 'tests/Framework')
expect(frameworkGroup).toBeDefined()
// Find tests with method suffixes
const testWithMethod = frameworkGroup!.tests.find(t => t.name.includes('::testSimple'))
expect(testWithMethod).toBeDefined()
expect(testWithMethod!.name).toBe('Assert.equal.recursive.phpt::testSimple')
})
it('parses complex test names from BootstrapFormRenderer-report.xml', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'BootstrapFormRenderer-report.xml')
const outputPath = path.join(__dirname, '__outputs__', 'tester-bootstrap-test-results.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Verify test counts: 4 tests, all passed
expect(result.tests).toBe(4)
expect(result.passed).toBe(4)
expect(result.failed).toBe(0)
expect(result.skipped).toBe(0)
// Verify suite name
expect(result.suites[0].name).toBe('BootstrapFormRenderer-report.xml')
// All tests should have method names
const allTests = result.suites[0].groups.flatMap(g => g.tests)
expect(allTests.every(t => t.name.includes('::'))).toBe(true)
expect(allTests.some(t => t.name.includes('::testRenderingBasics'))).toBe(true)
expect(allTests.some(t => t.name.includes('::testRenderingIndividual'))).toBe(true)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('extracts error details from failures', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Find the failed test
const allTests = result.suites[0].groups.flatMap(g => g.tests)
const failedTests = allTests.filter(t => t.result === 'failed')
expect(failedTests.length).toBe(1)
// Verify error details are captured
const failedTest = failedTests[0]
expect(failedTest.error).toBeDefined()
expect(failedTest.error!.details).toContain('Failed:')
expect(failedTest.error!.details).toContain('multiple-fails')
})
it('correctly identifies skipped tests', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Find skipped tests
const allTests = result.suites[0].groups.flatMap(g => g.tests)
const skippedTests = allTests.filter(t => t.result === 'skipped')
expect(skippedTests.length).toBe(3)
// Verify some known skipped tests
expect(skippedTests.some(t => t.name.includes('Dumper.toPhp.php7.phpt'))).toBe(true)
expect(skippedTests.some(t => t.name.includes('Collector.start.phpt'))).toBe(true)
})
it('parses test with description prefix correctly', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'nette-tester', 'tester-v1.7-report.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new NetteTesterJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
// Find test with description prefix
const allTests = result.suites[0].groups.flatMap(g => g.tests)
// The test name is generated from the basename, and the description is shown in parentheses
const testWithDescription = allTests.find(t => t.name.includes('Prevent loop'))
expect(testWithDescription).toBeDefined()
expect(testWithDescription!.name).toContain('Prevent loop')
expect(testWithDescription!.name).toContain('TestCase.ownErrorHandler.phpt')
})
})