add percentage analysis for total of invariants #51
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Java CI | |
on: | |
pull_request: | |
branches: | |
- master | |
- dev | |
push: | |
workflow_dispatch: | |
jobs: | |
format: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set up JDK 21 | |
uses: actions/setup-java@v3 | |
with: | |
java-version: '21' | |
distribution: 'temurin' | |
- name: Check Java Format | |
uses: axel-op/googlejavaformat-action@v3 | |
with: | |
args: "--replace" | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
skip-commit: false | |
test: | |
needs: format | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
checks: write | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set up JDK 21 | |
uses: actions/setup-java@v3 | |
with: | |
java-version: '21' | |
distribution: 'temurin' | |
- name: Setup Gradle Cache | |
uses: actions/cache@v3 | |
with: | |
path: | | |
~/.gradle/caches | |
~/.gradle/wrapper | |
.gradle | |
build | |
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle-wrapper.properties') }} | |
restore-keys: | | |
gradle-${{ runner.os }}- | |
- name: Setup Node Cache | |
uses: actions/cache@v3 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') || hashFiles('package.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
- name: Build with Gradle | |
run: ./gradlew build | |
continue-on-error: true | |
- name: Run tests with Gradle | |
run: ./gradlew test | |
continue-on-error: true | |
- name: Generate JaCoCo coverage report | |
run: ./gradlew jacocoTestReport | |
- name: Set up Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: '18' | |
- name: Install Dependencies | |
run: npm install xml2js glob | |
- name: Publish JUnit test results | |
uses: dorny/test-reporter@v1 | |
with: | |
name: JUnit Tests | |
path: build/test-results/**/*.xml | |
reporter: java-junit | |
- name: Generate Combined Test and Coverage Summary | |
uses: actions/github-script@v6 | |
env: | |
MINIMUM_COVERAGE: "20" | |
with: | |
script: | | |
const fs = require('fs'); | |
const path = require('path'); | |
const xml2js = require('xml2js'); | |
// Variables to store test results | |
let totalTests = 0, failures = 0, errors = 0, skipped = 0, successful = 0; | |
let totalLines = 0, coveredLines = 0, missedLines = 0; | |
let lineCoveragePercentage = "N/A"; | |
// Function to process test files | |
async function processTestFiles() { | |
const testDir = path.join('build', 'test-results', 'test'); | |
const files = fs.readdirSync(testDir) | |
.filter(file => file.endsWith('.xml')) | |
.map(file => path.join(testDir, file)); | |
const parser = new xml2js.Parser(); | |
for (const file of files) { | |
const xmlContent = fs.readFileSync(file, 'utf-8'); | |
try { | |
const result = await parser.parseStringPromise(xmlContent); | |
const testsuite = result.testsuite.$; | |
totalTests += parseInt(testsuite.tests || 0); | |
failures += parseInt(testsuite.failures || 0); | |
errors += parseInt(testsuite.errors || 0); | |
skipped += parseInt(testsuite.skipped || 0); | |
console.log(`Processed ${file}: ${testsuite.tests} tests`); | |
} catch (err) { | |
console.error(`Error processing ${file}: ${err.message}`); | |
} | |
} | |
successful = totalTests - failures - errors - skipped; | |
} | |
// Function for JaCoCo coverage report processing | |
async function processJacocoCoverage() { | |
const jacocoPath = path.join('build', 'reports', 'jacoco', 'test', 'jacocoTestReport.xml'); | |
if (fs.existsSync(jacocoPath)) { | |
const jacocoXml = fs.readFileSync(jacocoPath, 'utf-8'); | |
const parser = new xml2js.Parser(); | |
try { | |
const result = await parser.parseStringPromise(jacocoXml); | |
const counters = result.report.counter.filter(c => c.$.type === 'LINE'); | |
counters.forEach(counter => { | |
missedLines += parseInt(counter.$.missed); | |
coveredLines += parseInt(counter.$.covered); | |
}); | |
totalLines = missedLines + coveredLines; | |
lineCoveragePercentage = totalLines > 0 | |
? ((coveredLines / totalLines) * 100).toFixed(2) + '%' | |
: '0.00%'; | |
console.log(`Processed JaCoCo report: ${lineCoveragePercentage} coverage`); | |
} catch (err) { | |
console.error(`Error processing JaCoCo report: ${err.message}`); | |
} | |
} | |
} | |
// Process test files and JaCoCo coverage | |
await processTestFiles(); | |
await processJacocoCoverage(); | |
// Check if line coverage is within the expected range | |
let auxLineCoveragePercentage = parseFloat(lineCoveragePercentage.replace('%', '')); | |
if (auxLineCoveragePercentage < 0 || auxLineCoveragePercentage > 100) { | |
core.setFailed(`Invalid line coverage percentage: ${lineCoveragePercentage}`); | |
} | |
if (auxLineCoveragePercentage < parseFloat(process.env.MINIMUM_COVERAGE)) { | |
core.setFailed(`Line coverage is below the minimum threshold of ${process.env.MINIMUM_COVERAGE}%: ${lineCoveragePercentage}`); | |
} | |
const summary = ` | |
# Test and Coverage Summary | |
## Test Results | |
- **Total Tests:** ${totalTests} | |
- **Successful:** ${successful} | |
- **Failures:** ${failures} | |
- **Errors:** ${errors} | |
- **Skipped:** ${skipped} | |
## Code Coverage | |
- **Line Coverage:** ${lineCoveragePercentage} | |
- **Total Lines:** ${totalLines} | |
- **Covered Lines:** ${coveredLines} | |
- **Missed Lines:** ${missedLines} | |
`; | |
console.log(summary); | |
await core.summary.addRaw(summary).write(); | |
- name: Upload Artifacts On Failure | |
if: failure() | |
uses: actions/upload-artifact@v3 | |
with: | |
name: test-results | |
path: build/reports/tests |