Compare commits
91 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ca96a8c147 | |
|
|
5609ce4db7 | |
|
|
2f39fde5c9 | |
|
|
f93e996901 | |
|
|
d3a4a98751 | |
|
|
e3dc3b8070 | |
|
|
32ab8c7c18 | |
|
|
67f18696e2 | |
|
|
3265345995 | |
|
|
bd9ece3d5b | |
|
|
2cdc4b541f | |
|
|
2fc8e72d6d | |
|
|
1a128e49c0 | |
|
|
6966497014 | |
|
|
6e69e96316 | |
|
|
f7d3eb51ad | |
|
|
7b2af11512 | |
|
|
b8621febee | |
|
|
87fddf2d4c | |
|
|
199051a14a | |
|
|
571e1c7564 | |
|
|
1779a538c8 | |
|
|
6f22747ddf | |
|
|
a16fc5026c | |
|
|
1a4864283d | |
|
|
ce87cc29c8 | |
|
|
a2911bd1a4 | |
|
|
c9aa8e4c61 | |
|
|
4960c6f72d | |
|
|
687f107f48 | |
|
|
a27556b71f | |
|
|
9e99e42245 | |
|
|
b51833dace | |
|
|
21d3eaf2ba | |
|
|
7f7a8752e7 | |
|
|
b733e5fa06 | |
|
|
d949797a56 | |
|
|
2b73eae2a1 | |
|
|
9c98777b5e | |
|
|
cd2404de99 | |
|
|
e882a15498 | |
|
|
09ce9cb18e | |
|
|
8b7ece62e6 | |
|
|
6efd3d10b5 | |
|
|
cb8fa567f8 | |
|
|
aa43217b5c | |
|
|
372a0a3ce6 | |
|
|
e7304b1507 | |
|
|
901f7f3fb7 | |
|
|
78edec6077 | |
|
|
6408e20d8a | |
|
|
3163ccef2b | |
|
|
2c1664c634 | |
|
|
48452168d9 | |
|
|
7263a78ba0 | |
|
|
01b27826d2 | |
|
|
5b7a533e50 | |
|
|
a2d14baac0 | |
|
|
4cbb611f23 | |
|
|
885c9c7983 | |
|
|
86765bf9ff | |
|
|
3c98463190 | |
|
|
fa84819064 | |
|
|
be8172cc30 | |
|
|
522da11899 | |
|
|
25872e3ced | |
|
|
ad2418953f | |
|
|
73f631504e | |
|
|
4a5ec3cb2a | |
|
|
81b1db734f | |
|
|
7de9f0c20e | |
|
|
695d78b965 | |
|
|
8646b76a75 | |
|
|
f01db0d1e6 | |
|
|
09bb5e16ab | |
|
|
482f012643 | |
|
|
931cea1ce1 | |
|
|
6874623c31 | |
|
|
f1428434ae | |
|
|
9fb92762fe | |
|
|
f0a1b40820 | |
|
|
f049c0b8a0 | |
|
|
bfe48bdadd | |
|
|
a915ba6359 | |
|
|
d63a9f508a | |
|
|
fd75ee04fb | |
|
|
7a84557836 | |
|
|
aeff4d81b5 | |
|
|
0e669d19fc | |
|
|
8e816e7ede | |
|
|
89359cff67 |
|
|
@ -1 +0,0 @@
|
||||||
dist/*
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"commonjs": true,
|
|
||||||
"es6": true,
|
|
||||||
"node": true,
|
|
||||||
"jest": true
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"globals": {
|
|
||||||
"Atomics": "readonly",
|
|
||||||
"SharedArrayBuffer": "readonly"
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2018
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"indent": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
* @ScaCap/action-surefire-report-maintainers
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
### What
|
||||||
|
// Describe what this PR should do
|
||||||
|
|
||||||
|
### How
|
||||||
|
// Describe how you implemented it
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "monthly"
|
||||||
|
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "monthly"
|
||||||
|
|
@ -5,41 +5,56 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||||
|
group: ${{ github.ref }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
checks: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/cache@v1
|
- uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
path: ~/.m2/repository
|
java-version: 8
|
||||||
key: ${{ runner.os }}-main-maven-${{ hashFiles('**/pom.xml') }}
|
distribution: 'temurin'
|
||||||
restore-keys: |
|
cache: 'maven'
|
||||||
${{ runner.os }}-main-maven-
|
- run: cd integration-tests/maven && mvn clean verify --batch-mode -Dmaven.test.failure.ignore=true
|
||||||
- run: cd tests && mvn clean test --batch-mode -Dmaven.test.failure.ignore=true
|
- uses: ./
|
||||||
- uses: scacap/action-surefire-report@master
|
if: github.ref != 'refs/heads/master'
|
||||||
if: endsWith(github.ref, 'master') == false
|
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
check_name: Example Surefire Test Report
|
check_name: Example Surefire Test Report
|
||||||
|
report_paths: '**/surefire-reports/*.xml, **/failsafe-reports/*.xml'
|
||||||
- uses: cclauss/GitHub-Action-for-pytest@0.5.0
|
- uses: cclauss/GitHub-Action-for-pytest@0.5.0
|
||||||
with:
|
with:
|
||||||
args: pytest --junit-xml=python/report.xml python/ || exit 0
|
args: pytest integration-tests/python/ --junit-xml=integration-tests/python/report.xml || exit 0
|
||||||
- uses: scacap/action-surefire-report@master
|
- uses: ./
|
||||||
if: endsWith(github.ref, 'master') == false
|
if: github.ref != 'refs/heads/master'
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
check_name: Example Pytest Report
|
check_name: Example Pytest Report
|
||||||
report_paths: python/report.xml
|
report_paths: integration-tests/python/report.xml
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
node-version: 12
|
go-version: 1.21.x
|
||||||
- uses: actions/cache@v1
|
- run: |
|
||||||
|
cd integration-tests/go &&
|
||||||
|
go install github.com/jstemmer/go-junit-report/v2@latest &&
|
||||||
|
go test -v 2>&1 ./... |
|
||||||
|
go-junit-report -out report.xml
|
||||||
|
- uses: ./
|
||||||
|
if: github.ref != 'refs/heads/master'
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
check_name: Example Go Report
|
||||||
key: ${{ runner.os }}-npm-cache-${{ hashFiles('**/package-lock.json') }}
|
report_paths: integration-tests/go/report.xml
|
||||||
restore-keys: |
|
file_name_in_stack_trace: true
|
||||||
${{ runner.os }}-npm-cache-
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: npm
|
||||||
|
- uses: ScaCap/infra.gh-actions/ci/js/install-safe-chain@v1
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run eslint
|
- run: npm run eslint
|
||||||
- run: npm run test
|
- run: npm run test
|
||||||
|
|
|
||||||
40
README.md
40
README.md
|
|
@ -9,14 +9,14 @@ This action processes maven surefire or failsafe XML reports on pull requests an
|
||||||
|
|
||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
### `github_token`
|
|
||||||
|
|
||||||
**Required**. Usually in form of `github_token: ${{ secrets.GITHUB_TOKEN }}`.
|
|
||||||
|
|
||||||
### `report_paths`
|
### `report_paths`
|
||||||
|
|
||||||
Optional. [Glob](https://github.com/actions/toolkit/tree/master/packages/glob) expression to surefire or failsafe report paths. The default is `**/surefire-reports/TEST-*.xml`.
|
Optional. [Glob](https://github.com/actions/toolkit/tree/master/packages/glob) expression to surefire or failsafe report paths. The default is `**/surefire-reports/TEST-*.xml`.
|
||||||
|
|
||||||
|
### `create_check`
|
||||||
|
|
||||||
|
Optional. Set to `false` to add annotations to the current job where this action is being executed. The default is `true`.
|
||||||
|
|
||||||
### `check_name`
|
### `check_name`
|
||||||
|
|
||||||
Optional. Check name to use when creating a check run. The default is `Test Report`.
|
Optional. Check name to use when creating a check run. The default is `Test Report`.
|
||||||
|
|
@ -33,6 +33,27 @@ Optional. Check will fail if there are test failures. The default is `false`.
|
||||||
|
|
||||||
Optional. Check will fail if no tests were found. The default is `true`.
|
Optional. Check will fail if no tests were found. The default is `true`.
|
||||||
|
|
||||||
|
### `ignore_flaky_tests`
|
||||||
|
|
||||||
|
Optional. Set to `true` to consider flaky tests as success. The default is `false`.
|
||||||
|
|
||||||
|
### `skip_publishing`
|
||||||
|
|
||||||
|
Optional. Skip the test report publishing (check run creation). The default is `false`.
|
||||||
|
|
||||||
|
### `github_token`
|
||||||
|
|
||||||
|
Optional. Usually in form of `github_token: ${{ secrets.GITHUB_TOKEN }}`. The default is `${{ github.token }}`.
|
||||||
|
|
||||||
|
### `file_name_in_stack_trace`
|
||||||
|
|
||||||
|
Optional. Set to `true` to get the file name from the stack trace. The default is `false`.
|
||||||
|
|
||||||
|
### `github_base_url`
|
||||||
|
|
||||||
|
Optional: If you use GitHub Enterprise, you can set this to the URL of your server (e.g. https://github.myorg.com/api/v3).
|
||||||
|
|
||||||
|
|
||||||
## Example usage
|
## Example usage
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
|
|
@ -44,15 +65,18 @@ jobs:
|
||||||
build:
|
build:
|
||||||
name: Build and Run Tests
|
name: Build and Run Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Permissions block is optional, useful for dependabot checks
|
||||||
|
permissions:
|
||||||
|
checks: write
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
- name: Build and Run Tests
|
- name: Build and Run Tests
|
||||||
run: mvn test --batch-mode -Dmaven.test.failure.ignore=true
|
run: mvn test --batch-mode --fail-at-end
|
||||||
- name: Publish Test Report
|
- name: Publish Test Report
|
||||||
|
if: success() || failure()
|
||||||
uses: scacap/action-surefire-report@v1
|
uses: scacap/action-surefire-report@v1
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tips for Gradle
|
## Tips for Gradle
|
||||||
|
|
|
||||||
111
action.js
111
action.js
|
|
@ -1,56 +1,111 @@
|
||||||
const core = require('@actions/core');
|
const core = require('@actions/core');
|
||||||
const github = require('@actions/github');
|
const github = require('@actions/github');
|
||||||
|
const { Octokit } = require("@octokit/rest");
|
||||||
|
const { retry } = require("@octokit/plugin-retry");
|
||||||
|
const RetryingOctokit = Octokit.plugin(retry);
|
||||||
const { parseTestReports } = require('./utils.js');
|
const { parseTestReports } = require('./utils.js');
|
||||||
|
|
||||||
|
|
||||||
const action = async () => {
|
const action = async () => {
|
||||||
const reportPaths = core.getInput('report_paths').split(',').join('\n');
|
const reportPaths = core.getInput('report_paths').split(',').join('\n');
|
||||||
core.info(`Going to parse results form ${reportPaths}`);
|
core.info(`Going to parse results form ${reportPaths}`);
|
||||||
const githubToken = core.getInput('github_token');
|
const githubToken = core.getInput('github_token');
|
||||||
|
const createCheck = (core.getInput('create_check') || 'true') === 'true';
|
||||||
const name = core.getInput('check_name');
|
const name = core.getInput('check_name');
|
||||||
const commit = core.getInput('commit');
|
const commit = core.getInput('commit');
|
||||||
const failOnFailedTests = core.getInput('fail_on_test_failures') === 'true';
|
const failOnFailedTests = core.getInput('fail_on_test_failures') === 'true';
|
||||||
const failIfNoTests = core.getInput('fail_if_no_tests') === 'true';
|
const failIfNoTests = core.getInput('fail_if_no_tests') === 'true';
|
||||||
|
const ignoreFlakyTests = core.getInput('ignore_flaky_tests') === 'true';
|
||||||
|
const skipPublishing = core.getInput('skip_publishing') === 'true';
|
||||||
|
const isFilenameInStackTrace = core.getInput('file_name_in_stack_trace') === 'true';
|
||||||
|
const githubBaseUrl = core.getInput('github_base_url');
|
||||||
|
|
||||||
let { count, skipped, annotations } = await parseTestReports(reportPaths);
|
let { count, skipped, annotations } = await parseTestReports(reportPaths, isFilenameInStackTrace, ignoreFlakyTests);
|
||||||
const foundResults = count > 0 || skipped > 0;
|
const foundResults = count > 0 || skipped > 0;
|
||||||
const title = foundResults
|
|
||||||
? `${count} tests run, ${skipped} skipped, ${annotations.length} failed.`
|
|
||||||
: 'No test results found!';
|
|
||||||
core.info(`Result: ${title}`);
|
|
||||||
|
|
||||||
const pullRequest = github.context.payload.pull_request;
|
|
||||||
const link = (pullRequest && pullRequest.html_url) || github.context.ref;
|
|
||||||
const conclusion =
|
const conclusion =
|
||||||
(foundResults && annotations.length === 0) || (!foundResults && !failIfNoTests)
|
(foundResults && annotations.length === 0) || (!foundResults && !failIfNoTests)
|
||||||
? 'success'
|
? 'success'
|
||||||
: 'failure';
|
: 'failure';
|
||||||
const status = 'completed';
|
|
||||||
const head_sha = commit || (pullRequest && pullRequest.head.sha) || github.context.sha;
|
|
||||||
core.info(
|
|
||||||
`Posting status '${status}' with conclusion '${conclusion}' to ${link} (sha: ${head_sha})`
|
|
||||||
);
|
|
||||||
|
|
||||||
const createCheckRequest = {
|
function buildRetryingOctokitClient() {
|
||||||
...github.context.repo,
|
const baseRequest = { auth: githubToken, request: { retries: 3 } };
|
||||||
name,
|
|
||||||
head_sha,
|
if (githubBaseUrl){
|
||||||
status,
|
baseRequest.baseUrl = githubBaseUrl;
|
||||||
conclusion,
|
|
||||||
output: {
|
|
||||||
title,
|
|
||||||
summary: '',
|
|
||||||
annotations: annotations.slice(0, 50)
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
core.debug(JSON.stringify(createCheckRequest, null, 2));
|
return new RetryingOctokit(baseRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipPublishing) {
|
||||||
|
const title = foundResults
|
||||||
|
? `${count} tests run, ${skipped} skipped, ${annotations.length} failed.`
|
||||||
|
: 'No test results found!';
|
||||||
|
core.info(`Result: ${title}`);
|
||||||
|
|
||||||
|
const pullRequest = github.context.payload.pull_request;
|
||||||
|
const link = (pullRequest && pullRequest.html_url) || github.context.ref;
|
||||||
|
const status = 'completed';
|
||||||
|
const head_sha = commit || (pullRequest && pullRequest.head.sha) || github.context.sha;
|
||||||
|
|
||||||
|
const octokit = buildRetryingOctokitClient();
|
||||||
|
if (createCheck) {
|
||||||
|
core.info(`Posting status '${status}' with conclusion '${conclusion}' to ${link} (sha: ${head_sha})`);
|
||||||
|
const createCheckRequest = {
|
||||||
|
...github.context.repo,
|
||||||
|
name,
|
||||||
|
head_sha,
|
||||||
|
status,
|
||||||
|
conclusion,
|
||||||
|
output: {
|
||||||
|
title,
|
||||||
|
summary: '',
|
||||||
|
annotations: annotations.slice(0, 50)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
core.debug(JSON.stringify(createCheckRequest, null, 2));
|
||||||
|
|
||||||
|
await octokit.rest.checks.create(createCheckRequest);
|
||||||
|
} else {
|
||||||
|
const { data: {check_runs: check_runs} } = await octokit.rest.checks.listForRef({
|
||||||
|
...github.context.repo,
|
||||||
|
check_name: name,
|
||||||
|
ref: head_sha,
|
||||||
|
status: 'in_progress'
|
||||||
|
})
|
||||||
|
core.debug(JSON.stringify(check_runs, null, 2));
|
||||||
|
if (check_runs.length === 0) {
|
||||||
|
core.setFailed(`Did not find any in progress '${name}' check for sha ${head_sha}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (check_runs.length !== 1) {
|
||||||
|
core.setFailed(`Found multiple in progress '${name}' checks for sha ${head_sha}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const check_run = check_runs[0];
|
||||||
|
core.info(`Patching '${name}' check for ${link} (sha: ${head_sha})`);
|
||||||
|
const updateCheckRequest = {
|
||||||
|
...github.context.repo,
|
||||||
|
check_run_id: check_run.id,
|
||||||
|
output: {
|
||||||
|
title: check_run.output.title || title,
|
||||||
|
summary: check_run.output.summary || '',
|
||||||
|
annotations: annotations.slice(0, 50)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
core.debug(JSON.stringify(updateCheckRequest, null, 2));
|
||||||
|
|
||||||
|
await octokit.rest.checks.update(updateCheckRequest);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
core.info('Not publishing test result due to skip_publishing=true');
|
||||||
|
}
|
||||||
|
|
||||||
// make conclusion consumable by downstream actions
|
// make conclusion consumable by downstream actions
|
||||||
core.setOutput('conclusion', conclusion);
|
core.setOutput('conclusion', conclusion);
|
||||||
|
|
||||||
const octokit = new github.GitHub(githubToken);
|
|
||||||
await octokit.checks.create(createCheckRequest);
|
|
||||||
|
|
||||||
// optionally fail the action if tests fail
|
// optionally fail the action if tests fail
|
||||||
if (failOnFailedTests && conclusion !== 'success') {
|
if (failOnFailedTests && conclusion !== 'success') {
|
||||||
core.setFailed(`There were ${annotations.length} failed tests`);
|
core.setFailed(`There were ${annotations.length} failed tests`);
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ const finishedWithFailures = {
|
||||||
status: 'completed',
|
status: 'completed',
|
||||||
conclusion: 'failure',
|
conclusion: 'failure',
|
||||||
output: {
|
output: {
|
||||||
title: '17 tests run, 1 skipped, 11 failed.',
|
title: '20 tests run, 1 skipped, 13 failed.',
|
||||||
summary: '',
|
summary: '',
|
||||||
annotations: [
|
annotations: [
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 39,
|
start_line: 39,
|
||||||
end_line: 39,
|
end_line: 39,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -22,7 +22,7 @@ const finishedWithFailures = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 49,
|
start_line: 49,
|
||||||
end_line: 49,
|
end_line: 49,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -35,7 +35,7 @@ const finishedWithFailures = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 57,
|
start_line: 57,
|
||||||
end_line: 57,
|
end_line: 57,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -48,7 +48,7 @@ const finishedWithFailures = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 18,
|
start_line: 18,
|
||||||
end_line: 18,
|
end_line: 18,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -61,7 +61,7 @@ const finishedWithFailures = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 32,
|
start_line: 32,
|
||||||
end_line: 32,
|
end_line: 32,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -74,7 +74,7 @@ const finishedWithFailures = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 25,
|
start_line: 25,
|
||||||
end_line: 25,
|
end_line: 25,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -88,7 +88,7 @@ const finishedWithFailures = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:
|
path:
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java',
|
||||||
start_line: 66,
|
start_line: 66,
|
||||||
end_line: 66,
|
end_line: 66,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -100,7 +100,31 @@ const finishedWithFailures = {
|
||||||
"action.surefire.report.email.InvalidEmailAddressException: Invalid email address '.user@host.com'\n\tat action.surefire.report.email.EmailAddressTest.expectException(EmailAddressTest.java:74)\n\tat action.surefire.report.email.EmailAddressTest.shouldNotAllowDotsInWeirdPlaces(EmailAddressTest.java:66)"
|
"action.surefire.report.email.InvalidEmailAddressException: Invalid email address '.user@host.com'\n\tat action.surefire.report.email.EmailAddressTest.expectException(EmailAddressTest.java:74)\n\tat action.surefire.report.email.EmailAddressTest.shouldNotAllowDotsInWeirdPlaces(EmailAddressTest.java:66)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tests/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
path:
|
||||||
|
'integration-tests/maven/evil_twins/src/test/java/action/surefire/report/twin/second/TwinTest.java',
|
||||||
|
start_line: 13,
|
||||||
|
end_line: 13,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'TwinTest.should_always_fail',
|
||||||
|
message: "Expected: \"Good Twin\"\n but: was \"Evil Twin\"",
|
||||||
|
raw_details:
|
||||||
|
"java.lang.AssertionError: \n\nExpected: \"Good Twin\"\n but: was \"Evil Twin\"\n\tat action.surefire.report.twin.second.TwinTest.should_always_fail(TwinTest.java:13)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'integration-tests/maven/flakes/src/test/java/action/surefire/report/calc/AllOkWithFlakesTest.java',
|
||||||
|
start_line: 1,
|
||||||
|
end_line: 1,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'AllOkWithFlakesTest.firstTryFailSecondTrySuccess',
|
||||||
|
message: 'firstTryFailSecondTrySuccess',
|
||||||
|
raw_details: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'integration-tests/maven/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
||||||
start_line: 27,
|
start_line: 27,
|
||||||
end_line: 27,
|
end_line: 27,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -113,7 +137,7 @@ const finishedWithFailures = {
|
||||||
'java.lang.AssertionError: unexpected exception type thrown; expected:<java.lang.IllegalStateException> but was:<java.lang.IllegalArgumentException>\n\tat action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)\nCaused by: java.lang.IllegalArgumentException: Amount must have max 2 non-zero decimal places\n\tat action.surefire.report.calc.CalcUtilsTest.scale(CalcUtilsTest.kt:31)\n\tat action.surefire.report.calc.CalcUtilsTest.access$scale(CalcUtilsTest.kt:9)\n\tat action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)'
|
'java.lang.AssertionError: unexpected exception type thrown; expected:<java.lang.IllegalStateException> but was:<java.lang.IllegalArgumentException>\n\tat action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)\nCaused by: java.lang.IllegalArgumentException: Amount must have max 2 non-zero decimal places\n\tat action.surefire.report.calc.CalcUtilsTest.scale(CalcUtilsTest.kt:31)\n\tat action.surefire.report.calc.CalcUtilsTest.access$scale(CalcUtilsTest.kt:9)\n\tat action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tests/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
path: 'integration-tests/maven/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
||||||
start_line: 15,
|
start_line: 15,
|
||||||
end_line: 15,
|
end_line: 15,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -125,7 +149,7 @@ const finishedWithFailures = {
|
||||||
'java.lang.AssertionError: \n\nExpected: <100.10>\n but: was <100.11>\n\tat action.surefire.report.calc.CalcUtilsTest.test scale(CalcUtilsTest.kt:15)'
|
'java.lang.AssertionError: \n\nExpected: <100.10>\n but: was <100.11>\n\tat action.surefire.report.calc.CalcUtilsTest.test scale(CalcUtilsTest.kt:15)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tests/utils/src/test/java/action/surefire/report/calc/StringUtilsTest.java',
|
path: 'integration-tests/maven/utils/src/test/java/action/surefire/report/calc/StringUtilsTest.java',
|
||||||
start_line: 27,
|
start_line: 27,
|
||||||
end_line: 27,
|
end_line: 27,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -138,7 +162,7 @@ const finishedWithFailures = {
|
||||||
'java.lang.AssertionError: \n\nExpected: (an instance of java.lang.IllegalArgumentException and exception with message a string containing "This is unexpected")\n but: exception with message a string containing "This is unexpected" message was "Input=\'\' didn\'t match condition."\nStacktrace was: java.lang.IllegalArgumentException: Input=\'\' didn\'t match condition.\n\tat action.surefire.report.calc.StringUtils.requireNotBlank(StringUtils.java:25)\n\tat action.surefire.report.calc.StringUtils.requireNotBlank(StringUtils.java:18)\n\tat action.surefire.report.calc.StringUtilsTest.require_fail(StringUtilsTest.java:27)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.lang.reflect.Method.invoke(Method.java:498)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n\tat org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:258)\n\tat org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\n\tat org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)\n\tat org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)\n\tat org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)\n\tat org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:413)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)\n\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)\n\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)\n\tat org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)\n\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)'
|
'java.lang.AssertionError: \n\nExpected: (an instance of java.lang.IllegalArgumentException and exception with message a string containing "This is unexpected")\n but: exception with message a string containing "This is unexpected" message was "Input=\'\' didn\'t match condition."\nStacktrace was: java.lang.IllegalArgumentException: Input=\'\' didn\'t match condition.\n\tat action.surefire.report.calc.StringUtils.requireNotBlank(StringUtils.java:25)\n\tat action.surefire.report.calc.StringUtils.requireNotBlank(StringUtils.java:18)\n\tat action.surefire.report.calc.StringUtilsTest.require_fail(StringUtilsTest.java:27)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.lang.reflect.Method.invoke(Method.java:498)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n\tat org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:258)\n\tat org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\n\tat org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)\n\tat org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)\n\tat org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)\n\tat org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:413)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)\n\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)\n\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)\n\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)\n\tat org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)\n\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tests/utils/src/test/java/action/surefire/report/calc/StringUtilsTest.java',
|
path: 'integration-tests/maven/utils/src/test/java/action/surefire/report/calc/StringUtilsTest.java',
|
||||||
start_line: 20,
|
start_line: 20,
|
||||||
end_line: 20,
|
end_line: 20,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,15 @@ const {
|
||||||
|
|
||||||
jest.setTimeout(20000);
|
jest.setTimeout(20000);
|
||||||
|
|
||||||
let inputs = {};
|
let inputs;
|
||||||
let outputs = {};
|
let outputs;
|
||||||
let failed = null;
|
let failed;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
inputs = {};
|
||||||
|
outputs = {};
|
||||||
|
failed = null;
|
||||||
|
});
|
||||||
|
|
||||||
describe('action should work', () => {
|
describe('action should work', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
|
@ -37,6 +43,7 @@ describe('action should work', () => {
|
||||||
jest.spyOn(core, 'debug').mockImplementation(jest.fn());
|
jest.spyOn(core, 'debug').mockImplementation(jest.fn());
|
||||||
|
|
||||||
github.context.payload.pull_request = {
|
github.context.payload.pull_request = {
|
||||||
|
id: 1,
|
||||||
html_url: 'https://github.com/scacap/action-surefire-report',
|
html_url: 'https://github.com/scacap/action-surefire-report',
|
||||||
head: { sha: 'sha123' }
|
head: { sha: 'sha123' }
|
||||||
};
|
};
|
||||||
|
|
@ -55,7 +62,8 @@ describe('action should work', () => {
|
||||||
report_paths: '**/surefire-reports/TEST-*.xml, **/failsafe-reports/TEST-*.xml',
|
report_paths: '**/surefire-reports/TEST-*.xml, **/failsafe-reports/TEST-*.xml',
|
||||||
github_token: 'GITHUB_TOKEN',
|
github_token: 'GITHUB_TOKEN',
|
||||||
check_name: 'Test Report',
|
check_name: 'Test Report',
|
||||||
fail_if_no_tests: 'true'
|
fail_if_no_tests: 'true',
|
||||||
|
skip_publishing: 'false'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reset outputs
|
// Reset outputs
|
||||||
|
|
@ -99,6 +107,24 @@ describe('action should work', () => {
|
||||||
expect(failed).toBeNull();
|
expect(failed).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should send all ok if tests were flaky and ignore_flaky_test is true', async () => {
|
||||||
|
inputs.report_paths = '**/surefire-reports/TEST-*AllOkWithFlakesTest.xml';
|
||||||
|
inputs.ignore_flaky_tests = 'true';
|
||||||
|
let request = null;
|
||||||
|
const scope = nock('https://api.github.com')
|
||||||
|
.post('/repos/scacap/action-surefire-report/check-runs', body => {
|
||||||
|
request = body;
|
||||||
|
return body;
|
||||||
|
})
|
||||||
|
.reply(200, {});
|
||||||
|
await action();
|
||||||
|
scope.done();
|
||||||
|
|
||||||
|
expect(request).toStrictEqual(finishedSuccess);
|
||||||
|
expect(outputs).toHaveProperty('conclusion', 'success');
|
||||||
|
expect(failed).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('should send failure if no test results were found', async () => {
|
it('should send failure if no test results were found', async () => {
|
||||||
inputs.report_paths = '**/xxx/*.xml';
|
inputs.report_paths = '**/xxx/*.xml';
|
||||||
let request = null;
|
let request = null;
|
||||||
|
|
@ -149,6 +175,14 @@ describe('action should work', () => {
|
||||||
scope.done();
|
scope.done();
|
||||||
|
|
||||||
expect(request).toStrictEqual(masterSuccess);
|
expect(request).toStrictEqual(masterSuccess);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not send report on skip_publishing', async () => {
|
||||||
|
inputs.skip_publishing = 'true';
|
||||||
|
|
||||||
|
// nock error if the request is sent
|
||||||
|
|
||||||
|
await action();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with option fail_on_test_failures', () => {
|
describe('with option fail_on_test_failures', () => {
|
||||||
|
|
@ -175,7 +209,49 @@ describe('action should work', () => {
|
||||||
await action();
|
await action();
|
||||||
scope.done();
|
scope.done();
|
||||||
|
|
||||||
expect(failed).toBe('There were 11 failed tests');
|
expect(failed).toBe('There were 13 failed tests');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with option create_check=false', () => {
|
||||||
|
it('should parse surefire reports and update a check run', async () => {
|
||||||
|
inputs.create_check = 'false';
|
||||||
|
inputs.check_name = 'build';
|
||||||
|
github.context.sha = 'sha123';
|
||||||
|
github.context.job = 'build'
|
||||||
|
|
||||||
|
let request = null;
|
||||||
|
const getRuns = nock('https://api.github.com')
|
||||||
|
.get('/repos/scacap/action-surefire-report/commits/sha123/check-runs?check_name=build&status=in_progress')
|
||||||
|
.reply(200, {
|
||||||
|
check_runs: [
|
||||||
|
{
|
||||||
|
id: 123,
|
||||||
|
output: {
|
||||||
|
title: finishedWithFailures.output.title,
|
||||||
|
summary: finishedWithFailures.output.summary
|
||||||
|
},
|
||||||
|
pull_requests: [
|
||||||
|
{
|
||||||
|
id: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const patchRun = nock('https://api.github.com')
|
||||||
|
.patch('/repos/scacap/action-surefire-report/check-runs/123', body => {
|
||||||
|
request = body;
|
||||||
|
return body;
|
||||||
|
})
|
||||||
|
.reply(200, {});
|
||||||
|
await action();
|
||||||
|
getRuns.done();
|
||||||
|
patchRun.done();
|
||||||
|
|
||||||
|
expect(request).toStrictEqual({output: finishedWithFailures.output});
|
||||||
|
expect(outputs).toHaveProperty('conclusion', 'failure');
|
||||||
|
expect(failed).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
24
action.yml
24
action.yml
|
|
@ -7,10 +7,15 @@ inputs:
|
||||||
github_token:
|
github_token:
|
||||||
description: 'GITHUB_TOKEN'
|
description: 'GITHUB_TOKEN'
|
||||||
required: true
|
required: true
|
||||||
|
default: ${{ github.token }}
|
||||||
report_paths:
|
report_paths:
|
||||||
description: 'surefire/failsafe/junit compatible xml report paths in glob format'
|
description: 'surefire/failsafe/junit compatible xml report paths in glob format'
|
||||||
required: false
|
required: false
|
||||||
default: '**/surefire-reports/TEST-*.xml, **/failsafe-reports/TEST-*.xml'
|
default: '**/surefire-reports/TEST-*.xml, **/failsafe-reports/TEST-*.xml'
|
||||||
|
create_check:
|
||||||
|
description: 'create a new check with annotations'
|
||||||
|
required: false
|
||||||
|
default: 'true'
|
||||||
check_name:
|
check_name:
|
||||||
description: 'check name for test reports'
|
description: 'check name for test reports'
|
||||||
required: false
|
required: false
|
||||||
|
|
@ -26,10 +31,27 @@ inputs:
|
||||||
description: 'fail run if there were no test results found'
|
description: 'fail run if there were no test results found'
|
||||||
required: false
|
required: false
|
||||||
default: 'true'
|
default: 'true'
|
||||||
|
ignore_flaky_tests:
|
||||||
|
description: 'consider flaky tests as success'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
skip_publishing:
|
||||||
|
description: 'skip test report publishing'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
file_name_in_stack_trace:
|
||||||
|
description: 'get filename from stack trace'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
github_base_url:
|
||||||
|
description: 'if you use Github Enterprise, you can set this to the URL of your server (e.g. https://github.myorg.com/api/v3)'
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
outcome:
|
outcome:
|
||||||
description: 'the test outcome, either `success` or `failure`'
|
description: 'the test outcome, either `success` or `failure`'
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node20'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,30 @@
|
||||||
|
const globals = require('globals');
|
||||||
|
const js = require('@eslint/js');
|
||||||
|
const {FlatCompat} = require('@eslint/eslintrc');
|
||||||
|
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = [{
|
||||||
|
ignores: ['dist/*'],
|
||||||
|
}, ...compat.extends('eslint:recommended'), {
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.commonjs,
|
||||||
|
...globals.node,
|
||||||
|
...globals.jest,
|
||||||
|
Atomics: 'readonly',
|
||||||
|
SharedArrayBuffer: 'readonly',
|
||||||
|
},
|
||||||
|
|
||||||
|
ecmaVersion: 2018,
|
||||||
|
sourceType: 'commonjs',
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
indent: 2,
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd" version="3.0" name="pro.taskana.common.api.ListUtilTest" time="0.063" tests="1" errors="0" skipped="0" failures="1">
|
||||||
|
<testcase name="should_SplitListIntoChunks_When_CallingPartitionBasedOnSize" classname="pro.taskana.common.api.ListUtilTest(H2)" time="0.045">
|
||||||
|
<failure type="java.lang.AssertionError"><![CDATA[java.lang.AssertionError:
|
||||||
|
|
||||||
|
Expected size:<11> but was:<10> in:
|
||||||
|
<[[1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
96,
|
||||||
|
97,
|
||||||
|
98,
|
||||||
|
99,
|
||||||
|
100],
|
||||||
|
[101,
|
||||||
|
102,
|
||||||
|
103,
|
||||||
|
104,
|
||||||
|
194,
|
||||||
|
195,
|
||||||
|
196,
|
||||||
|
197,
|
||||||
|
198,
|
||||||
|
199,
|
||||||
|
200],
|
||||||
|
[201,
|
||||||
|
202,
|
||||||
|
997,
|
||||||
|
998,
|
||||||
|
999,
|
||||||
|
1000]]]]><![CDATA[>
|
||||||
|
at pro.taskana.common.api.ListUtilTest.should_SplitListIntoChunks_When_CallingPartitionBasedOnSize(ListUtilTest.java:22)
|
||||||
|
]]></failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="test.MyIntegrationTestSuite" time="751.336" tests="924" errors="0" skipped="0" failures="6">
|
||||||
|
<testcase name="testGetMails" classname="test.MyIntegrationTest" time="0.249">
|
||||||
|
<flakyFailure message="JSON path "$.mails[0].subject" Expected: "MySubject" but: was "YourSubject"" type="java.lang.AssertionError">
|
||||||
|
<stackTrace>java.lang.AssertionError:
|
||||||
|
JSON path "$.mails[0].subject"
|
||||||
|
Expected: "MySubject"
|
||||||
|
but: was "YourSubject"
|
||||||
|
at test.MyIntegrationTest.testGetMails(MyIntegrationTest.java:43)
|
||||||
|
</stackTrace>
|
||||||
|
<system-out><![CDATA[2021-02-05 09:11:05.249 INFO [,,,] 2909 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
||||||
|
2021-02-05 09:11:05.249 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
||||||
|
2021-02-05 09:11:05.255 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 6 ms
|
||||||
|
]]></system-out>
|
||||||
|
</flakyFailure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="shouldReturnBadRequestIfDocumentTypeIsInvalid" classname="test.DocumentUploadIntegrationTest" time="0.577">
|
||||||
|
<failure message="Status expected:<400> but was:<403>" type="java.lang.AssertionError"><![CDATA[java.lang.AssertionError: Status expected:<400> but was:<403>
|
||||||
|
at test.DocumentUploadIntegrationTest.shouldReturnBadRequestIfDocumentTypeIsInvalid(DocumentUploadIntegrationTest.java:33)
|
||||||
|
]]></failure>
|
||||||
|
<system-out><![CDATA[2021-02-05 09:11:11.090 INFO [,,,] 2909 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
||||||
|
2021-02-05 09:11:11.091 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
||||||
|
2021-02-05 09:11:11.096 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 5 ms
|
||||||
|
]]></system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="shouldReturnSuccessResponse" classname="test.DocumentUploadIntegrationTest" time="0.711">
|
||||||
|
<flakyFailure message="Status expected:<200> but was:<403>" type="java.lang.AssertionError">
|
||||||
|
<stackTrace><![CDATA[java.lang.AssertionError: Status expected:<200> but was:<403>
|
||||||
|
at test.DocumentUploadIntegrationTest.shouldReturnSuccessResponse(DocumentUploadIntegrationTest.java:23)
|
||||||
|
]]></stackTrace>
|
||||||
|
<system-out><![CDATA[2021-02-05 09:11:11.668 INFO [,,,] 2909 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
||||||
|
2021-02-05 09:11:11.668 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
||||||
|
2021-02-05 09:11:11.673 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 5 ms
|
||||||
|
]]></system-out>
|
||||||
|
</flakyFailure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="shouldReturnBadRequestIfDocumentSizeIsZero" classname="test.DocumentUploadIntegrationTest" time="0.573">
|
||||||
|
<failure message="Status expected:<400> but was:<403>" type="java.lang.AssertionError"><![CDATA[java.lang.AssertionError: Status expected:<400> but was:<403>
|
||||||
|
at test.DocumentUploadIntegrationTest.shouldReturnBadRequestIfDocumentSizeIsZero(DocumentUploadIntegrationTest.java:47)
|
||||||
|
]]></failure>
|
||||||
|
<system-out><![CDATA[2021-02-05 09:11:12.244 INFO [,,,] 2909 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
||||||
|
2021-02-05 09:11:12.244 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
||||||
|
2021-02-05 09:11:12.249 INFO [,,,] 2909 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 5 ms
|
||||||
|
]]></system-out>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="jacksonShouldHandleTypesCorrectly" classname="test.TestResourceIntegrationTest" time="0.018"/>
|
||||||
|
</testsuite>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
module github.com/ScaCap/action-surefire-report
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.8.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPassing(t *testing.T) {
|
||||||
|
t.Log("passing test")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailing(t *testing.T) {
|
||||||
|
t.Error("failing test")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
import "github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
func TestFailing(t *testing.T) {
|
||||||
|
assert.Equal(t, "1", "2")
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>tests</artifactId>
|
||||||
|
<groupId>action.surefire.report</groupId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>evil_twins</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package action.surefire.report.twin.first;
|
||||||
|
|
||||||
|
public class Twin {
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return "Good Twin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package action.surefire.report.twin.second;
|
||||||
|
|
||||||
|
public class Twin {
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return "Evil Twin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package action.surefire.report.twin.first;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TwinTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_always_pass() {
|
||||||
|
Twin goodTwin = new Twin();
|
||||||
|
assertThat(goodTwin.getName(), equalTo("Good Twin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package action.surefire.report.twin.second;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TwinTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_always_fail() {
|
||||||
|
Twin evilTwin = new Twin();
|
||||||
|
assertThat(evilTwin.getName(), equalTo("Good Twin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>tests</artifactId>
|
||||||
|
<groupId>action.surefire.report</groupId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>flakes</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<argLine>-Duser.language=en</argLine>
|
||||||
|
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||||
|
<testFailureIgnore>true</testFailureIgnore>
|
||||||
|
<rerunFailingTestsCount>1</rerunFailingTestsCount>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>compile</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>testCompile</id>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package action.surefire.report.calc;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class AllOkWithFlakesTest {
|
||||||
|
|
||||||
|
private static boolean failTest = true;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void firstTryFailSecondTrySuccess() {
|
||||||
|
if(failTest) {
|
||||||
|
failTest = false;
|
||||||
|
assertTrue(false);
|
||||||
|
} else {
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>utils</module>
|
<module>utils</module>
|
||||||
<module>email</module>
|
<module>email</module>
|
||||||
|
<module>evil_twins</module>
|
||||||
|
<module>flakes</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
@ -19,6 +21,7 @@
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<kotlin.version>1.3.72</kotlin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
@ -48,7 +51,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>2.5</version>
|
<version>2.14.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
|
|
@ -59,7 +62,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.7</version>
|
<version>3.18.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
@ -73,8 +76,22 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<argLine>-Duser.language=en</argLine>
|
<argLine>-Duser.language=en</argLine>
|
||||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||||
|
<testFailureIgnore>true</testFailureIgnore>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>2.22.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
@ -8,10 +8,6 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>utils</artifactId>
|
<artifactId>utils</artifactId>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<kotlin.version>1.3.72</kotlin.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
|
|
@ -34,15 +30,10 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
<artifactId>kotlin-test</artifactId>
|
<artifactId>kotlin-test-junit</artifactId>
|
||||||
<version>${kotlin.version}</version>
|
<version>${kotlin.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
@ -48,4 +48,4 @@ public class StringUtilsTest {
|
||||||
thrown.expectMessage("Input='' didn't match condition.");
|
thrown.expectMessage("Input='' didn't match condition.");
|
||||||
StringUtils.requireNotBlank("");
|
StringUtils.requireNotBlank("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
|
|
@ -31,18 +31,20 @@
|
||||||
"titleTemplate": "{title}"
|
"titleTemplate": "{title}"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "1.2.6",
|
"@actions/core": "1.10.1",
|
||||||
"@actions/github": "2.2.0",
|
"@actions/github": "6.0.0",
|
||||||
"@actions/glob": "0.1.0",
|
"@actions/glob": "0.5.0",
|
||||||
|
"@octokit/plugin-retry": "6.0.1",
|
||||||
|
"@octokit/rest": "20.0.2",
|
||||||
"xml-js": "1.6.11"
|
"xml-js": "1.6.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@octokit/fixtures": "21.0.5",
|
"@octokit/fixtures": "23.1.1",
|
||||||
"@zeit/ncc": "0.22.1",
|
"@vercel/ncc": "0.38.3",
|
||||||
"enzyme": "3.11.0",
|
"enzyme": "3.11.0",
|
||||||
"eslint": "7.0.0",
|
"eslint": "9.34.0",
|
||||||
"jest": "26.0.1",
|
"jest": "29.7.0",
|
||||||
"jest-junit": "10.0.0",
|
"jest-junit": "16.0.0",
|
||||||
"nock": "12.0.3"
|
"nock": "14.0.0-beta.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
96
utils.js
96
utils.js
|
|
@ -3,21 +3,31 @@ const core = require('@actions/core');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const parser = require('xml-js');
|
const parser = require('xml-js');
|
||||||
|
|
||||||
const resolveFileAndLine = (file, classname, output) => {
|
const resolveFileAndLine = (file, classname, output, isFilenameInOutput) => {
|
||||||
const filename = file ? file : classname.split('.').slice(-1)[0];
|
// extract filename from classname and remove suffix
|
||||||
const matches = output.match(new RegExp(`${filename}.*?:\\d+`, 'g'));
|
let filename;
|
||||||
if (!matches) return { filename: filename, line: 1 };
|
let filenameWithPackage;
|
||||||
|
if (isFilenameInOutput) {
|
||||||
|
filename = output.split(':')[0].trim();
|
||||||
|
filenameWithPackage = filename;
|
||||||
|
} else {
|
||||||
|
filename = file ? file : classname.split('.').slice(-1)[0].split('(')[0];
|
||||||
|
filenameWithPackage = classname.replace(/\./g, '/');
|
||||||
|
}
|
||||||
|
const escapedFilename = filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
const matches = output.match(new RegExp(`${escapedFilename}.*?:\\d+`, 'g'));
|
||||||
|
if (!matches) return {filename: filename, filenameWithPackage: filenameWithPackage, line: 1};
|
||||||
|
|
||||||
const [lastItem] = matches.slice(-1);
|
const [lastItem] = matches.slice(-1);
|
||||||
const [, line] = lastItem.split(':');
|
const [, line] = lastItem.split(':');
|
||||||
core.debug(`Resolved file ${filename} and line ${line}`);
|
core.debug(`Resolved file ${filenameWithPackage} with name ${filename} and line ${line}`);
|
||||||
|
|
||||||
return { filename, line: parseInt(line) };
|
return {filename, filenameWithPackage, line: parseInt(line)};
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolvePath = async filename => {
|
const resolvePath = async filenameWithPackage => {
|
||||||
core.debug(`Resolving path for ${filename}`);
|
core.debug(`Resolving path for ${filenameWithPackage}`);
|
||||||
const globber = await glob.create(`**/${filename}.*`, { followSymbolicLinks: false });
|
const globber = await glob.create([`**/${filenameWithPackage}.*`, `**/${filenameWithPackage}`].join('\n'), {followSymbolicLinks: false});
|
||||||
const results = await globber.glob();
|
const results = await globber.glob();
|
||||||
core.debug(`Matched files: ${results}`);
|
core.debug(`Matched files: ${results}`);
|
||||||
const searchPath = globber.getSearchPaths()[0];
|
const searchPath = globber.getSearchPaths()[0];
|
||||||
|
|
@ -25,11 +35,11 @@ const resolvePath = async filename => {
|
||||||
let path = '';
|
let path = '';
|
||||||
if (results.length) {
|
if (results.length) {
|
||||||
// skip various temp folders
|
// skip various temp folders
|
||||||
const found = results.find(r => !r.includes('__pycache__'));
|
const found = results.find(r => !r.includes('__pycache__') && !r.endsWith('.class'));
|
||||||
if (found) path = found.slice(searchPath.length + 1);
|
if (found) path = found.slice(searchPath.length + 1);
|
||||||
else path = filename;
|
else path = filenameWithPackage;
|
||||||
} else {
|
} else {
|
||||||
path = filename;
|
path = filenameWithPackage;
|
||||||
}
|
}
|
||||||
core.debug(`Resolved path: ${path}`);
|
core.debug(`Resolved path: ${path}`);
|
||||||
|
|
||||||
|
|
@ -40,7 +50,20 @@ const resolvePath = async filename => {
|
||||||
return canonicalPath;
|
return canonicalPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
async function parseFile(file) {
|
function getTestsuites(report) {
|
||||||
|
if (report.testsuite) {
|
||||||
|
return [report.testsuite];
|
||||||
|
}
|
||||||
|
if (!report.testsuites || !report.testsuites.testsuite) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (Array.isArray(report.testsuites.testsuite)) {
|
||||||
|
return report.testsuites.testsuite;
|
||||||
|
}
|
||||||
|
return [report.testsuites.testsuite];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function parseFile(file, isFilenameInStackTrace, ignoreFlakyTests) {
|
||||||
core.debug(`Parsing file ${file}`);
|
core.debug(`Parsing file ${file}`);
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let skipped = 0;
|
let skipped = 0;
|
||||||
|
|
@ -48,12 +71,11 @@ async function parseFile(file) {
|
||||||
|
|
||||||
const data = await fs.promises.readFile(file);
|
const data = await fs.promises.readFile(file);
|
||||||
|
|
||||||
const report = JSON.parse(parser.xml2json(data, { compact: true }));
|
const report = JSON.parse(parser.xml2json(data, {compact: true}));
|
||||||
const testsuites = report.testsuite
|
core.debug(`parsed report: ${JSON.stringify(report)}`);
|
||||||
? [report.testsuite]
|
|
||||||
: Array.isArray(report.testsuites.testsuite)
|
const testsuites = getTestsuites(report);
|
||||||
? report.testsuites.testsuite
|
core.debug(`test suites: ${JSON.stringify(testsuites)}`);
|
||||||
: [report.testsuites.testsuite];
|
|
||||||
|
|
||||||
for (const testsuite of testsuites) {
|
for (const testsuite of testsuites) {
|
||||||
const testcases = Array.isArray(testsuite.testcase)
|
const testcases = Array.isArray(testsuite.testcase)
|
||||||
|
|
@ -64,32 +86,40 @@ async function parseFile(file) {
|
||||||
for (const testcase of testcases) {
|
for (const testcase of testcases) {
|
||||||
count++;
|
count++;
|
||||||
if (testcase.skipped) skipped++;
|
if (testcase.skipped) skipped++;
|
||||||
if (testcase.failure || testcase.error) {
|
if (testcase.failure || (testcase.flakyFailure && !ignoreFlakyTests) || testcase.error) {
|
||||||
const stackTrace = (
|
let testcaseData =
|
||||||
(testcase.failure && testcase.failure._cdata) ||
|
(testcase.failure && testcase.failure._cdata) ||
|
||||||
(testcase.failure && testcase.failure._text) ||
|
(testcase.failure && testcase.failure._text) ||
|
||||||
|
(testcase.flakyFailure && testcase.flakyFailure._cdata) ||
|
||||||
|
(testcase.flakyFailure && testcase.flakyFailure._text) ||
|
||||||
(testcase.error && testcase.error._cdata) ||
|
(testcase.error && testcase.error._cdata) ||
|
||||||
(testcase.error && testcase.error._text) ||
|
(testcase.error && testcase.error._text) ||
|
||||||
''
|
'';
|
||||||
).trim();
|
testcaseData = Array.isArray(testcaseData) ? testcaseData : [testcaseData];
|
||||||
|
const stackTrace = (testcaseData.length ? testcaseData.join('') : '').trim();
|
||||||
|
|
||||||
const message = (
|
const message = (
|
||||||
(testcase.failure &&
|
(testcase.failure &&
|
||||||
testcase.failure._attributes &&
|
testcase.failure._attributes &&
|
||||||
testcase.failure._attributes.message) ||
|
testcase.failure._attributes.message) ||
|
||||||
|
(testcase.flakyFailure &&
|
||||||
|
testcase.flakyFailure._attributes &&
|
||||||
|
testcase.flakyFailure._attributes.message) ||
|
||||||
(testcase.error &&
|
(testcase.error &&
|
||||||
testcase.error._attributes &&
|
testcase.error._attributes &&
|
||||||
testcase.error._attributes.message) ||
|
testcase.error._attributes.message) ||
|
||||||
stackTrace.split('\n').slice(0, 2).join('\n')
|
stackTrace.split('\n').slice(0, 2).join('\n') ||
|
||||||
|
testcase._attributes.name
|
||||||
).trim();
|
).trim();
|
||||||
|
|
||||||
const { filename, line } = resolveFileAndLine(
|
const {filename, filenameWithPackage, line} = resolveFileAndLine(
|
||||||
testcase._attributes.file,
|
testcase._attributes.file,
|
||||||
testcase._attributes.classname,
|
testcase._attributes.classname,
|
||||||
stackTrace
|
stackTrace,
|
||||||
|
isFilenameInStackTrace
|
||||||
);
|
);
|
||||||
|
|
||||||
const path = await resolvePath(filename);
|
const path = await resolvePath(filenameWithPackage);
|
||||||
const title = `${filename}.${testcase._attributes.name}`;
|
const title = `${filename}.${testcase._attributes.name}`;
|
||||||
core.info(`${path}:${line} | ${message.replace(/\n/g, ' ')}`);
|
core.info(`${path}:${line} | ${message.replace(/\n/g, ' ')}`);
|
||||||
|
|
||||||
|
|
@ -107,22 +137,22 @@ async function parseFile(file) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { count, skipped, annotations };
|
return {count, skipped, annotations};
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseTestReports = async reportPaths => {
|
const parseTestReports = async (reportPaths, isFilenameInStackTrace, ignoreFlakyTests) => {
|
||||||
const globber = await glob.create(reportPaths, { followSymbolicLinks: false });
|
const globber = await glob.create(reportPaths, {followSymbolicLinks: false});
|
||||||
let annotations = [];
|
let annotations = [];
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let skipped = 0;
|
let skipped = 0;
|
||||||
for await (const file of globber.globGenerator()) {
|
for await (const file of globber.globGenerator()) {
|
||||||
const { count: c, skipped: s, annotations: a } = await parseFile(file);
|
const {count: c, skipped: s, annotations: a} = await parseFile(file, isFilenameInStackTrace, ignoreFlakyTests);
|
||||||
if (c == 0) continue;
|
if (c === 0) continue;
|
||||||
count += c;
|
count += c;
|
||||||
skipped += s;
|
skipped += s;
|
||||||
annotations = annotations.concat(a);
|
annotations = annotations.concat(a);
|
||||||
}
|
}
|
||||||
return { count, skipped, annotations };
|
return {count, skipped, annotations};
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = { resolveFileAndLine, resolvePath, parseFile, parseTestReports };
|
module.exports = { resolveFileAndLine, resolvePath, parseFile, parseTestReports };
|
||||||
|
|
|
||||||
214
utils.test.js
214
utils.test.js
|
|
@ -15,7 +15,8 @@ describe('resolveFileAndLine', () => {
|
||||||
action.surefire.report.email.InvalidEmailAddressException: Invalid email address 'user@ñandú.com.ar'
|
action.surefire.report.email.InvalidEmailAddressException: Invalid email address 'user@ñandú.com.ar'
|
||||||
at action.surefire.report.email.EmailAddressTest.expectException(EmailAddressTest.java:74)
|
at action.surefire.report.email.EmailAddressTest.expectException(EmailAddressTest.java:74)
|
||||||
at action.surefire.report.email.EmailAddressTest.shouldNotContainInternationalizedHostNames(EmailAddressTest.java:39)
|
at action.surefire.report.email.EmailAddressTest.shouldNotContainInternationalizedHostNames(EmailAddressTest.java:39)
|
||||||
`
|
`,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
expect(filename).toBe('EmailAddressTest');
|
expect(filename).toBe('EmailAddressTest');
|
||||||
expect(line).toBe(39);
|
expect(line).toBe(39);
|
||||||
|
|
@ -32,7 +33,8 @@ Caused by: java.lang.IllegalArgumentException: Amount must have max 2 non-zero d
|
||||||
at action.surefire.report.calc.CalcUtilsTest.scale(CalcUtilsTest.kt:31)
|
at action.surefire.report.calc.CalcUtilsTest.scale(CalcUtilsTest.kt:31)
|
||||||
at action.surefire.report.calc.CalcUtilsTest.access$scale(CalcUtilsTest.kt:9)
|
at action.surefire.report.calc.CalcUtilsTest.access$scale(CalcUtilsTest.kt:9)
|
||||||
at action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)
|
at action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)
|
||||||
`
|
`,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
expect(filename).toBe('CalcUtilsTest');
|
expect(filename).toBe('CalcUtilsTest');
|
||||||
expect(line).toBe(27);
|
expect(line).toBe(27);
|
||||||
|
|
@ -55,7 +57,8 @@ Stacktrace was: java.lang.IllegalArgumentException: Input='' didn't match condit
|
||||||
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
|
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
|
||||||
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
|
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
|
||||||
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
|
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
|
||||||
`
|
`,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
expect(filename).toBe('StringUtilsTest');
|
expect(filename).toBe('StringUtilsTest');
|
||||||
expect(line).toBe(26);
|
expect(line).toBe(26);
|
||||||
|
|
@ -73,38 +76,55 @@ event = { 'attr': 'test'}
|
||||||
E AttributeError: 'dict' object has no attribute 'attr'
|
E AttributeError: 'dict' object has no attribute 'attr'
|
||||||
|
|
||||||
test.py:14: AttributeError
|
test.py:14: AttributeError
|
||||||
`
|
`,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
expect(filename).toBe('test.py');
|
expect(filename).toBe('test.py');
|
||||||
expect(line).toBe(14);
|
expect(line).toBe(14);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should parse correctly filename and line for a Go file when filename is in stack trace', () => {
|
||||||
|
const {filename, line} = resolveFileAndLine(
|
||||||
|
null,
|
||||||
|
'com/ScaCap/action-surefire-report',
|
||||||
|
'main_test.go:8: failing test',
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(filename).toBe('main_test.go');
|
||||||
|
expect(line).toBe(8);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('resolvePath', () => {
|
describe('resolvePath', () => {
|
||||||
it('should find correct file for Java filename', async () => {
|
it('should find correct file for Java filename', async () => {
|
||||||
const path = await resolvePath('EmailAddressTest');
|
const path = await resolvePath('EmailAddressTest');
|
||||||
expect(path).toBe(
|
expect(path).toBe(
|
||||||
'tests/email/src/test/java/action/surefire/report/email/EmailAddressTest.java'
|
'integration-tests/maven/email/src/test/java/action/surefire/report/email/EmailAddressTest.java'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find correct file for Kotlin filename', async () => {
|
it('should find correct file for Kotlin filename', async () => {
|
||||||
const path = await resolvePath('CalcUtilsTest');
|
const path = await resolvePath('CalcUtilsTest');
|
||||||
expect(path).toBe('tests/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt');
|
expect(path).toBe('integration-tests/maven/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find correct file when extension is included', async () => {
|
||||||
|
const path = await resolvePath('CalcUtilsTest.kt');
|
||||||
|
expect(path).toBe('integration-tests/maven/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parseFile', () => {
|
describe('parseFile', () => {
|
||||||
it('should parse CalcUtils results', async () => {
|
it('should parse CalcUtils results', async () => {
|
||||||
const { count, skipped, annotations } = await parseFile(
|
const { count, skipped, annotations } = await parseFile(
|
||||||
'tests/utils/target/surefire-reports/TEST-action.surefire.report.calc.CalcUtilsTest.xml'
|
'integration-tests/maven/utils/target/surefire-reports/TEST-action.surefire.report.calc.CalcUtilsTest.xml'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(count).toBe(2);
|
expect(count).toBe(2);
|
||||||
expect(skipped).toBe(0);
|
expect(skipped).toBe(0);
|
||||||
expect(annotations).toStrictEqual([
|
expect(annotations).toStrictEqual([
|
||||||
{
|
{
|
||||||
path: 'tests/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
path: 'integration-tests/maven/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
||||||
start_line: 27,
|
start_line: 27,
|
||||||
end_line: 27,
|
end_line: 27,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -113,11 +133,10 @@ describe('parseFile', () => {
|
||||||
title: 'CalcUtilsTest.test error handling',
|
title: 'CalcUtilsTest.test error handling',
|
||||||
message:
|
message:
|
||||||
'unexpected exception type thrown; expected:<java.lang.IllegalStateException> but was:<java.lang.IllegalArgumentException>',
|
'unexpected exception type thrown; expected:<java.lang.IllegalStateException> but was:<java.lang.IllegalArgumentException>',
|
||||||
raw_details:
|
raw_details: expect.stringContaining('at action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)')
|
||||||
'java.lang.AssertionError: unexpected exception type thrown; expected:<java.lang.IllegalStateException> but was:<java.lang.IllegalArgumentException>\n\tat action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)\nCaused by: java.lang.IllegalArgumentException: Amount must have max 2 non-zero decimal places\n\tat action.surefire.report.calc.CalcUtilsTest.scale(CalcUtilsTest.kt:31)\n\tat action.surefire.report.calc.CalcUtilsTest.access$scale(CalcUtilsTest.kt:9)\n\tat action.surefire.report.calc.CalcUtilsTest.test error handling(CalcUtilsTest.kt:27)'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tests/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
path: 'integration-tests/maven/utils/src/test/java/action/surefire/report/calc/CalcUtilsTest.kt',
|
||||||
start_line: 15,
|
start_line: 15,
|
||||||
end_line: 15,
|
end_line: 15,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -125,19 +144,18 @@ describe('parseFile', () => {
|
||||||
annotation_level: 'failure',
|
annotation_level: 'failure',
|
||||||
title: 'CalcUtilsTest.test scale',
|
title: 'CalcUtilsTest.test scale',
|
||||||
message: 'Expected: <100.10>\n but: was <100.11>',
|
message: 'Expected: <100.10>\n but: was <100.11>',
|
||||||
raw_details:
|
raw_details: expect.stringContaining('at action.surefire.report.calc.CalcUtilsTest.test scale(CalcUtilsTest.kt:15)')
|
||||||
'java.lang.AssertionError: \n\nExpected: <100.10>\n but: was <100.11>\n\tat action.surefire.report.calc.CalcUtilsTest.test scale(CalcUtilsTest.kt:15)'
|
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should parse pytest results', async () => {
|
it('should parse pytest results', async () => {
|
||||||
const { count, skipped, annotations } = await parseFile('python/report.xml');
|
const { count, skipped, annotations } = await parseFile('integration-tests/python/report.xml');
|
||||||
|
|
||||||
expect(count).toBe(3);
|
expect(count).toBe(3);
|
||||||
expect(skipped).toBe(0);
|
expect(skipped).toBe(0);
|
||||||
expect(annotations).toStrictEqual([
|
expect(annotations).toStrictEqual([
|
||||||
{
|
{
|
||||||
path: 'python/test_sample.py',
|
path: 'integration-tests/python/test_sample.py',
|
||||||
start_line: 10,
|
start_line: 10,
|
||||||
end_line: 10,
|
end_line: 10,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -146,10 +164,10 @@ describe('parseFile', () => {
|
||||||
title: 'test_sample.test_which_fails',
|
title: 'test_sample.test_which_fails',
|
||||||
message: "AssertionError: assert 'test' == 'xyz'\n - xyz\n + test",
|
message: "AssertionError: assert 'test' == 'xyz'\n - xyz\n + test",
|
||||||
raw_details:
|
raw_details:
|
||||||
"def test_which_fails():\n event = { 'attr': 'test'}\n> assert event['attr'] == 'xyz'\nE AssertionError: assert 'test' == 'xyz'\nE - xyz\nE + test\n\npython/test_sample.py:10: AssertionError"
|
"def test_which_fails():\n event = { 'attr': 'test'}\n> assert event['attr'] == 'xyz'\nE AssertionError: assert 'test' == 'xyz'\nE - xyz\nE + test\n\nintegration-tests/python/test_sample.py:10: AssertionError"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'python/test_sample.py',
|
path: 'integration-tests/python/test_sample.py',
|
||||||
start_line: 14,
|
start_line: 14,
|
||||||
end_line: 14,
|
end_line: 14,
|
||||||
start_column: 0,
|
start_column: 0,
|
||||||
|
|
@ -158,7 +176,167 @@ describe('parseFile', () => {
|
||||||
title: 'test_sample.test_with_error',
|
title: 'test_sample.test_with_error',
|
||||||
message: "AttributeError: 'dict' object has no attribute 'attr'",
|
message: "AttributeError: 'dict' object has no attribute 'attr'",
|
||||||
raw_details:
|
raw_details:
|
||||||
"def test_with_error():\n event = { 'attr': 'test'}\n> assert event.attr == 'test'\nE AttributeError: 'dict' object has no attribute 'attr'\n\npython/test_sample.py:14: AttributeError"
|
"def test_with_error():\n event = { 'attr': 'test'}\n> assert event.attr == 'test'\nE AttributeError: 'dict' object has no attribute 'attr'\n\nintegration-tests/python/test_sample.py:14: AttributeError"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('should parse go results', async () => {
|
||||||
|
const {count, skipped, annotations} = await parseFile('integration-tests/go/report.xml', true);
|
||||||
|
|
||||||
|
expect(count).toBe(3);
|
||||||
|
expect(skipped).toBe(0);
|
||||||
|
// noinspection RegExpRepeatedSpace
|
||||||
|
expect(annotations).toStrictEqual([
|
||||||
|
{
|
||||||
|
path: 'integration-tests/go/main_test.go',
|
||||||
|
start_line: 12,
|
||||||
|
end_line: 12,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'main_test.go.TestFailing',
|
||||||
|
message: 'Failed',
|
||||||
|
raw_details: 'main_test.go:12: failing test'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'integration-tests/go/utils/string_test.go',
|
||||||
|
start_line: 7,
|
||||||
|
end_line: 7,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'string_test.go.TestFailing',
|
||||||
|
message: 'Failed',
|
||||||
|
raw_details: expect.stringMatching(new RegExp(`string_test.go:7:
|
||||||
|
\\s*Error Trace:.*action-surefire-report/integration-tests/go/utils/string_test.go:7
|
||||||
|
\\s*Error: \\s*Not equal:
|
||||||
|
\\s*expected: "1"
|
||||||
|
\\s*actual : "2"
|
||||||
|
\\s*
|
||||||
|
\\s*Diff:
|
||||||
|
\\s*--- Expected
|
||||||
|
\\s*\\+\\+\\+ Actual
|
||||||
|
\\s*@@ -1 \\+1 @@
|
||||||
|
\\s*-1
|
||||||
|
\\s*\\+2
|
||||||
|
\\s*Test:\\s*TestFailing`))
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('should parse custom report with details as an array', async () => {
|
||||||
|
const { count, skipped, annotations } = await parseFile(
|
||||||
|
'integration-tests/custom_reports/TEST-pro.taskana.common.api.ListUtilTest-H2.xml'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(count).toBe(1);
|
||||||
|
expect(skipped).toBe(0);
|
||||||
|
expect(annotations).toStrictEqual([
|
||||||
|
{
|
||||||
|
path: 'pro/taskana/common/api/ListUtilTest(H2)',
|
||||||
|
start_line: 22,
|
||||||
|
end_line: 22,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'ListUtilTest.should_SplitListIntoChunks_When_CallingPartitionBasedOnSize',
|
||||||
|
message: 'java.lang.AssertionError:',
|
||||||
|
raw_details:
|
||||||
|
'java.lang.AssertionError: \n' +
|
||||||
|
'\n' +
|
||||||
|
'Expected size:<11> but was:<10> in:\n' +
|
||||||
|
'<[[1,\n' +
|
||||||
|
' 2,\n' +
|
||||||
|
' 3,\n' +
|
||||||
|
' 4,\n' +
|
||||||
|
' 5,\n' +
|
||||||
|
' 6,\n' +
|
||||||
|
' 7,\n' +
|
||||||
|
' 96,\n' +
|
||||||
|
' 97,\n' +
|
||||||
|
' 98,\n' +
|
||||||
|
' 99,\n' +
|
||||||
|
' 100],\n' +
|
||||||
|
' [101,\n' +
|
||||||
|
' 102,\n' +
|
||||||
|
' 103,\n' +
|
||||||
|
' 104,\n' +
|
||||||
|
' 194,\n' +
|
||||||
|
' 195,\n' +
|
||||||
|
' 196,\n' +
|
||||||
|
' 197,\n' +
|
||||||
|
' 198,\n' +
|
||||||
|
' 199,\n' +
|
||||||
|
' 200],\n' +
|
||||||
|
' [201,\n' +
|
||||||
|
' 202,\n' +
|
||||||
|
' 997,\n' +
|
||||||
|
' 998,\n' +
|
||||||
|
' 999,\n' +
|
||||||
|
' 1000]]>\n' +
|
||||||
|
'\tat pro.taskana.common.api.ListUtilTest.should_SplitListIntoChunks_When_CallingPartitionBasedOnSize(ListUtilTest.java:22)'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse custom report with flaky failures', async () => {
|
||||||
|
const { count, skipped, annotations } = await parseFile(
|
||||||
|
'integration-tests/custom_reports/TEST-test.MyIntegrationTestSuite.xml'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(count).toBe(5);
|
||||||
|
expect(skipped).toBe(0);
|
||||||
|
expect(annotations).toStrictEqual([
|
||||||
|
{
|
||||||
|
path: 'test/MyIntegrationTest',
|
||||||
|
start_line: 1,
|
||||||
|
end_line: 1,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'MyIntegrationTest.testGetMails',
|
||||||
|
message:
|
||||||
|
'JSON path "$.mails[0].subject"\n' +
|
||||||
|
'Expected: "MySubject"\n' +
|
||||||
|
' but: was "YourSubject"',
|
||||||
|
raw_details: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'test/DocumentUploadIntegrationTest',
|
||||||
|
start_line: 33,
|
||||||
|
end_line: 33,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title:
|
||||||
|
'DocumentUploadIntegrationTest.shouldReturnBadRequestIfDocumentTypeIsInvalid',
|
||||||
|
message: 'Status expected:<400> but was:<403>',
|
||||||
|
raw_details:
|
||||||
|
'java.lang.AssertionError: Status expected:<400> but was:<403>\n' +
|
||||||
|
'\tat test.DocumentUploadIntegrationTest.shouldReturnBadRequestIfDocumentTypeIsInvalid(DocumentUploadIntegrationTest.java:33)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'test/DocumentUploadIntegrationTest',
|
||||||
|
start_line: 1,
|
||||||
|
end_line: 1,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'DocumentUploadIntegrationTest.shouldReturnSuccessResponse',
|
||||||
|
message: 'Status expected:<200> but was:<403>',
|
||||||
|
raw_details: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'test/DocumentUploadIntegrationTest',
|
||||||
|
start_line: 47,
|
||||||
|
end_line: 47,
|
||||||
|
start_column: 0,
|
||||||
|
end_column: 0,
|
||||||
|
annotation_level: 'failure',
|
||||||
|
title: 'DocumentUploadIntegrationTest.shouldReturnBadRequestIfDocumentSizeIsZero',
|
||||||
|
message: 'Status expected:<400> but was:<403>',
|
||||||
|
raw_details:
|
||||||
|
'java.lang.AssertionError: Status expected:<400> but was:<403>\n' +
|
||||||
|
'\tat test.DocumentUploadIntegrationTest.shouldReturnBadRequestIfDocumentSizeIsZero(DocumentUploadIntegrationTest.java:47)'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue