Skip to content

Commit d128d84

Browse files
Add scripts for checking JaCoCo coverage thresholds and configure GitHub Actions for unit testing with coverage checks
1 parent c816697 commit d128d84

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed

.github/scripts/check-coverage.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/bin/bash
2+
3+
# Script to check JaCoCo coverage against thresholds
4+
# Usage: ./check-coverage.sh
5+
6+
set -e
7+
8+
# Colors for output
9+
RED='\033[0;31m'
10+
GREEN='\033[0;32m'
11+
YELLOW='\033[1;33m'
12+
NC='\033[0m' # No Color
13+
14+
# Coverage thresholds
15+
INSTRUCTION_THRESHOLD=90
16+
BRANCH_THRESHOLD=80
17+
18+
echo "🔍 Checking JaCoCo coverage thresholds..."
19+
echo ""
20+
21+
# Check if JaCoCo XML report exists
22+
JACOCO_XML="target/site/jacoco/jacoco.xml"
23+
if [ ! -f "$JACOCO_XML" ]; then
24+
echo -e "${RED}❌ JaCoCo report not found at $JACOCO_XML${NC}"
25+
echo "Please run: mvn clean test -Dtest='!*IT' jacoco:report -Dgpg.skip=true"
26+
exit 1
27+
fi
28+
29+
# Extract coverage metrics from JaCoCo XML
30+
# Using sed for cross-platform compatibility (macOS doesn't support grep -P)
31+
INSTRUCTION_COVERED=$(sed -n 's/.*type="INSTRUCTION".*covered="\([0-9]*\)".*/\1/p' "$JACOCO_XML" | head -1)
32+
INSTRUCTION_MISSED=$(sed -n 's/.*type="INSTRUCTION".*missed="\([0-9]*\)".*/\1/p' "$JACOCO_XML" | head -1)
33+
BRANCH_COVERED=$(sed -n 's/.*type="BRANCH".*covered="\([0-9]*\)".*/\1/p' "$JACOCO_XML" | head -1)
34+
BRANCH_MISSED=$(sed -n 's/.*type="BRANCH".*missed="\([0-9]*\)".*/\1/p' "$JACOCO_XML" | head -1)
35+
36+
# Calculate totals
37+
INSTRUCTION_TOTAL=$((INSTRUCTION_COVERED + INSTRUCTION_MISSED))
38+
BRANCH_TOTAL=$((BRANCH_COVERED + BRANCH_MISSED))
39+
40+
# Calculate percentages
41+
if [ $INSTRUCTION_TOTAL -gt 0 ]; then
42+
INSTRUCTION_PCT=$((INSTRUCTION_COVERED * 100 / INSTRUCTION_TOTAL))
43+
else
44+
INSTRUCTION_PCT=0
45+
fi
46+
47+
if [ $BRANCH_TOTAL -gt 0 ]; then
48+
BRANCH_PCT=$((BRANCH_COVERED * 100 / BRANCH_TOTAL))
49+
else
50+
BRANCH_PCT=0
51+
fi
52+
53+
# Display coverage summary
54+
echo "📊 Coverage Summary:"
55+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
56+
echo " Instruction Coverage: $INSTRUCTION_PCT% ($INSTRUCTION_COVERED/$INSTRUCTION_TOTAL)"
57+
echo " Branch Coverage: $BRANCH_PCT% ($BRANCH_COVERED/$BRANCH_TOTAL)"
58+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
59+
echo ""
60+
61+
# Check thresholds
62+
THRESHOLD_MET=true
63+
64+
# Check instruction coverage
65+
if [ $INSTRUCTION_PCT -ge $INSTRUCTION_THRESHOLD ]; then
66+
echo -e "${GREEN}✅ Instruction coverage ($INSTRUCTION_PCT%) meets threshold ($INSTRUCTION_THRESHOLD%)${NC}"
67+
else
68+
echo -e "${RED}❌ Instruction coverage ($INSTRUCTION_PCT%) below threshold ($INSTRUCTION_THRESHOLD%)${NC}"
69+
THRESHOLD_MET=false
70+
fi
71+
72+
# Check branch coverage
73+
if [ $BRANCH_PCT -ge $BRANCH_THRESHOLD ]; then
74+
echo -e "${GREEN}✅ Branch coverage ($BRANCH_PCT%) meets threshold ($BRANCH_THRESHOLD%)${NC}"
75+
else
76+
echo -e "${RED}❌ Branch coverage ($BRANCH_PCT%) below threshold ($BRANCH_THRESHOLD%)${NC}"
77+
THRESHOLD_MET=false
78+
fi
79+
80+
echo ""
81+
82+
# Final result
83+
if [ "$THRESHOLD_MET" = true ]; then
84+
echo -e "${GREEN}🎉 All coverage thresholds met!${NC}"
85+
echo ""
86+
echo "HTML report available at: target/site/jacoco/index.html"
87+
exit 0
88+
else
89+
echo -e "${RED}💔 Coverage thresholds not met${NC}"
90+
echo ""
91+
echo "To improve coverage:"
92+
echo " 1. Review the HTML report: target/site/jacoco/index.html"
93+
echo " 2. Identify uncovered lines and branches"
94+
echo " 3. Add unit tests to cover the missing paths"
95+
echo ""
96+
exit 1
97+
fi
98+

