mirror of
https://github.com/dorny/test-reporter.git
synced 2026-02-02 03:15:22 -08:00
Compare commits
17 Commits
fix/comple
...
bugfix/703
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
055bc8c025 | ||
|
|
17c900ba4e | ||
|
|
ff2d13cc36 | ||
|
|
20823bb69a | ||
|
|
0be3971fec | ||
|
|
4ee97617f7 | ||
|
|
a97700c53c | ||
|
|
837045e72b | ||
|
|
d1de4d5f06 | ||
|
|
f24c625f56 | ||
|
|
ee446707ff | ||
|
|
fe45e95373 | ||
|
|
e40a1da745 | ||
|
|
3445860437 | ||
|
|
9ef5c136b2 | ||
|
|
83e20c1534 | ||
|
|
79ea6a9d0e |
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2.3.0
|
||||||
|
* Feature: Add Python support with `python-xunit` reporter (pytest) https://github.com/dorny/test-reporter/pull/643
|
||||||
|
* Feature: Add pytest traceback parsing and `directory-mapping` option https://github.com/dorny/test-reporter/pull/238
|
||||||
|
* Performance: Update sax.js to fix large XML file parsing https://github.com/dorny/test-reporter/pull/681
|
||||||
|
* Documentation: Complete documentation for all supported reporters https://github.com/dorny/test-reporter/pull/691
|
||||||
|
* Security: Bump js-yaml and mocha in /reports/mocha (fixes prototype pollution) https://github.com/dorny/test-reporter/pull/682
|
||||||
|
|
||||||
## 2.2.0
|
## 2.2.0
|
||||||
* Feature: Add collapsed option to control report summary visibility https://github.com/dorny/test-reporter/pull/664
|
* Feature: Add collapsed option to control report summary visibility https://github.com/dorny/test-reporter/pull/664
|
||||||
* Fix badge encoding for values including underscore and hyphens https://github.com/dorny/test-reporter/pull/672
|
* Fix badge encoding for values including underscore and hyphens https://github.com/dorny/test-reporter/pull/672
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -20,6 +20,7 @@ This [Github Action](https://github.com/features/actions) displays test results
|
|||||||
- Java / [JUnit](https://junit.org/)
|
- Java / [JUnit](https://junit.org/)
|
||||||
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
|
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
|
||||||
- Python / [pytest](https://docs.pytest.org/en/stable/) / [unittest](https://docs.python.org/3/library/unittest.html)
|
- Python / [pytest](https://docs.pytest.org/en/stable/) / [unittest](https://docs.python.org/3/library/unittest.html)
|
||||||
|
- PHP / [PHPUnit](https://phpunit.de/)
|
||||||
- Ruby / [RSpec](https://rspec.info/)
|
- Ruby / [RSpec](https://rspec.info/)
|
||||||
- Swift / xUnit
|
- Swift / xUnit
|
||||||
|
|
||||||
@@ -147,6 +148,7 @@ jobs:
|
|||||||
# java-junit
|
# java-junit
|
||||||
# jest-junit
|
# jest-junit
|
||||||
# mocha-json
|
# mocha-json
|
||||||
|
# phpunit-junit
|
||||||
# python-xunit
|
# python-xunit
|
||||||
# rspec-json
|
# rspec-json
|
||||||
# swift-xunit
|
# swift-xunit
|
||||||
@@ -314,6 +316,14 @@ This is due to the fact Java stack traces don't contain a full path to the sourc
|
|||||||
Some heuristic was necessary to figure out the mapping between the line in the stack trace and an actual source file.
|
Some heuristic was necessary to figure out the mapping between the line in the stack trace and an actual source file.
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>phpunit-junit</summary>
|
||||||
|
|
||||||
|
[PHPUnit](https://phpunit.de/) can generate JUnit XML via CLI:
|
||||||
|
`phpunit --log-junit reports/phpunit-junit.xml`
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>jest-junit</summary>
|
<summary>jest-junit</summary>
|
||||||
|
|
||||||
|
|||||||
23
__tests__/__outputs__/junit-basic.md
Normal file
23
__tests__/__outputs__/junit-basic.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|

|
||||||
|
|Report|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[fixtures/external/java/junit4-basic.xml](#user-content-r0)|5 ✅|1 ❌||16s|
|
||||||
|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/external/java/junit4-basic.xml</a>
|
||||||
|
**6** tests were completed in **16s** with **5** passed, **1** failed and **0** skipped.
|
||||||
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[Tests.Authentication](#user-content-r0s0)|2 ✅|1 ❌||9s|
|
||||||
|
|[Tests.Registration](#user-content-r0s1)|3 ✅|||7s|
|
||||||
|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">Tests.Authentication</a>
|
||||||
|
```
|
||||||
|
✅ testCase7
|
||||||
|
✅ testCase8
|
||||||
|
❌ testCase9
|
||||||
|
AssertionError: Assertion error message
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">Tests.Registration</a>
|
||||||
|
```
|
||||||
|
✅ testCase1
|
||||||
|
✅ testCase2
|
||||||
|
✅ testCase3
|
||||||
|
```
|
||||||
22
__tests__/__outputs__/junit-complete.md
Normal file
22
__tests__/__outputs__/junit-complete.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|

|
||||||
|
|Report|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[fixtures/external/java/junit4-complete.xml](#user-content-r0)|5 ✅|2 ❌|1 ⚪|16s|
|
||||||
|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/external/java/junit4-complete.xml</a>
|
||||||
|
**8** tests were completed in **16s** with **5** passed, **2** failed and **1** skipped.
|
||||||
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[Tests.Registration](#user-content-r0s0)|5 ✅|2 ❌|1 ⚪|16s|
|
||||||
|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">Tests.Registration</a>
|
||||||
|
```
|
||||||
|
✅ testCase1
|
||||||
|
✅ testCase2
|
||||||
|
✅ testCase3
|
||||||
|
⚪ testCase4
|
||||||
|
❌ testCase5
|
||||||
|
AssertionError: Expected value did not match.
|
||||||
|
❌ testCase6
|
||||||
|
ArithmeticError: Division by zero.
|
||||||
|
✅ testCase7
|
||||||
|
✅ testCase8
|
||||||
|
```
|
||||||
30
__tests__/__outputs__/phpunit-junit-basic-results.md
Normal file
30
__tests__/__outputs__/phpunit-junit-basic-results.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|

|
||||||
|
|Report|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[fixtures/external/phpunit/junit-basic.xml](#user-content-r0)|8 ✅|1 ❌||16s|
|
||||||
|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/external/phpunit/junit-basic.xml</a>
|
||||||
|
**9** tests were completed in **16s** with **8** passed, **1** failed and **0** skipped.
|
||||||
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[Tests.Authentication](#user-content-r0s0)|2 ✅|1 ❌||9s|
|
||||||
|
|[Tests.Authentication.Login](#user-content-r0s1)|3 ✅|||4s|
|
||||||
|
|[Tests.Registration](#user-content-r0s2)|3 ✅|||7s|
|
||||||
|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">Tests.Authentication</a>
|
||||||
|
```
|
||||||
|
✅ testCase7
|
||||||
|
✅ testCase8
|
||||||
|
❌ testCase9
|
||||||
|
AssertionError: Assertion error message
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">Tests.Authentication.Login</a>
|
||||||
|
```
|
||||||
|
✅ testCase4
|
||||||
|
✅ testCase5
|
||||||
|
✅ testCase6
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">Tests.Registration</a>
|
||||||
|
```
|
||||||
|
✅ testCase1
|
||||||
|
✅ testCase2
|
||||||
|
✅ testCase3
|
||||||
|
```
|
||||||
88
__tests__/__outputs__/phpunit-phpcheckstyle-results.md
Normal file
88
__tests__/__outputs__/phpunit-phpcheckstyle-results.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|

|
||||||
|
|Report|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[fixtures/external/phpunit/phpcheckstyle-phpunit.xml](#user-content-r0)|28 ✅|2 ❌||41ms|
|
||||||
|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/external/phpunit/phpcheckstyle-phpunit.xml</a>
|
||||||
|
**30** tests were completed in **41ms** with **28** passed, **2** failed and **0** skipped.
|
||||||
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[CommentsTest](#user-content-r0s0)|3 ✅|||7ms|
|
||||||
|
|[DeprecationTest](#user-content-r0s1)|1 ✅|||1ms|
|
||||||
|
|[GoodTest](#user-content-r0s2)|4 ✅|||5ms|
|
||||||
|
|[IndentationTest](#user-content-r0s3)|8 ✅|||8ms|
|
||||||
|
|[MetricsTest](#user-content-r0s4)|1 ✅|||4ms|
|
||||||
|
|[NamingTest](#user-content-r0s5)|2 ✅|||3ms|
|
||||||
|
|[OptimizationTest](#user-content-r0s6)|1 ✅|||1ms|
|
||||||
|
|[OtherTest](#user-content-r0s7)|2 ✅|2 ❌||7ms|
|
||||||
|
|[PHPTagsTest](#user-content-r0s8)|2 ✅|||1ms|
|
||||||
|
|[ProhibitedTest](#user-content-r0s9)|1 ✅|||1ms|
|
||||||
|
|[StrictCompareTest](#user-content-r0s10)|1 ✅|||2ms|
|
||||||
|
|[UnusedTest](#user-content-r0s11)|2 ✅|||2ms|
|
||||||
|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">CommentsTest</a>
|
||||||
|
```
|
||||||
|
✅ testGoodDoc
|
||||||
|
✅ testComments
|
||||||
|
✅ testTODOs
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">DeprecationTest</a>
|
||||||
|
```
|
||||||
|
✅ testDeprecations
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">GoodTest</a>
|
||||||
|
```
|
||||||
|
✅ testGood
|
||||||
|
✅ testDoWhile
|
||||||
|
✅ testAnonymousFunction
|
||||||
|
✅ testException
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">IndentationTest</a>
|
||||||
|
```
|
||||||
|
✅ testTabIndentation
|
||||||
|
✅ testSpaceIndentation
|
||||||
|
✅ testSpaceIndentationArray
|
||||||
|
✅ testGoodSpaceIndentationArray
|
||||||
|
✅ testGoodIndentationNewLine
|
||||||
|
✅ testGoodIndentationSpaces
|
||||||
|
✅ testBadSpaces
|
||||||
|
✅ testBadSpaceAfterControl
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s4" href="#user-content-r0s4">MetricsTest</a>
|
||||||
|
```
|
||||||
|
✅ testMetrics
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s5" href="#user-content-r0s5">NamingTest</a>
|
||||||
|
```
|
||||||
|
✅ testNaming
|
||||||
|
✅ testFunctionNaming
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s6" href="#user-content-r0s6">OptimizationTest</a>
|
||||||
|
```
|
||||||
|
✅ testTextAfterClosingTag
|
||||||
|
```
|
||||||
|
### ❌ <a id="user-content-r0s7" href="#user-content-r0s7">OtherTest</a>
|
||||||
|
```
|
||||||
|
❌ testOther
|
||||||
|
PHPUnit\Framework\ExpectationFailedException
|
||||||
|
❌ testException
|
||||||
|
PHPUnit\Framework\ExpectationFailedException
|
||||||
|
✅ testEmpty
|
||||||
|
✅ testSwitchCaseNeedBreak
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s8" href="#user-content-r0s8">PHPTagsTest</a>
|
||||||
|
```
|
||||||
|
✅ testTextAfterClosingTag
|
||||||
|
✅ testClosingTagNotNeeded
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s9" href="#user-content-r0s9">ProhibitedTest</a>
|
||||||
|
```
|
||||||
|
✅ testProhibited
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s10" href="#user-content-r0s10">StrictCompareTest</a>
|
||||||
|
```
|
||||||
|
✅ testStrictCompare
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s11" href="#user-content-r0s11">UnusedTest</a>
|
||||||
|
```
|
||||||
|
✅ testGoodUnused
|
||||||
|
✅ testBadUnused
|
||||||
|
```
|
||||||
41
__tests__/__outputs__/phpunit-test-results.md
Normal file
41
__tests__/__outputs__/phpunit-test-results.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|

|
||||||
|
|Report|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[fixtures/phpunit/phpunit.xml](#user-content-r0)|10 ✅|2 ❌||148ms|
|
||||||
|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/phpunit/phpunit.xml</a>
|
||||||
|
**12** tests were completed in **148ms** with **10** passed, **2** failed and **0** skipped.
|
||||||
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[CLI Arguments](#user-content-r0s0)||2 ❌||140ms|
|
||||||
|
|[PHPUnit\Event\CollectingDispatcherTest](#user-content-r0s1)|2 ✅|||4ms|
|
||||||
|
|[PHPUnit\Event\DeferringDispatcherTest](#user-content-r0s2)|4 ✅|||3ms|
|
||||||
|
|[PHPUnit\Event\DirectDispatcherTest](#user-content-r0s3)|4 ✅|||1ms|
|
||||||
|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">CLI Arguments</a>
|
||||||
|
```
|
||||||
|
❌ targeting-traits-with-coversclass-attribute-is-deprecated.phpt
|
||||||
|
PHPUnit\Framework\PhptAssertionFailedError
|
||||||
|
❌ targeting-traits-with-usesclass-attribute-is-deprecated.phpt
|
||||||
|
PHPUnit\Framework\PhptAssertionFailedError
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">PHPUnit\Event\CollectingDispatcherTest</a>
|
||||||
|
```
|
||||||
|
PHPUnit.Event.CollectingDispatcherTest
|
||||||
|
✅ testHasNoCollectedEventsWhenFlushedImmediatelyAfterCreation
|
||||||
|
✅ testCollectsDispatchedEventsUntilFlushed
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">PHPUnit\Event\DeferringDispatcherTest</a>
|
||||||
|
```
|
||||||
|
PHPUnit.Event.DeferringDispatcherTest
|
||||||
|
✅ testCollectsEventsUntilFlush
|
||||||
|
✅ testFlushesCollectedEvents
|
||||||
|
✅ testSubscriberCanBeRegistered
|
||||||
|
✅ testTracerCanBeRegistered
|
||||||
|
```
|
||||||
|
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">PHPUnit\Event\DirectDispatcherTest</a>
|
||||||
|
```
|
||||||
|
PHPUnit.Event.DirectDispatcherTest
|
||||||
|
✅ testDispatchesEventToKnownSubscribers
|
||||||
|
✅ testDispatchesEventToTracers
|
||||||
|
✅ testRegisterRejectsUnknownSubscriber
|
||||||
|
✅ testDispatchRejectsUnknownEventType
|
||||||
|
```
|
||||||
@@ -6878,3 +6878,153 @@ at java.lang.Thread.run(Thread.java:748)
|
|||||||
"totalTime": 2126531.0000000005,
|
"totalTime": 2126531.0000000005,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`java-junit tests report from testmo/junitxml basic example matches snapshot 1`] = `
|
||||||
|
TestRunResult {
|
||||||
|
"path": "fixtures/external/java/junit4-basic.xml",
|
||||||
|
"suites": [
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase1",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2113.871,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase2",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1051,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase3",
|
||||||
|
"result": "success",
|
||||||
|
"time": 3441,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "Tests.Registration",
|
||||||
|
"totalTime": 6605.870999999999,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase7",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2508,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase8",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1230.8159999999998,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": undefined,
|
||||||
|
"line": undefined,
|
||||||
|
"message": "AssertionError: Assertion error message",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "testCase9",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 982,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "Tests.Authentication",
|
||||||
|
"totalTime": 9076.816,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"totalTime": 15682.687,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`java-junit tests report from testmo/junitxml complete example matches snapshot 1`] = `
|
||||||
|
TestRunResult {
|
||||||
|
"path": "fixtures/external/java/junit4-complete.xml",
|
||||||
|
"suites": [
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase1",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2436,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase2",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1534,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase3",
|
||||||
|
"result": "success",
|
||||||
|
"time": 822,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase4",
|
||||||
|
"result": "skipped",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": undefined,
|
||||||
|
"line": undefined,
|
||||||
|
"message": "AssertionError: Expected value did not match.",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "testCase5",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 2902.412,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": undefined,
|
||||||
|
"line": undefined,
|
||||||
|
"message": "ArithmeticError: Division by zero.",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "testCase6",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 3819,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase7",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2944,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase8",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1625.275,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "Tests.Registration",
|
||||||
|
"totalTime": 16082.687,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"totalTime": 16082.687,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
628
__tests__/__snapshots__/phpunit-junit.test.ts.snap
Normal file
628
__tests__/__snapshots__/phpunit-junit.test.ts.snap
Normal file
@@ -0,0 +1,628 @@
|
|||||||
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||||
|
|
||||||
|
exports[`phpunit-junit tests report from junit-basic.xml matches snapshot 1`] = `
|
||||||
|
TestRunResult {
|
||||||
|
"path": "fixtures/external/phpunit/junit-basic.xml",
|
||||||
|
"suites": [
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase1",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2113.871,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase2",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1051,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase3",
|
||||||
|
"result": "success",
|
||||||
|
"time": 3441,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "Tests.Registration",
|
||||||
|
"totalTime": 6605.870999999999,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase4",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2244,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase5",
|
||||||
|
"result": "success",
|
||||||
|
"time": 781,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase6",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1331,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "Tests.Authentication.Login",
|
||||||
|
"totalTime": 4356,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase7",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2508,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCase8",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1230.8159999999998,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": "",
|
||||||
|
"line": undefined,
|
||||||
|
"message": "AssertionError: Assertion error message",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "testCase9",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 982,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "Tests.Authentication",
|
||||||
|
"totalTime": 9076.816,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"totalTime": 15682.687,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`phpunit-junit tests report from phpcheckstyle-phpunit.xml matches snapshot 1`] = `
|
||||||
|
TestRunResult {
|
||||||
|
"path": "fixtures/external/phpunit/phpcheckstyle-phpunit.xml",
|
||||||
|
"suites": [
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testGoodDoc",
|
||||||
|
"result": "success",
|
||||||
|
"time": 5.093,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testComments",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.921,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testTODOs",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.6880000000000001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "CommentsTest",
|
||||||
|
"totalTime": 6.702,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testDeprecations",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.9740000000000001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "DeprecationTest",
|
||||||
|
"totalTime": 0.9740000000000001,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testGood",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2.6470000000000002,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testDoWhile",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.0219999999999998,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testAnonymousFunction",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.8,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testException",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.888,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "GoodTest",
|
||||||
|
"totalTime": 5.357,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testTabIndentation",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.857,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testSpaceIndentation",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.929,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testSpaceIndentationArray",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.975,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testGoodSpaceIndentationArray",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.212,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testGoodIndentationNewLine",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.859,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testGoodIndentationSpaces",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.78,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testBadSpaces",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.1199999999999999,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testBadSpaceAfterControl",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.9219999999999999,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "IndentationTest",
|
||||||
|
"totalTime": 7.654,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testMetrics",
|
||||||
|
"result": "success",
|
||||||
|
"time": 4.146999999999999,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "MetricsTest",
|
||||||
|
"totalTime": 4.146999999999999,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testNaming",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.426,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testFunctionNaming",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.271,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "NamingTest",
|
||||||
|
"totalTime": 2.697,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testTextAfterClosingTag",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.9940000000000001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "OptimizationTest",
|
||||||
|
"totalTime": 0.9940000000000001,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": "OtherTest::testOther
|
||||||
|
We expect 20 warnings
|
||||||
|
Failed asserting that 19 matches expected 20.
|
||||||
|
|
||||||
|
/workspace/phpcheckstyle/test/OtherTest.php:24",
|
||||||
|
"line": 12,
|
||||||
|
"message": "PHPUnit\\Framework\\ExpectationFailedException",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "testOther",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 5.2509999999999994,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": "OtherTest::testException
|
||||||
|
We expect 1 error
|
||||||
|
Failed asserting that 0 matches expected 1.
|
||||||
|
|
||||||
|
/workspace/phpcheckstyle/test/OtherTest.php:40",
|
||||||
|
"line": 31,
|
||||||
|
"message": "PHPUnit\\Framework\\ExpectationFailedException",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "testException",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 0.751,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testEmpty",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.42700000000000005,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testSwitchCaseNeedBreak",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.901,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "OtherTest",
|
||||||
|
"totalTime": 7.329,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testTextAfterClosingTag",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.641,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testClosingTagNotNeeded",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.631,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "PHPTagsTest",
|
||||||
|
"totalTime": 1.272,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testProhibited",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.9380000000000001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "ProhibitedTest",
|
||||||
|
"totalTime": 0.9380000000000001,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testStrictCompare",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.578,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "StrictCompareTest",
|
||||||
|
"totalTime": 1.578,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testGoodUnused",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.94,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testBadUnused",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.895,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "UnusedTest",
|
||||||
|
"totalTime": 1.835,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"totalTime": undefined,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`phpunit-junit tests report from phpunit test results matches snapshot 1`] = `
|
||||||
|
TestRunResult {
|
||||||
|
"path": "fixtures/phpunit/phpunit.xml",
|
||||||
|
"suites": [
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "PHPUnit.Event.CollectingDispatcherTest",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testHasNoCollectedEventsWhenFlushedImmediatelyAfterCreation",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.441,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCollectsDispatchedEventsUntilFlushed",
|
||||||
|
"result": "success",
|
||||||
|
"time": 2.815,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "PHPUnit\\Event\\CollectingDispatcherTest",
|
||||||
|
"totalTime": 4.256,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "PHPUnit.Event.DeferringDispatcherTest",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testCollectsEventsUntilFlush",
|
||||||
|
"result": "success",
|
||||||
|
"time": 1.6720000000000002,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testFlushesCollectedEvents",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.661,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testSubscriberCanBeRegistered",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.33399999999999996,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testTracerCanBeRegistered",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.262,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "PHPUnit\\Event\\DeferringDispatcherTest",
|
||||||
|
"totalTime": 2.928,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "PHPUnit.Event.DirectDispatcherTest",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testDispatchesEventToKnownSubscribers",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.17,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testDispatchesEventToTracers",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.248,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testRegisterRejectsUnknownSubscriber",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.257,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": undefined,
|
||||||
|
"name": "testDispatchRejectsUnknownEventType",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0.11900000000000001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "PHPUnit\\Event\\DirectDispatcherTest",
|
||||||
|
"totalTime": 0.794,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "",
|
||||||
|
"tests": [
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": "targeting-traits-with-coversclass-attribute-is-deprecated.phptFailed asserting that string matches format description.
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ @@
|
||||||
|
PHPUnit Started (PHPUnit 11.2-g0c2333363 using PHP 8.2.17 (cli) on Linux)
|
||||||
|
Test Runner Configured
|
||||||
|
Test Suite Loaded (1 test)
|
||||||
|
+Test Runner Triggered Warning (No code coverage driver available)
|
||||||
|
Event Facade Sealed
|
||||||
|
Test Runner Started
|
||||||
|
Test Suite Sorted
|
||||||
|
@@ @@
|
||||||
|
Test Preparation Started (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
Test Prepared (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
Test Passed (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
-Test Runner Triggered Deprecation (Targeting a trait such as PHPUnit\\TestFixture\\CoveredTrait with #[CoversClass] is deprecated, please refactor your test to use #[CoversTrait] instead.)
|
||||||
|
Test Finished (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
Test Suite Finished (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithCoversClassTest, 1 test)
|
||||||
|
Test Runner Execution Finished
|
||||||
|
Test Runner Finished
|
||||||
|
-PHPUnit Finished (Shell Exit Code: 0)
|
||||||
|
+PHPUnit Finished (Shell Exit Code: 1)
|
||||||
|
|
||||||
|
/home/matteo/OSS/phpunit/tests/end-to-end/metadata/targeting-traits-with-coversclass-attribute-is-deprecated.phpt:28
|
||||||
|
/home/matteo/OSS/phpunit/src/Framework/TestSuite.php:369
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/TestRunner.php:62
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/Application.php:200",
|
||||||
|
"line": undefined,
|
||||||
|
"message": "PHPUnit\\Framework\\PhptAssertionFailedError",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "targeting-traits-with-coversclass-attribute-is-deprecated.phpt",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 68.151,
|
||||||
|
},
|
||||||
|
TestCaseResult {
|
||||||
|
"error": {
|
||||||
|
"details": "targeting-traits-with-usesclass-attribute-is-deprecated.phptFailed asserting that string matches format description.
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ @@
|
||||||
|
PHPUnit Started (PHPUnit 11.2-g0c2333363 using PHP 8.2.17 (cli) on Linux)
|
||||||
|
Test Runner Configured
|
||||||
|
Test Suite Loaded (1 test)
|
||||||
|
+Test Runner Triggered Warning (No code coverage driver available)
|
||||||
|
Event Facade Sealed
|
||||||
|
Test Runner Started
|
||||||
|
Test Suite Sorted
|
||||||
|
@@ @@
|
||||||
|
Test Preparation Started (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
Test Prepared (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
Test Passed (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
-Test Runner Triggered Deprecation (Targeting a trait such as PHPUnit\\TestFixture\\CoveredTrait with #[UsesClass] is deprecated, please refactor your test to use #[UsesTrait] instead.)
|
||||||
|
Test Finished (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
Test Suite Finished (PHPUnit\\DeprecatedAnnotationsTestFixture\\TraitTargetedWithUsesClassTest, 1 test)
|
||||||
|
Test Runner Execution Finished
|
||||||
|
Test Runner Finished
|
||||||
|
-PHPUnit Finished (Shell Exit Code: 0)
|
||||||
|
+PHPUnit Finished (Shell Exit Code: 1)
|
||||||
|
|
||||||
|
/home/matteo/OSS/phpunit/tests/end-to-end/metadata/targeting-traits-with-usesclass-attribute-is-deprecated.phpt:28
|
||||||
|
/home/matteo/OSS/phpunit/src/Framework/TestSuite.php:369
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/TestRunner.php:62
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/Application.php:200",
|
||||||
|
"line": undefined,
|
||||||
|
"message": "PHPUnit\\Framework\\PhptAssertionFailedError",
|
||||||
|
"path": undefined,
|
||||||
|
},
|
||||||
|
"name": "targeting-traits-with-usesclass-attribute-is-deprecated.phpt",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 64.268,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "CLI Arguments",
|
||||||
|
"totalTime": 140.397,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"totalTime": undefined,
|
||||||
|
}
|
||||||
|
`;
|
||||||
2
__tests__/fixtures/empty/phpunit-empty.xml
Normal file
2
__tests__/fixtures/empty/phpunit-empty.xml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites/>
|
||||||
31
__tests__/fixtures/external/java/junit4-basic.xml
vendored
Normal file
31
__tests__/fixtures/external/java/junit4-basic.xml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
This is a basic JUnit-style XML example to highlight the basis structure.
|
||||||
|
|
||||||
|
Example by Testmo. Copyright 2023 Testmo GmbH. All rights reserved.
|
||||||
|
Testmo test management software - https://www.testmo.com/
|
||||||
|
-->
|
||||||
|
<testsuites time="15.682687">
|
||||||
|
<testsuite name="Tests.Registration" time="6.605871">
|
||||||
|
<testcase name="testCase1" classname="Tests.Registration" time="2.113871" />
|
||||||
|
<testcase name="testCase2" classname="Tests.Registration" time="1.051" />
|
||||||
|
<testcase name="testCase3" classname="Tests.Registration" time="3.441" />
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="Tests.Authentication" time="9.076816">
|
||||||
|
<!-- Java JUni4 XML files does not nest <testsuite> elements -->
|
||||||
|
<!--
|
||||||
|
<testsuite name="Tests.Authentication.Login" time="4.356">
|
||||||
|
<testcase name="testCase4" classname="Tests.Authentication.Login" time="2.244" />
|
||||||
|
<testcase name="testCase5" classname="Tests.Authentication.Login" time="0.781" />
|
||||||
|
<testcase name="testCase6" classname="Tests.Authentication.Login" time="1.331" />
|
||||||
|
</testsuite>
|
||||||
|
-->
|
||||||
|
<testcase name="testCase7" classname="Tests.Authentication" time="2.508" />
|
||||||
|
<testcase name="testCase8" classname="Tests.Authentication" time="1.230816" />
|
||||||
|
<testcase name="testCase9" classname="Tests.Authentication" time="0.982">
|
||||||
|
<failure message="Assertion error message" type="AssertionError">
|
||||||
|
<!-- Call stack printed here -->
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
141
__tests__/fixtures/external/java/junit4-complete.xml
vendored
Normal file
141
__tests__/fixtures/external/java/junit4-complete.xml
vendored
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
This is a JUnit-style XML example with commonly used tags and attributes.
|
||||||
|
|
||||||
|
Example by Testmo. Copyright 2023 Testmo GmbH. All rights reserved.
|
||||||
|
Testmo test management software - https://www.testmo.com/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- <testsuites> Usually the root element of a JUnit XML file. Some tools leave out
|
||||||
|
the <testsuites> element if there is only a single top-level <testsuite> element (which
|
||||||
|
is then used as the root element).
|
||||||
|
|
||||||
|
name Name of the entire test run
|
||||||
|
tests Total number of tests in this file
|
||||||
|
failures Total number of failed tests in this file
|
||||||
|
errors Total number of errored tests in this file
|
||||||
|
skipped Total number of skipped tests in this file
|
||||||
|
assertions Total number of assertions for all tests in this file
|
||||||
|
time Aggregated time of all tests in this file in seconds
|
||||||
|
timestamp Date and time of when the test run was executed (in ISO 8601 format)
|
||||||
|
-->
|
||||||
|
<testsuites name="Test run" tests="8" failures="1" errors="1" skipped="1"
|
||||||
|
assertions="20" time="16.082687" timestamp="2021-04-02T15:48:23">
|
||||||
|
|
||||||
|
<!-- <testsuite> A test suite usually represents a class, folder or group of tests.
|
||||||
|
There can be many test suites in an XML file, and there can be test suites under other
|
||||||
|
test suites.
|
||||||
|
|
||||||
|
name Name of the test suite (e.g. class name or folder name)
|
||||||
|
tests Total number of tests in this suite
|
||||||
|
failures Total number of failed tests in this suite
|
||||||
|
errors Total number of errored tests in this suite
|
||||||
|
skipped Total number of skipped tests in this suite
|
||||||
|
assertions Total number of assertions for all tests in this suite
|
||||||
|
time Aggregated time of all tests in this file in seconds
|
||||||
|
timestamp Date and time of when the test suite was executed (in ISO 8601 format)
|
||||||
|
file Source code file of this test suite
|
||||||
|
-->
|
||||||
|
<testsuite name="Tests.Registration" tests="8" failures="1" errors="1" skipped="1"
|
||||||
|
assertions="20" time="16.082687" timestamp="2021-04-02T15:48:23"
|
||||||
|
file="tests/registration.code">
|
||||||
|
|
||||||
|
<!-- <properties> Test suites (and test cases, see below) can have additional
|
||||||
|
properties such as environment variables or version numbers. -->
|
||||||
|
<properties>
|
||||||
|
<!-- <property> Each property has a name and value. Some tools also support
|
||||||
|
properties with text values instead of value attributes. -->
|
||||||
|
<property name="version" value="1.774" />
|
||||||
|
<property name="commit" value="ef7bebf" />
|
||||||
|
<property name="browser" value="Google Chrome" />
|
||||||
|
<property name="ci" value="https://github.com/actions/runs/1234" />
|
||||||
|
<property name="config">
|
||||||
|
Config line #1
|
||||||
|
Config line #2
|
||||||
|
Config line #3
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<!-- <system-out> Optionally data written to standard out for the suite.
|
||||||
|
Also supported on a test case level, see below. -->
|
||||||
|
<system-out>Data written to standard out.</system-out>
|
||||||
|
|
||||||
|
<!-- <system-err> Optionally data written to standard error for the suite.
|
||||||
|
Also supported on a test case level, see below. -->
|
||||||
|
<system-err>Data written to standard error.</system-err>
|
||||||
|
|
||||||
|
<!-- <testcase> There are one or more test cases in a test suite. A test passed
|
||||||
|
if there isn't an additional result element (skipped, failure, error).
|
||||||
|
|
||||||
|
name The name of this test case, often the method name
|
||||||
|
classname The name of the parent class/folder, often the same as the suite's name
|
||||||
|
assertions Number of assertions checked during test case execution
|
||||||
|
time Execution time of the test in seconds
|
||||||
|
file Source code file of this test case
|
||||||
|
line Source code line number of the start of this test case
|
||||||
|
-->
|
||||||
|
<testcase name="testCase1" classname="Tests.Registration" assertions="2"
|
||||||
|
time="2.436" file="tests/registration.code" line="24" />
|
||||||
|
<testcase name="testCase2" classname="Tests.Registration" assertions="6"
|
||||||
|
time="1.534" file="tests/registration.code" line="62" />
|
||||||
|
<testcase name="testCase3" classname="Tests.Registration" assertions="3"
|
||||||
|
time="0.822" file="tests/registration.code" line="102" />
|
||||||
|
|
||||||
|
<!-- Example of a test case that was skipped -->
|
||||||
|
<testcase name="testCase4" classname="Tests.Registration" assertions="0"
|
||||||
|
time="0" file="tests/registration.code" line="164">
|
||||||
|
<!-- <skipped> Indicates that the test was not executed. Can have an optional
|
||||||
|
message describing why the test was skipped. -->
|
||||||
|
<skipped message="Test was skipped." />
|
||||||
|
</testcase>
|
||||||
|
|
||||||
|
<!-- Example of a test case that failed. -->
|
||||||
|
<testcase name="testCase5" classname="Tests.Registration" assertions="2"
|
||||||
|
time="2.902412" file="tests/registration.code" line="202">
|
||||||
|
<!-- <failure> The test failed because one of the assertions/checks failed.
|
||||||
|
Can have a message and failure type, often the assertion type or class. The text
|
||||||
|
content of the element often includes the failure description or stack trace. -->
|
||||||
|
<failure message="Expected value did not match." type="AssertionError">
|
||||||
|
<!-- Failure description or stack trace -->
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
|
||||||
|
<!-- Example of a test case that had errors. -->
|
||||||
|
<testcase name="testCase6" classname="Tests.Registration" assertions="0"
|
||||||
|
time="3.819" file="tests/registration.code" line="235">
|
||||||
|
<!-- <error> The test had an unexpected error during execution. Can have a
|
||||||
|
message and error type, often the exception type or class. The text
|
||||||
|
content of the element often includes the error description or stack trace. -->
|
||||||
|
<error message="Division by zero." type="ArithmeticError">
|
||||||
|
<!-- Error description or stack trace -->
|
||||||
|
</error>
|
||||||
|
</testcase>
|
||||||
|
|
||||||
|
<!-- Example of a test case with outputs. -->
|
||||||
|
<testcase name="testCase7" classname="Tests.Registration" assertions="3"
|
||||||
|
time="2.944" file="tests/registration.code" line="287">
|
||||||
|
<!-- <system-out> Optional data written to standard out for the test case. -->
|
||||||
|
<system-out>Data written to standard out.</system-out>
|
||||||
|
|
||||||
|
<!-- <system-err> Optional data written to standard error for the test case. -->
|
||||||
|
<system-err>Data written to standard error.</system-err>
|
||||||
|
</testcase>
|
||||||
|
|
||||||
|
<!-- Example of a test case with properties -->
|
||||||
|
<testcase name="testCase8" classname="Tests.Registration" assertions="4"
|
||||||
|
time="1.625275" file="tests/registration.code" line="302">
|
||||||
|
<!-- <properties> Some tools also support properties for test cases. -->
|
||||||
|
<properties>
|
||||||
|
<property name="priority" value="high" />
|
||||||
|
<property name="language" value="english" />
|
||||||
|
<property name="author" value="Adrian" />
|
||||||
|
<property name="attachment" value="screenshots/dashboard.png" />
|
||||||
|
<property name="attachment" value="screenshots/users.png" />
|
||||||
|
<property name="description">
|
||||||
|
This text describes the purpose of this test case and provides
|
||||||
|
an overview of what the test does and how it works.
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
28
__tests__/fixtures/external/phpunit/junit-basic.xml
vendored
Normal file
28
__tests__/fixtures/external/phpunit/junit-basic.xml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
This is a basic JUnit-style XML example to highlight the basis structure.
|
||||||
|
|
||||||
|
Example by Testmo. Copyright 2023 Testmo GmbH. All rights reserved.
|
||||||
|
Testmo test management software - https://www.testmo.com/
|
||||||
|
-->
|
||||||
|
<testsuites time="15.682687">
|
||||||
|
<testsuite name="Tests.Registration" time="6.605871">
|
||||||
|
<testcase name="testCase1" classname="Tests.Registration" time="2.113871" />
|
||||||
|
<testcase name="testCase2" classname="Tests.Registration" time="1.051" />
|
||||||
|
<testcase name="testCase3" classname="Tests.Registration" time="3.441" />
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="Tests.Authentication" time="9.076816">
|
||||||
|
<testsuite name="Tests.Authentication.Login" time="4.356">
|
||||||
|
<testcase name="testCase4" classname="Tests.Authentication.Login" time="2.244" />
|
||||||
|
<testcase name="testCase5" classname="Tests.Authentication.Login" time="0.781" />
|
||||||
|
<testcase name="testCase6" classname="Tests.Authentication.Login" time="1.331" />
|
||||||
|
</testsuite>
|
||||||
|
<testcase name="testCase7" classname="Tests.Authentication" time="2.508" />
|
||||||
|
<testcase name="testCase8" classname="Tests.Authentication" time="1.230816" />
|
||||||
|
<testcase name="testCase9" classname="Tests.Authentication" time="0.982">
|
||||||
|
<failure message="Assertion error message" type="AssertionError">
|
||||||
|
<!-- Call stack printed here -->
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
212
__tests__/fixtures/external/phpunit/phpcheckstyle-phpunit.xml
vendored
Normal file
212
__tests__/fixtures/external/phpunit/phpcheckstyle-phpunit.xml
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="/workspace/phpcheckstyle/phpunit.xml" tests="30" assertions="117" errors="0" failures="2" skipped="0" time="0.041478">
|
||||||
|
<testsuite name="PHPUnitTestSuite" tests="30" assertions="117" errors="0" failures="2" skipped="0" time="0.041478">
|
||||||
|
<testsuite name="CommentsTest" file="/workspace/phpcheckstyle/test/CommentsTest.php" tests="3" assertions="12" errors="0" failures="0" skipped="0" time="0.006702">
|
||||||
|
<testcase name="testGoodDoc" file="/workspace/phpcheckstyle/test/CommentsTest.php" line="12" class="CommentsTest" classname="CommentsTest" assertions="4" time="0.005093"/>
|
||||||
|
<testcase name="testComments" file="/workspace/phpcheckstyle/test/CommentsTest.php" line="30" class="CommentsTest" classname="CommentsTest" assertions="4" time="0.000921">
|
||||||
|
<system-out>File "./test/sample/bad_comments.php" warning, line 4 - Avoid Shell/Perl like comments.
|
||||||
|
File "./test/sample/bad_comments.php" warning, line 6 - The class Comments must have a docblock comment.
|
||||||
|
File "./test/sample/bad_comments.php" warning, line 10 - The function testComment must have a docblock comment.
|
||||||
|
File "./test/sample/bad_comments.php" warning, line 18 - The function testComment returns a value and must include @returns in its docblock.
|
||||||
|
File "./test/sample/bad_comments.php" warning, line 18 - The function testComment parameters must match those in its docblock @param.
|
||||||
|
File "./test/sample/bad_comments.php" warning, line 18 - The function testComment throws an exception and must include @throws in its docblock.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testTODOs" file="/workspace/phpcheckstyle/test/CommentsTest.php" line="48" class="CommentsTest" classname="CommentsTest" assertions="4" time="0.000688">
|
||||||
|
<system-out>File "./test/sample/todo.php" warning, line 3 - TODO: The todo message.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="DeprecationTest" file="/workspace/phpcheckstyle/test/DeprecationTest.php" tests="1" assertions="4" errors="0" failures="0" skipped="0" time="0.000974">
|
||||||
|
<testcase name="testDeprecations" file="/workspace/phpcheckstyle/test/DeprecationTest.php" line="12" class="DeprecationTest" classname="DeprecationTest" assertions="4" time="0.000974">
|
||||||
|
<system-out>File "./test/sample/bad_deprecation.php" warning, line 17 - split is deprecated since PHP 5.3. explode($pattern, $string) or preg_split('@'.$pattern.'@', $string) must be used instead.
|
||||||
|
File "./test/sample/bad_deprecation.php" warning, line 19 - ereg is deprecated since PHP 5.3. preg_match('@'.$pattern.'@', $string) must be used instead.
|
||||||
|
File "./test/sample/bad_deprecation.php" warning, line 21 - session_register is deprecated since PHP 5.3. $_SESSION must be used instead.
|
||||||
|
File "./test/sample/bad_deprecation.php" warning, line 23 - mysql_db_query is deprecated since PHP 5.3. mysql_select_db and mysql_query must be used instead.
|
||||||
|
File "./test/sample/bad_deprecation.php" warning, line 25 - $HTTP_GET_VARS is deprecated since PHP 5.3. $_GET must be used instead.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="GoodTest" file="/workspace/phpcheckstyle/test/GoodTest.php" tests="4" assertions="16" errors="0" failures="0" skipped="0" time="0.005357">
|
||||||
|
<testcase name="testGood" file="/workspace/phpcheckstyle/test/GoodTest.php" line="12" class="GoodTest" classname="GoodTest" assertions="4" time="0.002647"/>
|
||||||
|
<testcase name="testDoWhile" file="/workspace/phpcheckstyle/test/GoodTest.php" line="32" class="GoodTest" classname="GoodTest" assertions="4" time="0.001022"/>
|
||||||
|
<testcase name="testAnonymousFunction" file="/workspace/phpcheckstyle/test/GoodTest.php" line="50" class="GoodTest" classname="GoodTest" assertions="4" time="0.000800"/>
|
||||||
|
<testcase name="testException" file="/workspace/phpcheckstyle/test/GoodTest.php" line="68" class="GoodTest" classname="GoodTest" assertions="4" time="0.000888"/>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="IndentationTest" file="/workspace/phpcheckstyle/test/IndentationTest.php" tests="8" assertions="32" errors="0" failures="0" skipped="0" time="0.007654">
|
||||||
|
<testcase name="testTabIndentation" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="12" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.000857">
|
||||||
|
<system-out>File "./test/sample/bad_indentation.php" warning, line 8 - Whitespace indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 15 - Whitespace indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 17 - Whitespace indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 18 - Whitespace indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 19 - Whitespace indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 20 - Whitespace indentation must not be used.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testSpaceIndentation" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="30" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.000929">
|
||||||
|
<system-out>File "./test/sample/bad_indentation.php" warning, line 10 - Tab indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 10 - The indentation level must be 4 but was 1.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 13 - Tab indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 13 - The indentation level must be 4 but was 1.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 15 - The indentation level must be 8 but was 4.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 16 - Tab indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 16 - The indentation level must be 8 but was 1.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 17 - The indentation level must be 8 but was 3.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 18 - The indentation level must be 8 but was 5.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 19 - The indentation level must be 8 but was 6.
|
||||||
|
File "./test/sample/bad_indentation.php" warning, line 20 - The indentation level must be 4 but was 1.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testSpaceIndentationArray" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="51" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.000975">
|
||||||
|
<system-out>File "./test/sample/bad_indentation_array.php" warning, line 10 - Tab indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 10 - The indentation level must be 4 but was 1.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 13 - Tab indentation must not be used.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 13 - The indentation level must be 4 but was 1.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 16 - The indentation level must be 12 but was 8.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 24 - The indentation level must be 12 but was 8.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 29 - The indentation level must be 8 but was 12.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 15 - Undeclared or unused variable: $aVar.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 19 - Undeclared or unused variable: $bVar.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 23 - Undeclared or unused variable: $cVar.
|
||||||
|
File "./test/sample/bad_indentation_array.php" warning, line 27 - Undeclared or unused variable: $dVar.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testGoodSpaceIndentationArray" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="72" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.001212"/>
|
||||||
|
<testcase name="testGoodIndentationNewLine" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="93" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.000859"/>
|
||||||
|
<testcase name="testGoodIndentationSpaces" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="116" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.000780"/>
|
||||||
|
<testcase name="testBadSpaces" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="137" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.001120">
|
||||||
|
<system-out>File "./test/sample/bad_spaces.php" warning, line 17 - Whitespace must follow ,.
|
||||||
|
File "./test/sample/bad_spaces.php" warning, line 17 - Whitespace must precede {.
|
||||||
|
File "./test/sample/bad_spaces.php" warning, line 19 - Whitespace must follow if.
|
||||||
|
File "./test/sample/bad_spaces.php" warning, line 23 - Whitespace must precede =.
|
||||||
|
File "./test/sample/bad_spaces.php" warning, line 23 - Whitespace must follow =.
|
||||||
|
File "./test/sample/bad_spaces.php" warning, line 23 - Whitespace must precede +.
|
||||||
|
File "./test/sample/bad_spaces.php" warning, line 23 - Whitespace must follow +.
|
||||||
|
File "./test/sample/bad_spaces.php" info, line 25 - Whitespace must not precede ,.
|
||||||
|
File "./test/sample/bad_spaces.php" info, line 26 - Whitespace must not follow !.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testBadSpaceAfterControl" file="/workspace/phpcheckstyle/test/IndentationTest.php" line="155" class="IndentationTest" classname="IndentationTest" assertions="4" time="0.000922">
|
||||||
|
<system-out>File "./test/sample/bad_space_after_control.php" warning, line 19 - Whitespace must not follow if.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="MetricsTest" file="/workspace/phpcheckstyle/test/MetricsTest.php" tests="1" assertions="4" errors="0" failures="0" skipped="0" time="0.004147">
|
||||||
|
<testcase name="testMetrics" file="/workspace/phpcheckstyle/test/MetricsTest.php" line="12" class="MetricsTest" classname="MetricsTest" assertions="4" time="0.004147">
|
||||||
|
<system-out>File "./test/sample/bad_metrics.php" warning, line 21 - The function testMetrics's number of parameters (6) must not exceed 4.
|
||||||
|
File "./test/sample/bad_metrics.php" info, line 55 - Line is too long. [233/160]
|
||||||
|
File "./test/sample/bad_metrics.php" warning, line 21 - The Cyclomatic Complexity of function testMetrics is too high. [15/10]
|
||||||
|
File "./test/sample/bad_metrics.php" warning, line 244 - The testMetrics function body length is too long. [223/200]
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="NamingTest" file="/workspace/phpcheckstyle/test/NamingTest.php" tests="2" assertions="8" errors="0" failures="0" skipped="0" time="0.002697">
|
||||||
|
<testcase name="testNaming" file="/workspace/phpcheckstyle/test/NamingTest.php" line="12" class="NamingTest" classname="NamingTest" assertions="4" time="0.001426">
|
||||||
|
<system-out>File "./test/sample/_bad_naming.php" error, line 11 - Constant _badly_named_constant name should follow the pattern /^[A-Z][A-Z0-9_]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 13 - Constant bad_CONST name should follow the pattern /^[A-Z][A-Z0-9_]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" warning, line 17 - Top level variable $XXX name should follow the pattern /^[a-z_][a-zA-Z0-9]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" warning, line 20 - Variable x name length is too short.
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 28 - Class badlynamedclass name should follow the pattern /^[A-Z][a-zA-Z0-9_]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" warning, line 32 - Member variable $YYY name should follow the pattern /^[a-z_][a-zA-Z0-9]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" warning, line 37 - The constructor name must be __construct().
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 44 - Function Badlynamedfunction name should follow the pattern /^[a-z][a-zA-Z0-9]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" warning, line 47 - Local variable $ZZZ name should follow the pattern /^[a-z_][a-zA-Z0-9]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 54 - Protected function Badlynamedfunction2 name should follow the pattern /^[a-z][a-zA-Z0-9]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 61 - Private function badlynamedfunction3 name should follow the pattern /^_[a-z][a-zA-Z0-9]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 70 - Interface _badlynamedinterface name should follow the pattern /^[A-Z][a-zA-Z0-9_]*$/.
|
||||||
|
File "./test/sample/_bad_naming.php" error, line 75 - File _bad_naming.php name should follow the pattern /^[a-zA-Z][a-zA-Z0-9._]*$/.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testFunctionNaming" file="/workspace/phpcheckstyle/test/NamingTest.php" line="32" class="NamingTest" classname="NamingTest" assertions="4" time="0.001271"/>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="OptimizationTest" file="/workspace/phpcheckstyle/test/OptimizationTest.php" tests="1" assertions="4" errors="0" failures="0" skipped="0" time="0.000994">
|
||||||
|
<testcase name="testTextAfterClosingTag" file="/workspace/phpcheckstyle/test/OptimizationTest.php" line="12" class="OptimizationTest" classname="OptimizationTest" assertions="4" time="0.000994">
|
||||||
|
<system-out>File "./test/sample/bad_optimisation.php" warning, line 18 - count function must not be used inside a loop.
|
||||||
|
File "./test/sample/bad_optimisation.php" warning, line 23 - count function must not be used inside a loop.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="OtherTest" file="/workspace/phpcheckstyle/test/OtherTest.php" tests="4" assertions="13" errors="0" failures="2" skipped="0" time="0.007329">
|
||||||
|
<testcase name="testOther" file="/workspace/phpcheckstyle/test/OtherTest.php" line="12" class="OtherTest" classname="OtherTest" assertions="4" time="0.005251">
|
||||||
|
<failure type="PHPUnit\Framework\ExpectationFailedException">OtherTest::testOther
|
||||||
|
We expect 20 warnings
|
||||||
|
Failed asserting that 19 matches expected 20.
|
||||||
|
|
||||||
|
/workspace/phpcheckstyle/test/OtherTest.php:24</failure>
|
||||||
|
<system-out>File "./test/sample/bad_other.php" warning, line 17 - All arguments with default values must be at the end of the block or statement.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 21 - Errors must not be silenced when calling a function.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 23 - Prefer single-quoted strings when you don't need string interpolation.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 23 - Encapsed variables must not be used inside a string.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 23 - Encapsed variables must not be used inside a string.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 23 - Prefer single-quoted strings when you don't need string interpolation.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 37 - TODO: Show todos
|
||||||
|
File "./test/sample/bad_other.php" warning, line 40 - Avoid empty statements (;;).
|
||||||
|
File "./test/sample/bad_other.php" warning, line 42 - Boolean operators (&&) must be used instead of logical operators (AND).
|
||||||
|
File "./test/sample/bad_other.php" warning, line 42 - Empty if block.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 48 - Heredoc syntax must not be used.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 52 - The statement if must contain its code within a {} block.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 54 - Consider using a strict comparison operator instead of ==.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 54 - The statement while must contain its code within a {} block.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 66 - The switch statement must have a default case.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 79 - The default case of a switch statement must be located after all other cases.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 93 - Unary operators (++ or --) must not be used inside a control statement
|
||||||
|
File "./test/sample/bad_other.php" warning, line 95 - Assigments (=) must not be used inside a control statement.
|
||||||
|
File "./test/sample/bad_other.php" warning, line 106 - File ./test/sample/bad_other.php must not have multiple class declarations.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testException" file="/workspace/phpcheckstyle/test/OtherTest.php" line="31" class="OtherTest" classname="OtherTest" assertions="1" time="0.000751">
|
||||||
|
<failure type="PHPUnit\Framework\ExpectationFailedException">OtherTest::testException
|
||||||
|
We expect 1 error
|
||||||
|
Failed asserting that 0 matches expected 1.
|
||||||
|
|
||||||
|
/workspace/phpcheckstyle/test/OtherTest.php:40</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testEmpty" file="/workspace/phpcheckstyle/test/OtherTest.php" line="50" class="OtherTest" classname="OtherTest" assertions="4" time="0.000427">
|
||||||
|
<system-out>File "./test/sample/empty.php" warning, line 1 - The file ./test/sample/empty.php is empty.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testSwitchCaseNeedBreak" file="/workspace/phpcheckstyle/test/OtherTest.php" line="69" class="OtherTest" classname="OtherTest" assertions="4" time="0.000901">
|
||||||
|
<system-out>File "./test/sample/switch_multi_case.php" warning, line 10 - The case statement must contain a break.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="PHPTagsTest" file="/workspace/phpcheckstyle/test/PHPTagsTest.php" tests="2" assertions="8" errors="0" failures="0" skipped="0" time="0.001272">
|
||||||
|
<testcase name="testTextAfterClosingTag" file="/workspace/phpcheckstyle/test/PHPTagsTest.php" line="12" class="PHPTagsTest" classname="PHPTagsTest" assertions="4" time="0.000641">
|
||||||
|
<system-out>File "./test/sample/bad_php_tags_text_after_end.php" warning, line 9 - A PHP close tag must not be included at the end of the file.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testClosingTagNotNeeded" file="/workspace/phpcheckstyle/test/PHPTagsTest.php" line="30" class="PHPTagsTest" classname="PHPTagsTest" assertions="4" time="0.000631">
|
||||||
|
<system-out>File "./test/sample/bad_php_tags_end_not_needed.php" warning, line 1 - PHP tag should be at the beginning of the line.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="ProhibitedTest" file="/workspace/phpcheckstyle/test/ProhibitedTest.php" tests="1" assertions="4" errors="0" failures="0" skipped="0" time="0.000938">
|
||||||
|
<testcase name="testProhibited" file="/workspace/phpcheckstyle/test/ProhibitedTest.php" line="13" class="ProhibitedTest" classname="ProhibitedTest" assertions="4" time="0.000938">
|
||||||
|
<system-out>File "./test/sample/bad_prohibited.php" warning, line 18 - The function exec must not be called.
|
||||||
|
File "./test/sample/bad_prohibited.php" warning, line 20 - Token T_PRINT must not be used.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="StrictCompareTest" file="/workspace/phpcheckstyle/test/StrictCompareTest.php" tests="1" assertions="4" errors="0" failures="0" skipped="0" time="0.001578">
|
||||||
|
<testcase name="testStrictCompare" file="/workspace/phpcheckstyle/test/StrictCompareTest.php" line="12" class="StrictCompareTest" classname="StrictCompareTest" assertions="4" time="0.001578">
|
||||||
|
<system-out>File "./test/sample/bad_strictcompare.php" warning, line 14 - Consider using a strict comparison operator instead of ==.
|
||||||
|
File "./test/sample/bad_strictcompare.php" warning, line 19 - Consider using a strict comparison operator instead of !=.
|
||||||
|
File "./test/sample/bad_strictcompare.php" warning, line 24 - Consider using a strict comparison operator instead of ==.
|
||||||
|
File "./test/sample/bad_strictcompare.php" warning, line 29 - Consider using a strict comparison operator instead of ==.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="UnusedTest" file="/workspace/phpcheckstyle/test/UnusedTest.php" tests="2" assertions="8" errors="0" failures="0" skipped="0" time="0.001835">
|
||||||
|
<testcase name="testGoodUnused" file="/workspace/phpcheckstyle/test/UnusedTest.php" line="13" class="UnusedTest" classname="UnusedTest" assertions="4" time="0.000940"/>
|
||||||
|
<testcase name="testBadUnused" file="/workspace/phpcheckstyle/test/UnusedTest.php" line="32" class="UnusedTest" classname="UnusedTest" assertions="4" time="0.000895">
|
||||||
|
<system-out>File "./test/sample/bad_unused.php" warning, line 23 - Function _testUnused has unused code after RETURN.
|
||||||
|
File "./test/sample/bad_unused.php" warning, line 27 - The function _testUnused parameter $b is not used.
|
||||||
|
File "./test/sample/bad_unused.php" warning, line 18 - Unused private function: _testUnused.
|
||||||
|
File "./test/sample/bad_unused.php" warning, line 20 - Undeclared or unused variable: $c.
|
||||||
|
</system-out>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuite>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
23
__tests__/fixtures/phpunit/phpunit-paths.xml
Normal file
23
__tests__/fixtures/phpunit/phpunit-paths.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="SampleSuite" tests="6" failures="6" time="0.006">
|
||||||
|
<testcase name="testFailure" classname="SampleSuite" file="/home/runner/work/repo/src/Fake.php" line="42" time="0.001">
|
||||||
|
<failure type="Exception" message="Boom">/home/runner/work/repo/src/Fake.php:42</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testStringFailure" classname="SampleSuite" file="/home/runner/work/repo/src/Other.php" line="10" time="0.001">
|
||||||
|
<failure>/home/runner/work/repo/src/Other.php:10</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testParenFailure" classname="SampleSuite" file="/home/runner/work/repo/src/Paren.php" line="123" time="0.001">
|
||||||
|
<failure>at /home/runner/work/repo/src/Paren.php(123)</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testWindowsFailure" classname="SampleSuite" file="C:\repo\src\Win.php" line="77" time="0.001">
|
||||||
|
<failure>C:\repo\src\Win.php:77</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testWindowsParenFailure" classname="SampleSuite" file="C:\repo\src\WinParen.php" line="88" time="0.001">
|
||||||
|
<failure>at C:\repo\src\WinParen.php(88)</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="testPhptFailure" classname="SampleSuite" file="/home/runner/work/repo/tests/Sample.phpt" line="12" time="0.001">
|
||||||
|
<failure>/home/runner/work/repo/tests/Sample.phpt:12</failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
79
__tests__/fixtures/phpunit/phpunit.xml
Normal file
79
__tests__/fixtures/phpunit/phpunit.xml
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="CLI Arguments" tests="12" assertions="12" errors="0" failures="2" skipped="0" time="0.140397">
|
||||||
|
<testcase name="targeting-traits-with-coversclass-attribute-is-deprecated.phpt" file="/home/matteo/OSS/phpunit/tests/end-to-end/metadata/targeting-traits-with-coversclass-attribute-is-deprecated.phpt" assertions="1" time="0.068151">
|
||||||
|
<failure type="PHPUnit\Framework\PhptAssertionFailedError">targeting-traits-with-coversclass-attribute-is-deprecated.phptFailed asserting that string matches format description.
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ @@
|
||||||
|
PHPUnit Started (PHPUnit 11.2-g0c2333363 using PHP 8.2.17 (cli) on Linux)
|
||||||
|
Test Runner Configured
|
||||||
|
Test Suite Loaded (1 test)
|
||||||
|
+Test Runner Triggered Warning (No code coverage driver available)
|
||||||
|
Event Facade Sealed
|
||||||
|
Test Runner Started
|
||||||
|
Test Suite Sorted
|
||||||
|
@@ @@
|
||||||
|
Test Preparation Started (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
Test Prepared (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
Test Passed (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
-Test Runner Triggered Deprecation (Targeting a trait such as PHPUnit\TestFixture\CoveredTrait with #[CoversClass] is deprecated, please refactor your test to use #[CoversTrait] instead.)
|
||||||
|
Test Finished (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithCoversClassTest::testSomething)
|
||||||
|
Test Suite Finished (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithCoversClassTest, 1 test)
|
||||||
|
Test Runner Execution Finished
|
||||||
|
Test Runner Finished
|
||||||
|
-PHPUnit Finished (Shell Exit Code: 0)
|
||||||
|
+PHPUnit Finished (Shell Exit Code: 1)
|
||||||
|
|
||||||
|
/home/matteo/OSS/phpunit/tests/end-to-end/metadata/targeting-traits-with-coversclass-attribute-is-deprecated.phpt:28
|
||||||
|
/home/matteo/OSS/phpunit/src/Framework/TestSuite.php:369
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/TestRunner.php:62
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/Application.php:200</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="targeting-traits-with-usesclass-attribute-is-deprecated.phpt" file="/home/matteo/OSS/phpunit/tests/end-to-end/metadata/targeting-traits-with-usesclass-attribute-is-deprecated.phpt" assertions="1" time="0.064268">
|
||||||
|
<failure type="PHPUnit\Framework\PhptAssertionFailedError">targeting-traits-with-usesclass-attribute-is-deprecated.phptFailed asserting that string matches format description.
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ @@
|
||||||
|
PHPUnit Started (PHPUnit 11.2-g0c2333363 using PHP 8.2.17 (cli) on Linux)
|
||||||
|
Test Runner Configured
|
||||||
|
Test Suite Loaded (1 test)
|
||||||
|
+Test Runner Triggered Warning (No code coverage driver available)
|
||||||
|
Event Facade Sealed
|
||||||
|
Test Runner Started
|
||||||
|
Test Suite Sorted
|
||||||
|
@@ @@
|
||||||
|
Test Preparation Started (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
Test Prepared (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
Test Passed (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
-Test Runner Triggered Deprecation (Targeting a trait such as PHPUnit\TestFixture\CoveredTrait with #[UsesClass] is deprecated, please refactor your test to use #[UsesTrait] instead.)
|
||||||
|
Test Finished (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithUsesClassTest::testSomething)
|
||||||
|
Test Suite Finished (PHPUnit\DeprecatedAnnotationsTestFixture\TraitTargetedWithUsesClassTest, 1 test)
|
||||||
|
Test Runner Execution Finished
|
||||||
|
Test Runner Finished
|
||||||
|
-PHPUnit Finished (Shell Exit Code: 0)
|
||||||
|
+PHPUnit Finished (Shell Exit Code: 1)
|
||||||
|
|
||||||
|
/home/matteo/OSS/phpunit/tests/end-to-end/metadata/targeting-traits-with-usesclass-attribute-is-deprecated.phpt:28
|
||||||
|
/home/matteo/OSS/phpunit/src/Framework/TestSuite.php:369
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/TestRunner.php:62
|
||||||
|
/home/matteo/OSS/phpunit/src/TextUI/Application.php:200</failure>
|
||||||
|
</testcase>
|
||||||
|
<testsuite name="PHPUnit\Event\CollectingDispatcherTest" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/CollectingDispatcherTest.php" tests="2" assertions="2" errors="0" failures="0" skipped="0" time="0.004256">
|
||||||
|
<testcase name="testHasNoCollectedEventsWhenFlushedImmediatelyAfterCreation" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/CollectingDispatcherTest.php" line="20" class="PHPUnit\Event\CollectingDispatcherTest" classname="PHPUnit.Event.CollectingDispatcherTest" assertions="1" time="0.001441"/>
|
||||||
|
<testcase name="testCollectsDispatchedEventsUntilFlushed" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/CollectingDispatcherTest.php" line="27" class="PHPUnit\Event\CollectingDispatcherTest" classname="PHPUnit.Event.CollectingDispatcherTest" assertions="1" time="0.002815"/>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="PHPUnit\Event\DeferringDispatcherTest" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DeferringDispatcherTest.php" tests="4" assertions="4" errors="0" failures="0" skipped="0" time="0.002928">
|
||||||
|
<testcase name="testCollectsEventsUntilFlush" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DeferringDispatcherTest.php" line="22" class="PHPUnit\Event\DeferringDispatcherTest" classname="PHPUnit.Event.DeferringDispatcherTest" assertions="1" time="0.001672"/>
|
||||||
|
<testcase name="testFlushesCollectedEvents" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DeferringDispatcherTest.php" line="35" class="PHPUnit\Event\DeferringDispatcherTest" classname="PHPUnit.Event.DeferringDispatcherTest" assertions="1" time="0.000661"/>
|
||||||
|
<testcase name="testSubscriberCanBeRegistered" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DeferringDispatcherTest.php" line="53" class="PHPUnit\Event\DeferringDispatcherTest" classname="PHPUnit.Event.DeferringDispatcherTest" assertions="1" time="0.000334"/>
|
||||||
|
<testcase name="testTracerCanBeRegistered" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DeferringDispatcherTest.php" line="69" class="PHPUnit\Event\DeferringDispatcherTest" classname="PHPUnit.Event.DeferringDispatcherTest" assertions="1" time="0.000262"/>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="PHPUnit\Event\DirectDispatcherTest" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DirectDispatcherTest.php" tests="4" assertions="4" errors="0" failures="0" skipped="0" time="0.000794">
|
||||||
|
<testcase name="testDispatchesEventToKnownSubscribers" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DirectDispatcherTest.php" line="24" class="PHPUnit\Event\DirectDispatcherTest" classname="PHPUnit.Event.DirectDispatcherTest" assertions="1" time="0.000170"/>
|
||||||
|
<testcase name="testDispatchesEventToTracers" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DirectDispatcherTest.php" line="43" class="PHPUnit\Event\DirectDispatcherTest" classname="PHPUnit.Event.DirectDispatcherTest" assertions="1" time="0.000248"/>
|
||||||
|
<testcase name="testRegisterRejectsUnknownSubscriber" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DirectDispatcherTest.php" line="62" class="PHPUnit\Event\DirectDispatcherTest" classname="PHPUnit.Event.DirectDispatcherTest" assertions="1" time="0.000257"/>
|
||||||
|
<testcase name="testDispatchRejectsUnknownEventType" file="/home/matteo/OSS/phpunit/tests/unit/Event/Dispatcher/DirectDispatcherTest.php" line="73" class="PHPUnit\Event\DirectDispatcherTest" classname="PHPUnit.Event.DirectDispatcherTest" assertions="1" time="0.000119"/>
|
||||||
|
</testsuite>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
@@ -73,6 +73,46 @@ describe('java-junit tests', () => {
|
|||||||
fs.writeFileSync(outputPath, report)
|
fs.writeFileSync(outputPath, report)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('report from testmo/junitxml basic example matches snapshot', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'java', 'junit4-basic.xml')
|
||||||
|
const outputPath = path.join(__dirname, '__outputs__', 'junit-basic.md')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new JavaJunitParser(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('report from testmo/junitxml complete example matches snapshot', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'java', 'junit4-complete.xml')
|
||||||
|
const outputPath = path.join(__dirname, '__outputs__', 'junit-complete.md')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new JavaJunitParser(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 empty failures in test results', async () => {
|
it('parses empty failures in test results', async () => {
|
||||||
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'java', 'empty_failures.xml')
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'java', 'empty_failures.xml')
|
||||||
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
|||||||
347
__tests__/phpunit-junit.test.ts
Normal file
347
__tests__/phpunit-junit.test.ts
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
import {PhpunitJunitParser} from '../src/parsers/phpunit-junit/phpunit-junit-parser'
|
||||||
|
import {ParseOptions} from '../src/test-parser'
|
||||||
|
import {getReport} from '../src/report/get-report'
|
||||||
|
import {normalizeFilePath} from '../src/utils/path-utils'
|
||||||
|
|
||||||
|
describe('phpunit-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 PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
expect(result.tests).toBe(0)
|
||||||
|
expect(result.result).toBe('success')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('report from phpunit test results matches snapshot', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'phpunit', 'phpunit.xml')
|
||||||
|
const outputPath = path.join(__dirname, '__outputs__', 'phpunit-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 PhpunitJunitParser(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 nested test suites correctly', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'phpunit', 'phpunit.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
// Should have 4 test suites (3 nested ones plus the parent with direct testcases)
|
||||||
|
expect(result.suites.length).toBe(4)
|
||||||
|
|
||||||
|
// Verify suite names
|
||||||
|
const suiteNames = result.suites.map(s => s.name)
|
||||||
|
expect(suiteNames).toContain('PHPUnit\\Event\\CollectingDispatcherTest')
|
||||||
|
expect(suiteNames).toContain('PHPUnit\\Event\\DeferringDispatcherTest')
|
||||||
|
expect(suiteNames).toContain('PHPUnit\\Event\\DirectDispatcherTest')
|
||||||
|
expect(suiteNames).toContain('CLI Arguments')
|
||||||
|
|
||||||
|
// Verify total test count
|
||||||
|
expect(result.tests).toBe(12)
|
||||||
|
expect(result.passed).toBe(10)
|
||||||
|
expect(result.failed).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('extracts error details from failures', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'phpunit', 'phpunit.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
// Find the CLI Arguments suite which has failures
|
||||||
|
const cliSuite = result.suites.find(s => s.name === 'CLI Arguments')
|
||||||
|
expect(cliSuite).toBeDefined()
|
||||||
|
|
||||||
|
// Get the failed tests
|
||||||
|
const failedTests = cliSuite!.groups.flatMap(g => g.tests).filter(t => t.result === 'failed')
|
||||||
|
expect(failedTests.length).toBe(2)
|
||||||
|
|
||||||
|
// Verify error details are captured
|
||||||
|
for (const test of failedTests) {
|
||||||
|
expect(test.error).toBeDefined()
|
||||||
|
expect(test.error!.details).toContain('Failed asserting that string matches format description')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('maps absolute paths to tracked files for annotations', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'phpunit', 'phpunit-paths.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: [
|
||||||
|
'src/Fake.php',
|
||||||
|
'src/Other.php',
|
||||||
|
'src/Paren.php',
|
||||||
|
'src/Win.php',
|
||||||
|
'src/WinParen.php',
|
||||||
|
'tests/Sample.phpt'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
const suite = result.suites.find(s => s.name === 'SampleSuite')
|
||||||
|
expect(suite).toBeDefined()
|
||||||
|
|
||||||
|
const tests = suite!.groups.flatMap(g => g.tests)
|
||||||
|
const fileFailure = tests.find(t => t.name === 'testFailure')
|
||||||
|
expect(fileFailure).toBeDefined()
|
||||||
|
expect(fileFailure!.error).toBeDefined()
|
||||||
|
expect(fileFailure!.error!.path).toBe('src/Fake.php')
|
||||||
|
expect(fileFailure!.error!.line).toBe(42)
|
||||||
|
|
||||||
|
const stringFailure = tests.find(t => t.name === 'testStringFailure')
|
||||||
|
expect(stringFailure).toBeDefined()
|
||||||
|
expect(stringFailure!.error).toBeDefined()
|
||||||
|
expect(stringFailure!.error!.path).toBe('src/Other.php')
|
||||||
|
expect(stringFailure!.error!.line).toBe(10)
|
||||||
|
|
||||||
|
const parenFailure = tests.find(t => t.name === 'testParenFailure')
|
||||||
|
expect(parenFailure).toBeDefined()
|
||||||
|
expect(parenFailure!.error).toBeDefined()
|
||||||
|
expect(parenFailure!.error!.path).toBe('src/Paren.php')
|
||||||
|
expect(parenFailure!.error!.line).toBe(123)
|
||||||
|
|
||||||
|
const windowsFailure = tests.find(t => t.name === 'testWindowsFailure')
|
||||||
|
expect(windowsFailure).toBeDefined()
|
||||||
|
expect(windowsFailure!.error).toBeDefined()
|
||||||
|
expect(windowsFailure!.error!.path).toBe('src/Win.php')
|
||||||
|
expect(windowsFailure!.error!.line).toBe(77)
|
||||||
|
|
||||||
|
const windowsParenFailure = tests.find(t => t.name === 'testWindowsParenFailure')
|
||||||
|
expect(windowsParenFailure).toBeDefined()
|
||||||
|
expect(windowsParenFailure!.error).toBeDefined()
|
||||||
|
expect(windowsParenFailure!.error!.path).toBe('src/WinParen.php')
|
||||||
|
expect(windowsParenFailure!.error!.line).toBe(88)
|
||||||
|
|
||||||
|
const phptFailure = tests.find(t => t.name === 'testPhptFailure')
|
||||||
|
expect(phptFailure).toBeDefined()
|
||||||
|
expect(phptFailure!.error).toBeDefined()
|
||||||
|
expect(phptFailure!.error!.path).toBe('tests/Sample.phpt')
|
||||||
|
expect(phptFailure!.error!.line).toBe(12)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('parses junit-basic.xml with nested suites and failure', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'phpunit', 'junit-basic.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
// Verify test counts
|
||||||
|
expect(result.tests).toBe(9)
|
||||||
|
expect(result.passed).toBe(8)
|
||||||
|
expect(result.failed).toBe(1)
|
||||||
|
expect(result.result).toBe('failed')
|
||||||
|
|
||||||
|
// Verify suites - should have Tests.Registration, Tests.Authentication.Login, and Tests.Authentication
|
||||||
|
expect(result.suites.length).toBe(3)
|
||||||
|
|
||||||
|
const suiteNames = result.suites.map(s => s.name)
|
||||||
|
expect(suiteNames).toContain('Tests.Registration')
|
||||||
|
expect(suiteNames).toContain('Tests.Authentication.Login')
|
||||||
|
expect(suiteNames).toContain('Tests.Authentication')
|
||||||
|
|
||||||
|
// Verify the Registration suite has 3 tests
|
||||||
|
const registrationSuite = result.suites.find(s => s.name === 'Tests.Registration')
|
||||||
|
expect(registrationSuite).toBeDefined()
|
||||||
|
const registrationTests = registrationSuite!.groups.flatMap(g => g.tests)
|
||||||
|
expect(registrationTests.length).toBe(3)
|
||||||
|
|
||||||
|
// Verify the Authentication suite has 3 direct tests (not counting nested suite)
|
||||||
|
const authSuite = result.suites.find(s => s.name === 'Tests.Authentication')
|
||||||
|
expect(authSuite).toBeDefined()
|
||||||
|
const authTests = authSuite!.groups.flatMap(g => g.tests)
|
||||||
|
expect(authTests.length).toBe(3)
|
||||||
|
|
||||||
|
// Verify the Login nested suite has 3 tests
|
||||||
|
const loginSuite = result.suites.find(s => s.name === 'Tests.Authentication.Login')
|
||||||
|
expect(loginSuite).toBeDefined()
|
||||||
|
const loginTests = loginSuite!.groups.flatMap(g => g.tests)
|
||||||
|
expect(loginTests.length).toBe(3)
|
||||||
|
|
||||||
|
// Verify failure is captured
|
||||||
|
const failedTest = authTests.find(t => t.name === 'testCase9')
|
||||||
|
expect(failedTest).toBeDefined()
|
||||||
|
expect(failedTest!.result).toBe('failed')
|
||||||
|
expect(failedTest!.error).toBeDefined()
|
||||||
|
expect(failedTest!.error!.message).toBe('AssertionError: Assertion error message')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('parses phpcheckstyle-phpunit.xml with deeply nested suites', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'phpunit', 'phpcheckstyle-phpunit.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
// Verify test counts from the XML: tests="30", failures="2"
|
||||||
|
expect(result.tests).toBe(30)
|
||||||
|
expect(result.passed).toBe(28)
|
||||||
|
expect(result.failed).toBe(2)
|
||||||
|
expect(result.result).toBe('failed')
|
||||||
|
|
||||||
|
// Verify the number of test suites extracted (leaf suites with testcases)
|
||||||
|
// CommentsTest, DeprecationTest, GoodTest, IndentationTest, MetricsTest,
|
||||||
|
// NamingTest, OptimizationTest, OtherTest, PHPTagsTest, ProhibitedTest,
|
||||||
|
// StrictCompareTest, UnusedTest = 12 suites
|
||||||
|
expect(result.suites.length).toBe(12)
|
||||||
|
|
||||||
|
const suiteNames = result.suites.map(s => s.name)
|
||||||
|
expect(suiteNames).toContain('CommentsTest')
|
||||||
|
expect(suiteNames).toContain('GoodTest')
|
||||||
|
expect(suiteNames).toContain('IndentationTest')
|
||||||
|
expect(suiteNames).toContain('OtherTest')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('extracts test data from phpcheckstyle-phpunit.xml', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'phpunit', 'phpcheckstyle-phpunit.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
// Find the CommentsTest suite
|
||||||
|
const commentsSuite = result.suites.find(s => s.name === 'CommentsTest')
|
||||||
|
expect(commentsSuite).toBeDefined()
|
||||||
|
|
||||||
|
// Verify tests are extracted correctly
|
||||||
|
const tests = commentsSuite!.groups.flatMap(g => g.tests)
|
||||||
|
expect(tests.length).toBe(3)
|
||||||
|
|
||||||
|
const testGoodDoc = tests.find(t => t.name === 'testGoodDoc')
|
||||||
|
expect(testGoodDoc).toBeDefined()
|
||||||
|
expect(testGoodDoc!.result).toBe('success')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('captures failure details from phpcheckstyle-phpunit.xml', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'phpunit', 'phpcheckstyle-phpunit.xml')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const opts: ParseOptions = {
|
||||||
|
parseErrors: true,
|
||||||
|
trackedFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new PhpunitJunitParser(opts)
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
|
||||||
|
// Find the OtherTest suite which has failures
|
||||||
|
const otherSuite = result.suites.find(s => s.name === 'OtherTest')
|
||||||
|
expect(otherSuite).toBeDefined()
|
||||||
|
|
||||||
|
const failedTests = otherSuite!.groups.flatMap(g => g.tests).filter(t => t.result === 'failed')
|
||||||
|
expect(failedTests.length).toBe(2)
|
||||||
|
|
||||||
|
// Verify failure details
|
||||||
|
const testOther = failedTests.find(t => t.name === 'testOther')
|
||||||
|
expect(testOther).toBeDefined()
|
||||||
|
expect(testOther!.error).toBeDefined()
|
||||||
|
expect(testOther!.error!.details).toContain('We expect 20 warnings')
|
||||||
|
expect(testOther!.error!.details).toContain('Failed asserting that 19 matches expected 20')
|
||||||
|
|
||||||
|
const testException = failedTests.find(t => t.name === 'testException')
|
||||||
|
expect(testException).toBeDefined()
|
||||||
|
expect(testException!.error).toBeDefined()
|
||||||
|
expect(testException!.error!.details).toContain('We expect 1 error')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('report from junit-basic.xml matches snapshot', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'phpunit', 'junit-basic.xml')
|
||||||
|
const outputPath = path.join(__dirname, '__outputs__', 'phpunit-junit-basic-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 PhpunitJunitParser(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('report from phpcheckstyle-phpunit.xml matches snapshot', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'phpunit', 'phpcheckstyle-phpunit.xml')
|
||||||
|
const outputPath = path.join(__dirname, '__outputs__', 'phpunit-phpcheckstyle-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 PhpunitJunitParser(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)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
name: Test Reporter
|
name: Test Reporter
|
||||||
description: |
|
description: Displays test results from popular testing frameworks directly in GitHub
|
||||||
Shows test results in GitHub UI: .NET (xUnit, NUnit, MSTest), Dart, Flutter, Go, Java (JUnit), JavaScript (JEST, Mocha), Python (pytest, unittest), Ruby (RSpec), Swift
|
|
||||||
author: Michal Dorner <dorner.michal@gmail.com>
|
author: Michal Dorner <dorner.michal@gmail.com>
|
||||||
inputs:
|
inputs:
|
||||||
artifact:
|
artifact:
|
||||||
@@ -33,6 +32,7 @@ inputs:
|
|||||||
- java-junit
|
- java-junit
|
||||||
- jest-junit
|
- jest-junit
|
||||||
- mocha-json
|
- mocha-json
|
||||||
|
- phpunit-junit
|
||||||
- python-xunit
|
- python-xunit
|
||||||
- rspec-json
|
- rspec-json
|
||||||
- swift-xunit
|
- swift-xunit
|
||||||
|
|||||||
260
dist/index.js
generated
vendored
260
dist/index.js
generated
vendored
@@ -277,6 +277,7 @@ const golang_json_parser_1 = __nccwpck_require__(5162);
|
|||||||
const java_junit_parser_1 = __nccwpck_require__(8342);
|
const java_junit_parser_1 = __nccwpck_require__(8342);
|
||||||
const jest_junit_parser_1 = __nccwpck_require__(1042);
|
const jest_junit_parser_1 = __nccwpck_require__(1042);
|
||||||
const mocha_json_parser_1 = __nccwpck_require__(5402);
|
const mocha_json_parser_1 = __nccwpck_require__(5402);
|
||||||
|
const phpunit_junit_parser_1 = __nccwpck_require__(2674);
|
||||||
const python_xunit_parser_1 = __nccwpck_require__(6578);
|
const python_xunit_parser_1 = __nccwpck_require__(6578);
|
||||||
const rspec_json_parser_1 = __nccwpck_require__(9768);
|
const rspec_json_parser_1 = __nccwpck_require__(9768);
|
||||||
const swift_xunit_parser_1 = __nccwpck_require__(7330);
|
const swift_xunit_parser_1 = __nccwpck_require__(7330);
|
||||||
@@ -494,6 +495,8 @@ class TestReporter {
|
|||||||
return new jest_junit_parser_1.JestJunitParser(options);
|
return new jest_junit_parser_1.JestJunitParser(options);
|
||||||
case 'mocha-json':
|
case 'mocha-json':
|
||||||
return new mocha_json_parser_1.MochaJsonParser(options);
|
return new mocha_json_parser_1.MochaJsonParser(options);
|
||||||
|
case 'phpunit-junit':
|
||||||
|
return new phpunit_junit_parser_1.PhpunitJunitParser(options);
|
||||||
case 'python-xunit':
|
case 'python-xunit':
|
||||||
return new python_xunit_parser_1.PythonXunitParser(options);
|
return new python_xunit_parser_1.PythonXunitParser(options);
|
||||||
case 'rspec-json':
|
case 'rspec-json':
|
||||||
@@ -726,12 +729,12 @@ class DartJsonParser {
|
|||||||
getRelativePath(path) {
|
getRelativePath(path) {
|
||||||
const prefix = 'file://';
|
const prefix = 'file://';
|
||||||
if (path.startsWith(prefix)) {
|
if (path.startsWith(prefix)) {
|
||||||
path = path.substr(prefix.length);
|
path = path.substring(prefix.length);
|
||||||
}
|
}
|
||||||
path = (0, path_utils_1.normalizeFilePath)(path);
|
path = (0, path_utils_1.normalizeFilePath)(path);
|
||||||
const workDir = this.getWorkDir(path);
|
const workDir = this.getWorkDir(path);
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length);
|
path = path.substring(workDir.length);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -890,7 +893,7 @@ class DotnetNunitParser {
|
|||||||
path = (0, path_utils_1.normalizeFilePath)(path);
|
path = (0, path_utils_1.normalizeFilePath)(path);
|
||||||
const workDir = this.getWorkDir(path);
|
const workDir = this.getWorkDir(path);
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length);
|
path = path.substring(workDir.length);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -994,7 +997,7 @@ class DotnetTrxParser {
|
|||||||
const duration = durationAttr ? (0, parse_utils_1.parseNetDuration)(durationAttr) : 0;
|
const duration = durationAttr ? (0, parse_utils_1.parseNetDuration)(durationAttr) : 0;
|
||||||
const resultTestName = r.result.$.testName;
|
const resultTestName = r.result.$.testName;
|
||||||
const testName = resultTestName.startsWith(className) && resultTestName[className.length] === '.'
|
const testName = resultTestName.startsWith(className) && resultTestName[className.length] === '.'
|
||||||
? resultTestName.substr(className.length + 1)
|
? resultTestName.substring(className.length + 1)
|
||||||
: resultTestName;
|
: resultTestName;
|
||||||
const test = new Test(testName, r.result.$.outcome, duration, error);
|
const test = new Test(testName, r.result.$.outcome, duration, error);
|
||||||
tc.tests.push(test);
|
tc.tests.push(test);
|
||||||
@@ -1061,7 +1064,7 @@ class DotnetTrxParser {
|
|||||||
const filePath = (0, path_utils_1.normalizeFilePath)(fileStr);
|
const filePath = (0, path_utils_1.normalizeFilePath)(fileStr);
|
||||||
const workDir = this.getWorkDir(filePath);
|
const workDir = this.getWorkDir(filePath);
|
||||||
if (workDir) {
|
if (workDir) {
|
||||||
const file = filePath.substr(workDir.length);
|
const file = filePath.substring(workDir.length);
|
||||||
if (trackedFiles.includes(file)) {
|
if (trackedFiles.includes(file)) {
|
||||||
const line = parseInt(lineStr);
|
const line = parseInt(lineStr);
|
||||||
return { path: file, line };
|
return { path: file, line };
|
||||||
@@ -1547,7 +1550,7 @@ class JestJunitParser {
|
|||||||
path = (0, path_utils_1.normalizeFilePath)(path);
|
path = (0, path_utils_1.normalizeFilePath)(path);
|
||||||
const workDir = this.getWorkDir(path);
|
const workDir = this.getWorkDir(path);
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length);
|
path = path.substring(workDir.length);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -1618,7 +1621,7 @@ class MochaJsonParser {
|
|||||||
}
|
}
|
||||||
processTest(suite, test, result) {
|
processTest(suite, test, result) {
|
||||||
const groupName = test.fullTitle !== test.title
|
const groupName = test.fullTitle !== test.title
|
||||||
? test.fullTitle.substr(0, test.fullTitle.length - test.title.length).trimEnd()
|
? test.fullTitle.substring(0, test.fullTitle.length - test.title.length).trimEnd()
|
||||||
: null;
|
: null;
|
||||||
let group = suite.groups.find(grp => grp.name === groupName);
|
let group = suite.groups.find(grp => grp.name === groupName);
|
||||||
if (group === undefined) {
|
if (group === undefined) {
|
||||||
@@ -1653,7 +1656,7 @@ class MochaJsonParser {
|
|||||||
path = (0, path_utils_1.normalizeFilePath)(path);
|
path = (0, path_utils_1.normalizeFilePath)(path);
|
||||||
const workDir = this.getWorkDir(path);
|
const workDir = this.getWorkDir(path);
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length);
|
path = path.substring(workDir.length);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -1666,6 +1669,241 @@ class MochaJsonParser {
|
|||||||
exports.MochaJsonParser = MochaJsonParser;
|
exports.MochaJsonParser = MochaJsonParser;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 2674:
|
||||||
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.PhpunitJunitParser = void 0;
|
||||||
|
const xml2js_1 = __nccwpck_require__(758);
|
||||||
|
const path_utils_1 = __nccwpck_require__(9132);
|
||||||
|
const test_results_1 = __nccwpck_require__(613);
|
||||||
|
class PhpunitJunitParser {
|
||||||
|
options;
|
||||||
|
trackedFiles;
|
||||||
|
trackedFilesList;
|
||||||
|
assumedWorkDir;
|
||||||
|
constructor(options) {
|
||||||
|
this.options = options;
|
||||||
|
this.trackedFilesList = options.trackedFiles.map(f => (0, path_utils_1.normalizeFilePath)(f));
|
||||||
|
this.trackedFiles = new Set(this.trackedFilesList);
|
||||||
|
}
|
||||||
|
async parse(filePath, content) {
|
||||||
|
const reportOrSuite = await this.getPhpunitReport(filePath, content);
|
||||||
|
const isReport = reportOrSuite.testsuites !== undefined;
|
||||||
|
// XML might contain:
|
||||||
|
// - multiple suites under <testsuites> root node
|
||||||
|
// - single <testsuite> as root node
|
||||||
|
let report;
|
||||||
|
if (isReport) {
|
||||||
|
report = reportOrSuite;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Make it behave the same way as if suite was inside <testsuites> root node
|
||||||
|
const suite = reportOrSuite.testsuite;
|
||||||
|
report = {
|
||||||
|
testsuites: {
|
||||||
|
$: { time: suite.$.time },
|
||||||
|
testsuite: [suite]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.getTestRunResult(filePath, report);
|
||||||
|
}
|
||||||
|
async getPhpunitReport(filePath, content) {
|
||||||
|
try {
|
||||||
|
return await (0, xml2js_1.parseStringPromise)(content);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new Error(`Invalid XML at ${filePath}\n\n${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getTestRunResult(filePath, report) {
|
||||||
|
const suites = [];
|
||||||
|
this.collectSuites(suites, report.testsuites.testsuite ?? []);
|
||||||
|
const seconds = parseFloat(report.testsuites.$?.time ?? '');
|
||||||
|
const time = isNaN(seconds) ? undefined : seconds * 1000;
|
||||||
|
return new test_results_1.TestRunResult(filePath, suites, time);
|
||||||
|
}
|
||||||
|
collectSuites(results, testsuites) {
|
||||||
|
for (const ts of testsuites) {
|
||||||
|
// Recursively process nested test suites first (depth-first)
|
||||||
|
if (ts.testsuite) {
|
||||||
|
this.collectSuites(results, ts.testsuite);
|
||||||
|
}
|
||||||
|
// Only add suites that have direct test cases
|
||||||
|
// This avoids adding container suites that only hold nested suites
|
||||||
|
if (ts.testcase && ts.testcase.length > 0) {
|
||||||
|
const name = ts.$.name.trim();
|
||||||
|
const time = parseFloat(ts.$.time) * 1000;
|
||||||
|
results.push(new test_results_1.TestSuiteResult(name, this.getGroups(ts), time));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getGroups(suite) {
|
||||||
|
if (!suite.testcase || suite.testcase.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const groups = [];
|
||||||
|
for (const tc of suite.testcase) {
|
||||||
|
// Use classname (PHPUnit style) for grouping
|
||||||
|
// If classname matches suite name, use empty string to avoid redundancy
|
||||||
|
const className = tc.$.classname ?? tc.$.class ?? '';
|
||||||
|
const groupName = className === suite.$.name ? '' : className;
|
||||||
|
let grp = groups.find(g => g.name === groupName);
|
||||||
|
if (grp === undefined) {
|
||||||
|
grp = { name: groupName, tests: [] };
|
||||||
|
groups.push(grp);
|
||||||
|
}
|
||||||
|
grp.tests.push(tc);
|
||||||
|
}
|
||||||
|
return groups.map(grp => {
|
||||||
|
const tests = grp.tests.map(tc => {
|
||||||
|
const name = tc.$.name.trim();
|
||||||
|
const result = this.getTestCaseResult(tc);
|
||||||
|
const time = parseFloat(tc.$.time) * 1000;
|
||||||
|
const error = this.getTestCaseError(tc);
|
||||||
|
return new test_results_1.TestCaseResult(name, result, time, error);
|
||||||
|
});
|
||||||
|
return new test_results_1.TestGroupResult(grp.name, tests);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getTestCaseResult(test) {
|
||||||
|
if (test.failure || test.error)
|
||||||
|
return 'failed';
|
||||||
|
if (test.skipped)
|
||||||
|
return 'skipped';
|
||||||
|
return 'success';
|
||||||
|
}
|
||||||
|
getTestCaseError(tc) {
|
||||||
|
if (!this.options.parseErrors) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
// We process <error> and <failure> the same way
|
||||||
|
const failures = tc.failure ?? tc.error;
|
||||||
|
if (!failures || failures.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const failure = failures[0];
|
||||||
|
const details = typeof failure === 'string' ? failure : failure._ ?? '';
|
||||||
|
// PHPUnit provides file path directly in testcase attributes
|
||||||
|
let filePath;
|
||||||
|
let line;
|
||||||
|
if (tc.$.file) {
|
||||||
|
const relativePath = this.getRelativePath(tc.$.file);
|
||||||
|
if (this.trackedFiles.has(relativePath)) {
|
||||||
|
filePath = relativePath;
|
||||||
|
}
|
||||||
|
if (tc.$.line) {
|
||||||
|
line = parseInt(tc.$.line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If file not in tracked files, try to extract from error details
|
||||||
|
if (!filePath && details) {
|
||||||
|
const extracted = this.extractFileAndLine(details);
|
||||||
|
if (extracted) {
|
||||||
|
filePath = extracted.filePath;
|
||||||
|
line = extracted.line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let message;
|
||||||
|
if (typeof failure !== 'string' && failure.$) {
|
||||||
|
message = failure.$.message;
|
||||||
|
if (failure.$.type) {
|
||||||
|
message = message ? `${failure.$.type}: ${message}` : failure.$.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
path: filePath,
|
||||||
|
line,
|
||||||
|
details,
|
||||||
|
message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
extractFileAndLine(details) {
|
||||||
|
// PHPUnit stack traces typically have format: /path/to/file.php:123
|
||||||
|
const lines = details.split(/\r?\n/);
|
||||||
|
for (const str of lines) {
|
||||||
|
// Match patterns like /path/to/file.php:123 or at /path/to/file.php(123)
|
||||||
|
const matchColon = str.match(/((?:[A-Za-z]:)?[^\s:()]+?\.(?:php|phpt)):(\d+)/);
|
||||||
|
if (matchColon) {
|
||||||
|
const relativePath = this.getRelativePath(matchColon[1]);
|
||||||
|
if (this.trackedFiles.has(relativePath)) {
|
||||||
|
return { filePath: relativePath, line: parseInt(matchColon[2]) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const matchParen = str.match(/((?:[A-Za-z]:)?[^\s:()]+?\.(?:php|phpt))\((\d+)\)/);
|
||||||
|
if (matchParen) {
|
||||||
|
const relativePath = this.getRelativePath(matchParen[1]);
|
||||||
|
if (this.trackedFiles.has(relativePath)) {
|
||||||
|
return { filePath: relativePath, line: parseInt(matchParen[2]) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Converts an absolute file path to a relative path by stripping the working directory prefix.
|
||||||
|
*
|
||||||
|
* @param path - The absolute file path from PHPUnit output (e.g., `/home/runner/work/repo/src/Test.php`)
|
||||||
|
* @returns The relative path (e.g., `src/Test.php`) if a working directory can be determined,
|
||||||
|
* otherwise returns the normalized original path
|
||||||
|
*/
|
||||||
|
getRelativePath(path) {
|
||||||
|
path = (0, path_utils_1.normalizeFilePath)(path);
|
||||||
|
const workDir = this.getWorkDir(path);
|
||||||
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
|
path = path.substring(workDir.length);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Determines the working directory prefix to strip from absolute file paths.
|
||||||
|
*
|
||||||
|
* The working directory is resolved using the following priority:
|
||||||
|
*
|
||||||
|
* 1. **Explicit configuration** - If `options.workDir` is set, it takes precedence.
|
||||||
|
* This allows users to explicitly specify the working directory.
|
||||||
|
*
|
||||||
|
* 2. **Cached assumption** - If we've previously determined a working directory
|
||||||
|
* (`assumedWorkDir`) and the current path starts with it, we reuse that value.
|
||||||
|
* This avoids redundant computation for subsequent paths.
|
||||||
|
*
|
||||||
|
* 3. **Heuristic detection** - Uses `getBasePath()` to find the common prefix between
|
||||||
|
* the absolute path and the list of tracked files in the repository. For example:
|
||||||
|
* - Absolute path: `/home/runner/work/repo/src/Test.php`
|
||||||
|
* - Tracked file: `src/Test.php`
|
||||||
|
* - Detected workDir: `/home/runner/work/repo/`
|
||||||
|
*
|
||||||
|
* Once detected, the working directory is cached in `assumedWorkDir` for efficiency.
|
||||||
|
*
|
||||||
|
* @param path - The normalized absolute file path to analyze
|
||||||
|
* @returns The working directory prefix (with trailing slash), or `undefined` if it cannot be determined
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // With tracked file 'src/Foo.php' and path '/home/runner/work/repo/src/Foo.php'
|
||||||
|
* // Returns: '/home/runner/work/repo/'
|
||||||
|
*/
|
||||||
|
getWorkDir(path) {
|
||||||
|
if (this.options.workDir) {
|
||||||
|
return this.options.workDir;
|
||||||
|
}
|
||||||
|
if (this.assumedWorkDir && path.startsWith(this.assumedWorkDir)) {
|
||||||
|
return this.assumedWorkDir;
|
||||||
|
}
|
||||||
|
const basePath = (0, path_utils_1.getBasePath)(path, this.trackedFilesList);
|
||||||
|
if (basePath !== undefined) {
|
||||||
|
this.assumedWorkDir = basePath;
|
||||||
|
}
|
||||||
|
return basePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.PhpunitJunitParser = PhpunitJunitParser;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 6578:
|
/***/ 6578:
|
||||||
@@ -1739,7 +1977,7 @@ class RspecJsonParser {
|
|||||||
}
|
}
|
||||||
processTest(suite, test, result) {
|
processTest(suite, test, result) {
|
||||||
const groupName = test.full_description !== test.description
|
const groupName = test.full_description !== test.description
|
||||||
? test.full_description.substr(0, test.full_description.length - test.description.length).trimEnd()
|
? test.full_description.substring(0, test.full_description.length - test.description.length).trimEnd()
|
||||||
: null;
|
: null;
|
||||||
let group = suite.groups.find(grp => grp.name === groupName);
|
let group = suite.groups.find(grp => grp.name === groupName);
|
||||||
if (group === undefined) {
|
if (group === undefined) {
|
||||||
@@ -2585,7 +2823,7 @@ function ellipsis(text, maxLength) {
|
|||||||
if (text.length <= maxLength) {
|
if (text.length <= maxLength) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
return text.substr(0, maxLength - 3) + '...';
|
return text.substring(0, maxLength - 3) + '...';
|
||||||
}
|
}
|
||||||
function formatTime(ms) {
|
function formatTime(ms) {
|
||||||
if (ms > 1000) {
|
if (ms > 1000) {
|
||||||
@@ -2704,7 +2942,7 @@ function getBasePath(path, trackedFiles) {
|
|||||||
if (max === '') {
|
if (max === '') {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const base = path.substr(0, path.length - max.length);
|
const base = path.substring(0, path.length - max.length);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "test-reporter",
|
"name": "test-reporter",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "test-reporter",
|
"name": "test-reporter",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.11.1",
|
"@actions/core": "^1.11.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "test-reporter",
|
"name": "test-reporter",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Presents test results from popular testing frameworks as Github check run",
|
"description": "Presents test results from popular testing frameworks as Github check run",
|
||||||
"main": "lib/main.js",
|
"main": "lib/main.js",
|
||||||
|
|||||||
4826
reports/jest/package-lock.json
generated
4826
reports/jest/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
1453
reports/mocha/package-lock.json
generated
1453
reports/mocha/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,6 @@
|
|||||||
"author": "Michal Dorner <dorner.michal@gmail.com>",
|
"author": "Michal Dorner <dorner.michal@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "^8.3.0"
|
"mocha": "^11.7.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {GolangJsonParser} from './parsers/golang-json/golang-json-parser'
|
|||||||
import {JavaJunitParser} from './parsers/java-junit/java-junit-parser'
|
import {JavaJunitParser} from './parsers/java-junit/java-junit-parser'
|
||||||
import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser'
|
import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser'
|
||||||
import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser'
|
import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser'
|
||||||
|
import {PhpunitJunitParser} from './parsers/phpunit-junit/phpunit-junit-parser'
|
||||||
import {PythonXunitParser} from './parsers/python-xunit/python-xunit-parser'
|
import {PythonXunitParser} from './parsers/python-xunit/python-xunit-parser'
|
||||||
import {RspecJsonParser} from './parsers/rspec-json/rspec-json-parser'
|
import {RspecJsonParser} from './parsers/rspec-json/rspec-json-parser'
|
||||||
import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
|
import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
|
||||||
@@ -271,6 +272,8 @@ class TestReporter {
|
|||||||
return new JestJunitParser(options)
|
return new JestJunitParser(options)
|
||||||
case 'mocha-json':
|
case 'mocha-json':
|
||||||
return new MochaJsonParser(options)
|
return new MochaJsonParser(options)
|
||||||
|
case 'phpunit-junit':
|
||||||
|
return new PhpunitJunitParser(options)
|
||||||
case 'python-xunit':
|
case 'python-xunit':
|
||||||
return new PythonXunitParser(options)
|
return new PythonXunitParser(options)
|
||||||
case 'rspec-json':
|
case 'rspec-json':
|
||||||
|
|||||||
@@ -242,13 +242,13 @@ export class DartJsonParser implements TestParser {
|
|||||||
private getRelativePath(path: string): string {
|
private getRelativePath(path: string): string {
|
||||||
const prefix = 'file://'
|
const prefix = 'file://'
|
||||||
if (path.startsWith(prefix)) {
|
if (path.startsWith(prefix)) {
|
||||||
path = path.substr(prefix.length)
|
path = path.substring(prefix.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = normalizeFilePath(path)
|
path = normalizeFilePath(path)
|
||||||
const workDir = this.getWorkDir(path)
|
const workDir = this.getWorkDir(path)
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length)
|
path = path.substring(workDir.length)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ export class DotnetNunitParser implements TestParser {
|
|||||||
path = normalizeFilePath(path)
|
path = normalizeFilePath(path)
|
||||||
const workDir = this.getWorkDir(path)
|
const workDir = this.getWorkDir(path)
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length)
|
path = path.substring(workDir.length)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export class DotnetTrxParser implements TestParser {
|
|||||||
const resultTestName = r.result.$.testName
|
const resultTestName = r.result.$.testName
|
||||||
const testName =
|
const testName =
|
||||||
resultTestName.startsWith(className) && resultTestName[className.length] === '.'
|
resultTestName.startsWith(className) && resultTestName[className.length] === '.'
|
||||||
? resultTestName.substr(className.length + 1)
|
? resultTestName.substring(className.length + 1)
|
||||||
: resultTestName
|
: resultTestName
|
||||||
|
|
||||||
const test = new Test(testName, r.result.$.outcome, duration, error)
|
const test = new Test(testName, r.result.$.outcome, duration, error)
|
||||||
@@ -177,7 +177,7 @@ export class DotnetTrxParser implements TestParser {
|
|||||||
const filePath = normalizeFilePath(fileStr)
|
const filePath = normalizeFilePath(fileStr)
|
||||||
const workDir = this.getWorkDir(filePath)
|
const workDir = this.getWorkDir(filePath)
|
||||||
if (workDir) {
|
if (workDir) {
|
||||||
const file = filePath.substr(workDir.length)
|
const file = filePath.substring(workDir.length)
|
||||||
if (trackedFiles.includes(file)) {
|
if (trackedFiles.includes(file)) {
|
||||||
const line = parseInt(lineStr)
|
const line = parseInt(lineStr)
|
||||||
return {path: file, line}
|
return {path: file, line}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export class JestJunitParser implements TestParser {
|
|||||||
path = normalizeFilePath(path)
|
path = normalizeFilePath(path)
|
||||||
const workDir = this.getWorkDir(path)
|
const workDir = this.getWorkDir(path)
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length)
|
path = path.substring(workDir.length)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export class MochaJsonParser implements TestParser {
|
|||||||
private processTest(suite: TestSuiteResult, test: MochaJsonTest, result: TestExecutionResult): void {
|
private processTest(suite: TestSuiteResult, test: MochaJsonTest, result: TestExecutionResult): void {
|
||||||
const groupName =
|
const groupName =
|
||||||
test.fullTitle !== test.title
|
test.fullTitle !== test.title
|
||||||
? test.fullTitle.substr(0, test.fullTitle.length - test.title.length).trimEnd()
|
? test.fullTitle.substring(0, test.fullTitle.length - test.title.length).trimEnd()
|
||||||
: null
|
: null
|
||||||
|
|
||||||
let group = suite.groups.find(grp => grp.name === groupName)
|
let group = suite.groups.find(grp => grp.name === groupName)
|
||||||
@@ -103,7 +103,7 @@ export class MochaJsonParser implements TestParser {
|
|||||||
path = normalizeFilePath(path)
|
path = normalizeFilePath(path)
|
||||||
const workDir = this.getWorkDir(path)
|
const workDir = this.getWorkDir(path)
|
||||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length)
|
path = path.substring(workDir.length)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|||||||
258
src/parsers/phpunit-junit/phpunit-junit-parser.ts
Normal file
258
src/parsers/phpunit-junit/phpunit-junit-parser.ts
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
import {ParseOptions, TestParser} from '../../test-parser'
|
||||||
|
import {parseStringPromise} from 'xml2js'
|
||||||
|
|
||||||
|
import {PhpunitReport, SingleSuiteReport, TestCase, TestSuite} from './phpunit-junit-types'
|
||||||
|
import {getBasePath, normalizeFilePath} from '../../utils/path-utils'
|
||||||
|
|
||||||
|
import {
|
||||||
|
TestExecutionResult,
|
||||||
|
TestRunResult,
|
||||||
|
TestSuiteResult,
|
||||||
|
TestGroupResult,
|
||||||
|
TestCaseResult,
|
||||||
|
TestCaseError
|
||||||
|
} from '../../test-results'
|
||||||
|
|
||||||
|
export class PhpunitJunitParser implements TestParser {
|
||||||
|
readonly trackedFiles: Set<string>
|
||||||
|
readonly trackedFilesList: string[]
|
||||||
|
private assumedWorkDir: string | undefined
|
||||||
|
|
||||||
|
constructor(readonly options: ParseOptions) {
|
||||||
|
this.trackedFilesList = options.trackedFiles.map(f => normalizeFilePath(f))
|
||||||
|
this.trackedFiles = new Set(this.trackedFilesList)
|
||||||
|
}
|
||||||
|
|
||||||
|
async parse(filePath: string, content: string): Promise<TestRunResult> {
|
||||||
|
const reportOrSuite = await this.getPhpunitReport(filePath, content)
|
||||||
|
const isReport = (reportOrSuite as PhpunitReport).testsuites !== undefined
|
||||||
|
|
||||||
|
// XML might contain:
|
||||||
|
// - multiple suites under <testsuites> root node
|
||||||
|
// - single <testsuite> as root node
|
||||||
|
let report: PhpunitReport
|
||||||
|
if (isReport) {
|
||||||
|
report = reportOrSuite as PhpunitReport
|
||||||
|
} else {
|
||||||
|
// Make it behave the same way as if suite was inside <testsuites> root node
|
||||||
|
const suite = (reportOrSuite as SingleSuiteReport).testsuite
|
||||||
|
report = {
|
||||||
|
testsuites: {
|
||||||
|
$: {time: suite.$.time},
|
||||||
|
testsuite: [suite]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getTestRunResult(filePath, report)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getPhpunitReport(filePath: string, content: string): Promise<PhpunitReport | SingleSuiteReport> {
|
||||||
|
try {
|
||||||
|
return await parseStringPromise(content)
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Invalid XML at ${filePath}\n\n${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTestRunResult(filePath: string, report: PhpunitReport): TestRunResult {
|
||||||
|
const suites: TestSuiteResult[] = []
|
||||||
|
this.collectSuites(suites, report.testsuites.testsuite ?? [])
|
||||||
|
|
||||||
|
const seconds = parseFloat(report.testsuites.$?.time ?? '')
|
||||||
|
const time = isNaN(seconds) ? undefined : seconds * 1000
|
||||||
|
return new TestRunResult(filePath, suites, time)
|
||||||
|
}
|
||||||
|
|
||||||
|
private collectSuites(results: TestSuiteResult[], testsuites: TestSuite[]): void {
|
||||||
|
for (const ts of testsuites) {
|
||||||
|
// Recursively process nested test suites first (depth-first)
|
||||||
|
if (ts.testsuite) {
|
||||||
|
this.collectSuites(results, ts.testsuite)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only add suites that have direct test cases
|
||||||
|
// This avoids adding container suites that only hold nested suites
|
||||||
|
if (ts.testcase && ts.testcase.length > 0) {
|
||||||
|
const name = ts.$.name.trim()
|
||||||
|
const time = parseFloat(ts.$.time) * 1000
|
||||||
|
results.push(new TestSuiteResult(name, this.getGroups(ts), time))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getGroups(suite: TestSuite): TestGroupResult[] {
|
||||||
|
if (!suite.testcase || suite.testcase.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const groups: {name: string; tests: TestCase[]}[] = []
|
||||||
|
for (const tc of suite.testcase) {
|
||||||
|
// Use classname (PHPUnit style) for grouping
|
||||||
|
// If classname matches suite name, use empty string to avoid redundancy
|
||||||
|
const className = tc.$.classname ?? tc.$.class ?? ''
|
||||||
|
const groupName = className === suite.$.name ? '' : className
|
||||||
|
let grp = groups.find(g => g.name === groupName)
|
||||||
|
if (grp === undefined) {
|
||||||
|
grp = {name: groupName, tests: []}
|
||||||
|
groups.push(grp)
|
||||||
|
}
|
||||||
|
grp.tests.push(tc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups.map(grp => {
|
||||||
|
const tests = grp.tests.map(tc => {
|
||||||
|
const name = tc.$.name.trim()
|
||||||
|
const result = this.getTestCaseResult(tc)
|
||||||
|
const time = parseFloat(tc.$.time) * 1000
|
||||||
|
const error = this.getTestCaseError(tc)
|
||||||
|
return new TestCaseResult(name, result, time, error)
|
||||||
|
})
|
||||||
|
return new TestGroupResult(grp.name, tests)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTestCaseResult(test: TestCase): TestExecutionResult {
|
||||||
|
if (test.failure || test.error) return 'failed'
|
||||||
|
if (test.skipped) return 'skipped'
|
||||||
|
return 'success'
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTestCaseError(tc: TestCase): TestCaseError | undefined {
|
||||||
|
if (!this.options.parseErrors) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// We process <error> and <failure> the same way
|
||||||
|
const failures = tc.failure ?? tc.error
|
||||||
|
if (!failures || failures.length === 0) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const failure = failures[0]
|
||||||
|
const details = typeof failure === 'string' ? failure : failure._ ?? ''
|
||||||
|
|
||||||
|
// PHPUnit provides file path directly in testcase attributes
|
||||||
|
let filePath: string | undefined
|
||||||
|
let line: number | undefined
|
||||||
|
|
||||||
|
if (tc.$.file) {
|
||||||
|
const relativePath = this.getRelativePath(tc.$.file)
|
||||||
|
if (this.trackedFiles.has(relativePath)) {
|
||||||
|
filePath = relativePath
|
||||||
|
}
|
||||||
|
if (tc.$.line) {
|
||||||
|
line = parseInt(tc.$.line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If file not in tracked files, try to extract from error details
|
||||||
|
if (!filePath && details) {
|
||||||
|
const extracted = this.extractFileAndLine(details)
|
||||||
|
if (extracted) {
|
||||||
|
filePath = extracted.filePath
|
||||||
|
line = extracted.line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let message: string | undefined
|
||||||
|
if (typeof failure !== 'string' && failure.$) {
|
||||||
|
message = failure.$.message
|
||||||
|
if (failure.$.type) {
|
||||||
|
message = message ? `${failure.$.type}: ${message}` : failure.$.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
path: filePath,
|
||||||
|
line,
|
||||||
|
details,
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractFileAndLine(details: string): {filePath: string; line: number} | undefined {
|
||||||
|
// PHPUnit stack traces typically have format: /path/to/file.php:123
|
||||||
|
const lines = details.split(/\r?\n/)
|
||||||
|
|
||||||
|
for (const str of lines) {
|
||||||
|
// Match patterns like /path/to/file.php:123 or at /path/to/file.php(123)
|
||||||
|
const matchColon = str.match(/((?:[A-Za-z]:)?[^\s:()]+?\.(?:php|phpt)):(\d+)/)
|
||||||
|
if (matchColon) {
|
||||||
|
const relativePath = this.getRelativePath(matchColon[1])
|
||||||
|
if (this.trackedFiles.has(relativePath)) {
|
||||||
|
return {filePath: relativePath, line: parseInt(matchColon[2])}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchParen = str.match(/((?:[A-Za-z]:)?[^\s:()]+?\.(?:php|phpt))\((\d+)\)/)
|
||||||
|
if (matchParen) {
|
||||||
|
const relativePath = this.getRelativePath(matchParen[1])
|
||||||
|
if (this.trackedFiles.has(relativePath)) {
|
||||||
|
return {filePath: relativePath, line: parseInt(matchParen[2])}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an absolute file path to a relative path by stripping the working directory prefix.
|
||||||
|
*
|
||||||
|
* @param path - The absolute file path from PHPUnit output (e.g., `/home/runner/work/repo/src/Test.php`)
|
||||||
|
* @returns The relative path (e.g., `src/Test.php`) if a working directory can be determined,
|
||||||
|
* otherwise returns the normalized original path
|
||||||
|
*/
|
||||||
|
private getRelativePath(path: string): string {
|
||||||
|
path = normalizeFilePath(path)
|
||||||
|
const workDir = this.getWorkDir(path)
|
||||||
|
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||||
|
path = path.substring(workDir.length)
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the working directory prefix to strip from absolute file paths.
|
||||||
|
*
|
||||||
|
* The working directory is resolved using the following priority:
|
||||||
|
*
|
||||||
|
* 1. **Explicit configuration** - If `options.workDir` is set, it takes precedence.
|
||||||
|
* This allows users to explicitly specify the working directory.
|
||||||
|
*
|
||||||
|
* 2. **Cached assumption** - If we've previously determined a working directory
|
||||||
|
* (`assumedWorkDir`) and the current path starts with it, we reuse that value.
|
||||||
|
* This avoids redundant computation for subsequent paths.
|
||||||
|
*
|
||||||
|
* 3. **Heuristic detection** - Uses `getBasePath()` to find the common prefix between
|
||||||
|
* the absolute path and the list of tracked files in the repository. For example:
|
||||||
|
* - Absolute path: `/home/runner/work/repo/src/Test.php`
|
||||||
|
* - Tracked file: `src/Test.php`
|
||||||
|
* - Detected workDir: `/home/runner/work/repo/`
|
||||||
|
*
|
||||||
|
* Once detected, the working directory is cached in `assumedWorkDir` for efficiency.
|
||||||
|
*
|
||||||
|
* @param path - The normalized absolute file path to analyze
|
||||||
|
* @returns The working directory prefix (with trailing slash), or `undefined` if it cannot be determined
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // With tracked file 'src/Foo.php' and path '/home/runner/work/repo/src/Foo.php'
|
||||||
|
* // Returns: '/home/runner/work/repo/'
|
||||||
|
*/
|
||||||
|
private getWorkDir(path: string): string | undefined {
|
||||||
|
if (this.options.workDir) {
|
||||||
|
return this.options.workDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.assumedWorkDir && path.startsWith(this.assumedWorkDir)) {
|
||||||
|
return this.assumedWorkDir
|
||||||
|
}
|
||||||
|
|
||||||
|
const basePath = getBasePath(path, this.trackedFilesList)
|
||||||
|
if (basePath !== undefined) {
|
||||||
|
this.assumedWorkDir = basePath
|
||||||
|
}
|
||||||
|
return basePath
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/parsers/phpunit-junit/phpunit-junit-types.ts
Normal file
52
src/parsers/phpunit-junit/phpunit-junit-types.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export interface PhpunitReport {
|
||||||
|
testsuites: TestSuites
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SingleSuiteReport {
|
||||||
|
testsuite: TestSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TestSuites {
|
||||||
|
$?: {
|
||||||
|
time?: string
|
||||||
|
}
|
||||||
|
testsuite?: TestSuite[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TestSuite {
|
||||||
|
$: {
|
||||||
|
name: string
|
||||||
|
tests?: string
|
||||||
|
assertions?: string
|
||||||
|
errors?: string
|
||||||
|
failures?: string
|
||||||
|
skipped?: string
|
||||||
|
time: string
|
||||||
|
file?: string
|
||||||
|
}
|
||||||
|
testcase?: TestCase[]
|
||||||
|
testsuite?: TestSuite[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TestCase {
|
||||||
|
$: {
|
||||||
|
name: string
|
||||||
|
class?: string
|
||||||
|
classname?: string
|
||||||
|
file?: string
|
||||||
|
line?: string
|
||||||
|
assertions?: string
|
||||||
|
time: string
|
||||||
|
}
|
||||||
|
failure?: Failure[]
|
||||||
|
error?: Failure[]
|
||||||
|
skipped?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Failure {
|
||||||
|
_: string
|
||||||
|
$?: {
|
||||||
|
type?: string
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,7 +55,7 @@ export class RspecJsonParser implements TestParser {
|
|||||||
private processTest(suite: TestSuiteResult, test: RspecExample, result: TestExecutionResult): void {
|
private processTest(suite: TestSuiteResult, test: RspecExample, result: TestExecutionResult): void {
|
||||||
const groupName =
|
const groupName =
|
||||||
test.full_description !== test.description
|
test.full_description !== test.description
|
||||||
? test.full_description.substr(0, test.full_description.length - test.description.length).trimEnd()
|
? test.full_description.substring(0, test.full_description.length - test.description.length).trimEnd()
|
||||||
: null
|
: null
|
||||||
|
|
||||||
let group = suite.groups.find(grp => grp.name === groupName)
|
let group = suite.groups.find(grp => grp.name === groupName)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function ellipsis(text: string, maxLength: number): string {
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
return text.substr(0, maxLength - 3) + '...'
|
return text.substring(0, maxLength - 3) + '...'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatTime(ms: number): string {
|
export function formatTime(ms: number): string {
|
||||||
|
|||||||
@@ -34,6 +34,6 @@ export function getBasePath(path: string, trackedFiles: string[]): string | unde
|
|||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const base = path.substr(0, path.length - max.length)
|
const base = path.substring(0, path.length - max.length)
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user