.github/workflows/unit-testing.yml

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: 'Java SDK - Unit Testing'
2+
3+
# This workflow runs ONLY unit tests (excludes integration tests ending with IT.java)
4+
# Integration tests require network access and valid .env credentials
5+
6+
on:
7+
pull_request:
8+
branches:
9+
- development
10+
- staging
11+
- main
12+
13+
jobs:
14+
coverage:
15+
name: Unit Test Coverage Check
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
pull-requests: write
20+
checks: write
21+
22+
steps:
23+
- name: Checkout code
24+
uses: actions/checkout@v4
25+
26+
- name: Set up JDK 8
27+
uses: actions/setup-java@v4
28+
with:
29+
java-version: '8'
30+
distribution: 'temurin'
31+
cache: 'maven'
32+
33+
- name: Run unit tests with coverage (excluding integration tests)
34+
run: |
35+
echo "Running unit tests only (excluding *IT.java files)..."
36+
mvn clean test -Dtest='!*IT' jacoco:report -Dgpg.skip=true
37+
echo "Unit tests completed"
38+
continue-on-error: true
39+
40+
- name: Generate JaCoCo Badge
41+
id: jacoco
42+
uses: cicirello/jacoco-badge-generator@v2
43+
with:
44+
badges-directory: .github/badges
45+
generate-branches-badge: true
46+
generate-summary: true
47+
48+
- name: Check coverage thresholds
49+
id: coverage-check
50+
run: |
51+
echo "Checking coverage thresholds (unit tests only)..."
52+
# Extract coverage percentages from JaCoCo XML report (using sed for cross-platform compatibility)
53+
INSTRUCTION_COVERAGE=$(sed -n 's/.*type="INSTRUCTION".*covered="\([0-9]*\)".*/\1/p' target/site/jacoco/jacoco.xml | tail -1)
54+
INSTRUCTION_MISSED=$(sed -n 's/.*type="INSTRUCTION".*missed="\([0-9]*\)".*/\1/p' target/site/jacoco/jacoco.xml | tail -1)
55+
BRANCH_COVERAGE=$(sed -n 's/.*type="BRANCH".*covered="\([0-9]*\)".*/\1/p' target/site/jacoco/jacoco.xml | tail -1)
56+
BRANCH_MISSED=$(sed -n 's/.*type="BRANCH".*missed="\([0-9]*\)".*/\1/p' target/site/jacoco/jacoco.xml | tail -1)
57+
58+
# Calculate percentages
59+
INSTRUCTION_TOTAL=$((INSTRUCTION_COVERAGE + INSTRUCTION_MISSED))
60+
BRANCH_TOTAL=$((BRANCH_COVERAGE + BRANCH_MISSED))
61+
62+
if [ $INSTRUCTION_TOTAL -gt 0 ]; then
63+
INSTRUCTION_PCT=$((INSTRUCTION_COVERAGE * 100 / INSTRUCTION_TOTAL))
64+
else
65+
INSTRUCTION_PCT=0
66+
fi
67+
68+
if [ $BRANCH_TOTAL -gt 0 ]; then
69+
BRANCH_PCT=$((BRANCH_COVERAGE * 100 / BRANCH_TOTAL))
70+
else
71+
BRANCH_PCT=0
72+
fi
73+
74+
echo "instruction_pct=$INSTRUCTION_PCT" >> $GITHUB_OUTPUT
75+
echo "branch_pct=$BRANCH_PCT" >> $GITHUB_OUTPUT
76+
77+
# Check thresholds
78+
THRESHOLD_MET=true
79+
MESSAGES=""
80+
81+
if [ $INSTRUCTION_PCT -lt 90 ]; then
82+
THRESHOLD_MET=false
83+
MESSAGES="${MESSAGES}❌ Overall instruction coverage is ${INSTRUCTION_PCT}% (threshold: 90%)\n"
84+
else
85+
MESSAGES="${MESSAGES}✅ Overall instruction coverage is ${INSTRUCTION_PCT}% (threshold: 90%)\n"
86+
fi
87+
88+
if [ $BRANCH_PCT -lt 80 ]; then
89+
THRESHOLD_MET=false
90+
MESSAGES="${MESSAGES}❌ Branch coverage is ${BRANCH_PCT}% (threshold: 80%)\n"
91+
else
92+
MESSAGES="${MESSAGES}✅ Branch coverage is ${BRANCH_PCT}% (threshold: 80%)\n"
93+
fi
94+
95+
echo "threshold_met=$THRESHOLD_MET" >> $GITHUB_OUTPUT
96+
echo -e "$MESSAGES"
97+
echo "messages<<EOF" >> $GITHUB_OUTPUT
98+
echo -e "$MESSAGES" >> $GITHUB_OUTPUT
99+
echo "EOF" >> $GITHUB_OUTPUT
100+
101+
if [ "$THRESHOLD_MET" = "false" ]; then
102+
exit 1
103+
fi
104+
105+
- name: Add coverage comment to PR
106+
uses: madrapps/jacoco-report@v1.6.1
107+
if: always()
108+
with:
109+
paths: |
110+
${{ github.workspace }}/target/site/jacoco/jacoco.xml
111+
token: ${{ secrets.GITHUB_TOKEN }}
112+
min-coverage-overall: 90
113+
min-coverage-changed-files: 80
114+
title: '📊 Unit Test Coverage Report'
115+
update-comment: true
116+
117+
- name: Upload JaCoCo coverage report
118+
uses: actions/upload-artifact@v4
119+
if: always()
120+
with:
121+
name: jacoco-report
122+
path: target/site/jacoco/
123+
124+
- name: Fail if coverage thresholds not met
125+
if: steps.coverage-check.outputs.threshold_met == 'false'
126+
run: |
127+
echo "Coverage thresholds not met:"
128+
echo "${{ steps.coverage-check.outputs.messages }}"
129+
exit 1
130+

0 commit comments

Comments
 (0)