setup coverate report generation

This commit is contained in:
2025-12-05 18:20:51 +01:00
parent c5c602d599
commit f9cbb1b596
12 changed files with 1142 additions and 387 deletions

View File

@ -20,7 +20,8 @@
"Bash(docker-compose ps:*)", "Bash(docker-compose ps:*)",
"Bash(tree:*)", "Bash(tree:*)",
"Bash(docker-compose:*)", "Bash(docker-compose:*)",
"Bash(chmod:*)" "Bash(chmod:*)",
"Bash(ls:*)"
], ],
"deny": [], "deny": [],
"ask": [] "ask": []

400
DOCKER_COMPOSE_GUIDE.md Normal file
View File

@ -0,0 +1,400 @@
# Docker Compose Patterns - Quick Guide
This guide provides a focused reference for all Docker Compose patterns used in this project.
## Overview
This project uses **three Docker Compose files** for different purposes:
```
docker-compose.yml ← Start application server
docker-compose.test.yml ← Run unit tests
docker-compose.coverage.yml ← Generate coverage reports
```
---
## Pattern 1: Application Server
**File**: `docker-compose.yml`
**Purpose**: Deploy JAX-WS application to Tomcat
### Commands
```bash
# Start server
docker-compose up -d
# Start with build
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop server
docker-compose down
# Restart
docker-compose restart
```
### What Happens
1. Builds Docker image (3 stages):
- Stage 1: Run unit tests
- Stage 2: Build WAR file
- Stage 3: Deploy to Tomcat
2. Starts Tomcat on port 8080
3. Creates/persists SQLite database
### Access
- Hello World: http://localhost:8080/jaxws-hello-world/hello?wsdl
- Loan Service: http://localhost:8080/jaxws-hello-world/loan?wsdl
- Tomcat Manager: http://localhost:8080/manager (admin/admin123)
---
## Pattern 2: Run Unit Tests
**File**: `docker-compose.test.yml`
**Purpose**: Execute JUnit tests
### Commands
```bash
# Run tests
docker-compose -f docker-compose.test.yml up --build
# View test output
docker-compose -f docker-compose.test.yml logs
# Clean up
docker-compose -f docker-compose.test.yml down
# One-liner (run and clean)
docker-compose -f docker-compose.test.yml up --build && docker-compose -f docker-compose.test.yml down
```
### Convenience Scripts
**Windows:**
```cmd
run-tests.bat
```
**Linux/Mac:**
```bash
./run-tests.sh
```
### What Happens
1. Builds test environment
2. Runs `mvn test`
3. Executes all *Test.java files
4. Exports results to `./target/surefire-reports/`
5. Generates JaCoCo coverage data
### Output
**Console:**
```
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
```
**Files:**
- `./target/surefire-reports/` - Test reports (text & XML)
- `./target/jacoco.exec` - Coverage data
---
## Pattern 3: Generate Code Coverage
**File**: `docker-compose.coverage.yml`
**Purpose**: Generate JaCoCo coverage reports
### Commands
```bash
# Generate coverage
docker-compose -f docker-compose.coverage.yml up --build
# View logs
docker-compose -f docker-compose.coverage.yml logs
# Clean up
docker-compose -f docker-compose.coverage.yml down
# One-liner (generate and clean)
docker-compose -f docker-compose.coverage.yml up --build && docker-compose -f docker-compose.coverage.yml down
```
### Convenience Scripts
**Windows:**
```cmd
run-coverage.bat
```
**Linux/Mac:**
```bash
./run-coverage.sh
```
### What Happens
1. Builds test environment
2. Runs `mvn test` with JaCoCo agent
3. Generates coverage reports (HTML, XML, CSV)
4. Exports to `./target/site/jacoco/`
### Output
**Console:**
```
=================================================================================
Coverage report generated successfully!
=================================================================================
HTML Report: ./target/site/jacoco/index.html
XML Report: ./target/site/jacoco/jacoco.xml
CSV Report: ./target/site/jacoco/jacoco.csv
=================================================================================
```
**Files:**
- `./target/site/jacoco/index.html`**Open this in browser**
- `./target/site/jacoco/jacoco.xml` (for CI/CD)
- `./target/site/jacoco/jacoco.csv` (for spreadsheets)
---
## Complete Workflow
### Typical Development Cycle
```bash
# 1. Write code
vim src/main/java/com/example/service/MyService.java
# 2. Run tests
docker-compose -f docker-compose.test.yml up --build
docker-compose -f docker-compose.test.yml down
# 3. Check coverage
docker-compose -f docker-compose.coverage.yml up --build
docker-compose -f docker-compose.coverage.yml down
# 4. View coverage report
# Open target/site/jacoco/index.html in browser
# 5. Deploy if tests pass
docker-compose up -d --build
# 6. Verify
curl http://localhost:8080/jaxws-hello-world/hello?wsdl
# 7. View logs
docker-compose logs -f
# 8. Stop when done
docker-compose down
```
### Using Convenience Scripts (Faster)
**Windows:**
```cmd
REM 1. Write code
notepad src\main\java\com\example\service\MyService.java
REM 2. Run tests
run-tests.bat
REM 3. Generate coverage
run-coverage.bat
REM 4. View coverage
start target\site\jacoco\index.html
REM 5. Deploy
docker-compose up -d --build
```
**Linux/Mac:**
```bash
# 1. Write code
vim src/main/java/com/example/service/MyService.java
# 2. Run tests
./run-tests.sh
# 3. Generate coverage
./run-coverage.sh
# 4. View coverage (Linux)
xdg-open target/site/jacoco/index.html
# 5. Deploy
docker-compose up -d --build
```
---
## Quick Reference Table
| Task | Docker Compose Command | Script Alternative |
|------|----------------------|-------------------|
| **Run Tests** | `docker-compose -f docker-compose.test.yml up --build` | `run-tests.bat` / `./run-tests.sh` |
| **Generate Coverage** | `docker-compose -f docker-compose.coverage.yml up --build` | `run-coverage.bat` / `./run-coverage.sh` |
| **Start Server** | `docker-compose up -d` | N/A |
| **Stop Server** | `docker-compose down` | N/A |
| **View Logs** | `docker-compose logs -f` | N/A |
| **Rebuild Server** | `docker-compose up -d --build` | N/A |
---
## Common Patterns
### Pattern: Test-Driven Development (TDD)
```bash
# Watch-test loop (manual)
while true; do
docker-compose -f docker-compose.test.yml up --build
docker-compose -f docker-compose.test.yml down
read -p "Press Enter to run again, Ctrl+C to exit..."
done
```
### Pattern: CI/CD Pipeline
```yaml
# GitHub Actions example
- name: Run Tests
run: docker-compose -f docker-compose.test.yml up --build
- name: Generate Coverage
run: docker-compose -f docker-compose.coverage.yml up --build
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./target/site/jacoco/jacoco.xml
- name: Deploy (if tests pass)
run: docker-compose up -d --build
```
### Pattern: Pre-commit Hook
```bash
#!/bin/bash
# .git/hooks/pre-commit
echo "Running tests before commit..."
docker-compose -f docker-compose.test.yml up --build
if [ $? -ne 0 ]; then
echo "Tests failed! Commit aborted."
docker-compose -f docker-compose.test.yml down
exit 1
fi
docker-compose -f docker-compose.test.yml down
echo "Tests passed! Proceeding with commit."
```
---
## Troubleshooting
### Tests Failing
```bash
# View detailed test output
docker-compose -f docker-compose.test.yml up
# Check test container logs
docker-compose -f docker-compose.test.yml logs
# Access test container
docker-compose -f docker-compose.test.yml run --rm test bash
```
### Coverage Report Empty
```bash
# Ensure tests are running
docker-compose -f docker-compose.test.yml up --build
# Check if target directory is mounted
docker-compose -f docker-compose.coverage.yml config | grep target
# Manually verify mount
ls -la target/site/jacoco/
```
### Server Won't Start
```bash
# Check if port 8080 is in use
netstat -ano | findstr :8080 # Windows
lsof -i :8080 # Linux/Mac
# View server logs
docker-compose logs -f
# Rebuild from scratch
docker-compose down
docker-compose build --no-cache
docker-compose up -d
```
---
## Advanced Usage
### Run Specific Test
```bash
# Override command to run specific test
docker-compose -f docker-compose.test.yml run --rm test \
mvn test -Dtest=HelloWorldServiceImplTest
```
### Custom Memory Settings
```bash
# Override environment variable
docker-compose -f docker-compose.test.yml run --rm \
-e MAVEN_OPTS="-Xmx1024m" test mvn test
```
### Debug Mode
```bash
# Run tests with Maven debug output
docker-compose -f docker-compose.test.yml run --rm test \
mvn test -X
```
---
## Summary
- **3 Docker Compose files** = 3 different purposes
- **Test first** before deploying
- **Check coverage** to ensure quality
- **Use scripts** for convenience
- **All outputs** go to `./target/`
**Quick commands to remember:**
```bash
run-tests.bat # or ./run-tests.sh
run-coverage.bat # or ./run-coverage.sh
docker-compose up -d # start server
```
That's it! You now have everything you need to use Docker Compose patterns in this project.

30
Dockerfile.coverage Normal file
View File

@ -0,0 +1,30 @@
# Multi-stage build for code coverage
FROM maven:3.8.6-openjdk-8 AS builder
# Set working directory
WORKDIR /app
# Copy pom.xml and src
COPY pom.xml .
COPY src ./src
# Build with tests
RUN mvn clean package -DskipTests=false
# Create a separate stage for running tests with coverage
FROM maven:3.8.6-openjdk-8
# Set working directory
WORKDIR /app
# Copy the built project
COPY --from=builder /app/target/*.war /app/app.war
# Install dependencies for coverage reporting
RUN apt-get update && apt-get install -y wget unzip
# Create a script to run tests with coverage
COPY scripts/ .
# Run tests with coverage
CMD ["mvn", "test"]

View File

@ -0,0 +1,16 @@
FROM maven:3.8.6-openjdk-8
WORKDIR /app
# Copy pom.xml and source files
COPY pom.xml .
COPY src ./src
# Run tests with coverage
RUN mvn clean test
# Generate coverage report
RUN mvn jacoco:report
# Show the coverage report location
RUN echo "Coverage report is available in target/site/jacoco/"

581
README.md
View File

@ -2,6 +2,25 @@
A complete JAX-WS SOAP web services application for loan processing, featuring customer registration, credit score evaluation, and loan approval workflows with SQLite database persistence. A complete JAX-WS SOAP web services application for loan processing, featuring customer registration, credit score evaluation, and loan approval workflows with SQLite database persistence.
## Quick Reference Card
### 🚀 Three Ways to Use This Project
| Task | Command | Result |
|------|---------|--------|
| **Run Tests** | `docker-compose -f docker-compose.test.yml up --build` | Tests run, results in `./target/surefire-reports/` |
| **Generate Coverage** | `docker-compose -f docker-compose.coverage.yml up --build` | Coverage report in `./target/site/jacoco/index.html` |
| **Start Server** | `docker-compose up -d` | Server running at http://localhost:8080 |
### 📝 Convenience Scripts
| Platform | Run Tests | Generate Coverage |
|----------|-----------|-------------------|
| **Windows** | `run-tests.bat` | `run-coverage.bat` |
| **Linux/Mac** | `./run-tests.sh` | `./run-coverage.sh` |
---
## Project Details ## Project Details
### Overview ### Overview
@ -23,7 +42,8 @@ This project demonstrates a production-ready JAX-WS web service implementation u
- **Application Server**: Apache Tomcat 9+ - **Application Server**: Apache Tomcat 9+
- **Database**: SQLite 3.43.0 - **Database**: SQLite 3.43.0
- **Containerization**: Docker & Docker Compose - **Containerization**: Docker & Docker Compose
- **Testing**: Python 3 with zeep library - **Unit Testing**: JUnit 5 (Jupiter), Mockito, JaCoCo
- **Integration Testing**: Python 3 with requests library
### Key Features ### Key Features
@ -32,7 +52,8 @@ This project demonstrates a production-ready JAX-WS web service implementation u
- **Credit Risk Assessment**: Tiered approval logic based on credit scores - **Credit Risk Assessment**: Tiered approval logic based on credit scores
- **Blacklist Management**: Customer screening and rejection system - **Blacklist Management**: Customer screening and rejection system
- **Docker Support**: Fully containerized with one-command deployment - **Docker Support**: Fully containerized with one-command deployment
- **Comprehensive Testing**: Python test clients for all services - **Unit Testing**: JUnit 5 tests with JaCoCo code coverage
- **Integration Testing**: Python test clients for all services
- **Production-Ready**: Singleton patterns, prepared statements, error handling - **Production-Ready**: Singleton patterns, prepared statements, error handling
--- ---
@ -46,6 +67,75 @@ This project demonstrates a production-ready JAX-WS web service implementation u
### Quick Start ### Quick Start
#### Three Docker Compose Configurations
This project provides three Docker Compose files for different purposes:
| Purpose | File | Command | Output Location |
|---------|------|---------|----------------|
| **🚀 Start Server** | `docker-compose.yml` | `docker-compose up -d` | http://localhost:8080 |
| **✅ Run Tests** | `docker-compose.test.yml` | `docker-compose -f docker-compose.test.yml up --build` | `./target/surefire-reports/` |
| **📊 Coverage Report** | `docker-compose.coverage.yml` | `docker-compose -f docker-compose.coverage.yml up --build` | `./target/site/jacoco/index.html` |
**Visual Workflow:**
```
┌─────────────────────────────────────────────────────────────────┐
│ Development Workflow │
└─────────────────────────────────────────────────────────────────┘
1. Write Code
┌─────────────────────────┐
│ Run Unit Tests │ ──► docker-compose -f docker-compose.test.yml up --build
│ (docker-compose.test) │
└──────────┬──────────────┘
│ Tests Pass ✓
┌─────────────────────────┐
│ Generate Coverage │ ──► docker-compose -f docker-compose.coverage.yml up --build
│ (docker-compose.coverage│
└──────────┬──────────────┘ Open: ./target/site/jacoco/index.html
│ Coverage OK ✓
┌─────────────────────────┐
│ Deploy Application │ ──► docker-compose up -d
│ (docker-compose.yml) │
└──────────┬──────────────┘ Access: http://localhost:8080
Production Ready!
```
**Quick Commands:**
```bash
# Run all tests
docker-compose -f docker-compose.test.yml up --build && docker-compose -f docker-compose.test.yml down
# Generate coverage report
docker-compose -f docker-compose.coverage.yml up --build && docker-compose -f docker-compose.coverage.yml down
# Start application server
docker-compose up -d
```
**Or use convenience scripts:**
```cmd
REM Windows
run-tests.bat
run-coverage.bat
docker-compose up -d
```
```bash
# Linux/Mac
./run-tests.sh
./run-coverage.sh
docker-compose up -d
```
---
#### 1. Start the Application #### 1. Start the Application
```bash ```bash
@ -88,6 +178,188 @@ docker-compose logs jaxws-service
docker-compose down docker-compose down
``` ```
---
### Docker Compose Patterns
This project includes three Docker Compose configurations for different purposes:
#### Pattern 1: Start Application Server
**File**: `docker-compose.yml`
**Purpose**: Deploy and run the JAX-WS application on Tomcat
```bash
# Start the server in detached mode
docker-compose up -d
# Start with build (after code changes)
docker-compose up -d --build
# View logs in real-time
docker-compose logs -f
# Stop the server
docker-compose down
```
**What happens:**
1. Runs unit tests (Stage 1: tester)
2. Builds WAR file (Stage 2: builder)
3. Deploys to Tomcat (Stage 3)
4. Exposes port 8080
5. Creates/persists SQLite database
**Access points:**
- Hello World Service: http://localhost:8080/jaxws-hello-world/hello?wsdl
- Loan Service: http://localhost:8080/jaxws-hello-world/loan?wsdl
- Tomcat Manager: http://localhost:8080/manager (admin/admin123)
---
#### Pattern 2: Run Unit Tests
**File**: `docker-compose.test.yml`
**Purpose**: Execute JUnit tests and export results to `./target`
```bash
# Run tests
docker-compose -f docker-compose.test.yml up --build
# Run tests in background
docker-compose -f docker-compose.test.yml up -d
# View test output
docker-compose -f docker-compose.test.yml logs
# Clean up
docker-compose -f docker-compose.test.yml down
```
**What happens:**
1. Builds test environment (tester stage)
2. Runs `mvn test`
3. Executes all *Test.java files
4. Exports test reports to `./target/surefire-reports/`
5. Exports coverage data to `./target/jacoco.exec`
**Test results location:**
- Console output: Test summary with pass/fail counts
- Reports: `./target/surefire-reports/` (text and XML)
**Example output:**
```
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
```
---
#### Pattern 3: Generate Code Coverage Report
**File**: `docker-compose.coverage.yml`
**Purpose**: Run tests and generate JaCoCo coverage reports in `./target/site/jacoco/`
```bash
# Generate coverage reports
docker-compose -f docker-compose.coverage.yml up --build
# Generate coverage in background
docker-compose -f docker-compose.coverage.yml up -d
# View coverage generation logs
docker-compose -f docker-compose.coverage.yml logs
# Clean up
docker-compose -f docker-compose.coverage.yml down
```
**What happens:**
1. Builds test environment
2. Runs `mvn test` with JaCoCo agent
3. Generates coverage reports in multiple formats
4. Exports to `./target/site/jacoco/`
**Coverage reports location:**
- **HTML Report**: `./target/site/jacoco/index.html`**Open this in browser**
- **XML Report**: `./target/site/jacoco/jacoco.xml` (for CI/CD)
- **CSV Report**: `./target/site/jacoco/jacoco.csv` (for spreadsheets)
**Example output:**
```
=================================================================================
Coverage report generated successfully!
=================================================================================
HTML Report: ./target/site/jacoco/index.html
XML Report: ./target/site/jacoco/jacoco.xml
CSV Report: ./target/site/jacoco/jacoco.csv
=================================================================================
```
---
### Complete Workflow Example
Here's a typical development workflow using all three patterns:
```bash
# 1. Run tests to ensure code works
docker-compose -f docker-compose.test.yml up --build
docker-compose -f docker-compose.test.yml down
# 2. Generate coverage report to check test quality
docker-compose -f docker-compose.coverage.yml up --build
docker-compose -f docker-compose.coverage.yml down
# 3. View coverage report
# Open target/site/jacoco/index.html in browser
# 4. Deploy application if tests pass
docker-compose up -d --build
# 5. Verify deployment
curl http://localhost:8080/jaxws-hello-world/hello?wsdl
# 6. View application logs
docker-compose logs -f
# 7. Stop when done
docker-compose down
```
---
### Quick Reference Scripts
For convenience, use the provided scripts instead of typing full commands:
| Task | Windows | Linux/Mac | Docker Compose Equivalent |
|------|---------|-----------|--------------------------|
| Run Tests | `run-tests.bat` | `./run-tests.sh` | `docker-compose -f docker-compose.test.yml up --build` |
| Generate Coverage | `run-coverage.bat` | `./run-coverage.sh` | `docker-compose -f docker-compose.coverage.yml up --build` |
| Start Server | N/A | N/A | `docker-compose up -d` |
**Example:**
```cmd
REM Windows
run-tests.bat
run-coverage.bat
REM Then start server
docker-compose up -d
```
```bash
# Linux/Mac
./run-tests.sh
./run-coverage.sh
# Then start server
docker-compose up -d
```
---
### Rebuild After Code Changes ### Rebuild After Code Changes
When you modify the source code, rebuild and restart: When you modify the source code, rebuild and restart:
@ -103,15 +375,33 @@ docker-compose up -d
### Docker Commands Reference ### Docker Commands Reference
#### Application Server Commands
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `docker-compose up -d` | Start services in detached mode | | `docker-compose up -d` | Start application server in detached mode |
| `docker-compose up -d --build` | Rebuild and start services | | `docker-compose up -d --build` | Rebuild and start application server |
| `docker-compose down` | Stop and remove containers | | `docker-compose down` | Stop and remove application containers |
| `docker-compose logs -f` | Follow logs output | | `docker-compose logs -f` | Follow application logs in real-time |
| `docker-compose ps` | List running containers | | `docker-compose ps` | List running containers |
| `docker-compose restart` | Restart services | | `docker-compose restart` | Restart application services |
| `docker-compose exec jaxws-service bash` | Access container shell | | `docker-compose exec jaxws-service bash` | Access application container shell |
#### Test Commands
| Command | Description |
|---------|-------------|
| `docker-compose -f docker-compose.test.yml up --build` | Run unit tests |
| `docker-compose -f docker-compose.test.yml logs` | View test output |
| `docker-compose -f docker-compose.test.yml down` | Clean up test containers |
#### Coverage Commands
| Command | Description |
|---------|-------------|
| `docker-compose -f docker-compose.coverage.yml up --build` | Generate coverage reports |
| `docker-compose -f docker-compose.coverage.yml logs` | View coverage generation logs |
| `docker-compose -f docker-compose.coverage.yml down` | Clean up coverage containers |
### Accessing the Database ### Accessing the Database
@ -145,38 +435,45 @@ The `docker-compose.yml` includes these configurations:
jaxws-hello-world/ jaxws-hello-world/
├── src/ ├── src/
── main/ ── main/
├── java/ ├── java/
│ └── com/ │ └── com/
│ └── example/ │ └── example/
│ ├── listener/ │ ├── listener/
│ │ └── DatabaseInitializationListener.java # Application startup initialization │ │ └── DatabaseInitializationListener.java # Application startup initialization
│ │ │ │
│ ├── model/ # Data models (POJOs) │ ├── model/ # Data models (POJOs)
│ │ ├── CustomerRegistrationRequest.java # Customer registration request │ │ ├── CustomerRegistrationRequest.java # Customer registration request
│ │ ├── LoanRequest.java # Loan application request │ │ ├── LoanRequest.java # Loan application request
│ │ └── LoanResponse.java # Loan application response │ │ └── LoanResponse.java # Loan application response
│ │ │ │
│ ├── repository/ # Data access layer │ ├── repository/ # Data access layer
│ │ ├── CustomerRepository.java # Customer DAO interface │ │ ├── CustomerRepository.java # Customer DAO interface
│ │ ├── LoanHistoryRepository.java # Loan history DAO interface │ │ ├── LoanHistoryRepository.java # Loan history DAO interface
│ │ └── impl/ │ │ └── impl/
│ │ ├── CustomerRepositoryImpl.java # Customer DAO implementation │ │ ├── CustomerRepositoryImpl.java # Customer DAO implementation
│ │ └── LoanHistoryRepositoryImpl.java # Loan history DAO implementation │ │ └── LoanHistoryRepositoryImpl.java # Loan history DAO implementation
│ │ │ │
│ ├── service/ # Web service layer │ ├── service/ # Web service layer
│ │ ├── HelloWorldService.java # Hello World interface │ │ ├── HelloWorldService.java # Hello World interface
│ │ ├── HelloWorldServiceImpl.java # Hello World implementation │ │ ├── HelloWorldServiceImpl.java # Hello World implementation
│ │ ├── LoanApprovalService.java # Loan service (interface + impl) │ │ ├── LoanApprovalService.java # Loan service (interface + impl)
│ │ └── CreditScoreService.java # Credit score evaluation │ │ └── CreditScoreService.java # Credit score evaluation
│ │ │ │
│ └── util/ │ └── util/
│ └── DatabaseManager.java # Singleton DB connection manager │ └── DatabaseManager.java # Singleton DB connection manager
└── webapp/ └── webapp/
└── WEB-INF/ └── WEB-INF/
├── web.xml # Web application descriptor ├── web.xml # Web application descriptor
└── sun-jaxws.xml # JAX-WS endpoint configuration └── sun-jaxws.xml # JAX-WS endpoint configuration
│ │
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── service/
│ └── HelloWorldServiceImplTest.java # Unit tests for Hello World service
├── scripts/ # Python test clients ├── scripts/ # Python test clients
│ ├── test_all_services.py # Comprehensive test suite │ ├── test_all_services.py # Comprehensive test suite
@ -186,12 +483,25 @@ jaxws-hello-world/
│ └── README.md # Test scripts documentation │ └── README.md # Test scripts documentation
├── logs/ # Tomcat logs (Docker volume) ├── logs/ # Tomcat logs (Docker volume)
├── target/ # Build output (generated)
│ ├── site/jacoco/ # Code coverage reports
│ │ ├── index.html # HTML coverage report
│ │ ├── jacoco.xml # XML coverage report
│ │ └── jacoco.csv # CSV coverage report
│ └── surefire-reports/ # Test execution reports
├── pom.xml # Maven project configuration ├── pom.xml # Maven project configuration
├── docker-compose.yml # Docker Compose orchestration ├── docker-compose.yml # Docker Compose orchestration
├── docker-compose.test.yml # Docker Compose for unit tests
├── docker-compose.coverage.yml # Docker Compose for coverage
├── Dockerfile # Multi-stage Docker build ├── Dockerfile # Multi-stage Docker build
├── Dockerfile.coverage.simple # Dockerfile for coverage
├── tomcat-users.xml # Tomcat manager users ├── tomcat-users.xml # Tomcat manager users
├── loan_app.db # SQLite database (created on first run) ├── loan_app.db # SQLite database (created on first run)
├── run-tests.bat # Windows test runner script
├── run-tests.sh # Linux/Mac test runner script
├── run-coverage.bat # Windows coverage script
├── run-coverage.sh # Linux/Mac coverage script
├── README.md # This file ├── README.md # This file
├── apidoc.md # Complete API documentation ├── apidoc.md # Complete API documentation
├── requirements.md # Project requirements specification ├── requirements.md # Project requirements specification
@ -777,6 +1087,197 @@ See [scripts/README.md](scripts/README.md)
--- ---
## Unit Tests and Code Coverage
### Overview
This project includes comprehensive unit testing with JUnit 5 and code coverage analysis with JaCoCo. All test results and coverage reports are automatically exported to the `./target` directory for easy access.
### Quick Start
#### Run Unit Tests
**Windows:**
```cmd
run-tests.bat
```
**Linux/Mac:**
```bash
./run-tests.sh
```
**Docker Compose:**
```bash
docker-compose -f docker-compose.test.yml up --build
docker-compose -f docker-compose.test.yml down
```
#### Generate Code Coverage Reports
**Windows:**
```cmd
run-coverage.bat
```
**Linux/Mac:**
```bash
./run-coverage.sh
```
**Docker Compose:**
```bash
docker-compose -f docker-compose.coverage.yml up --build
docker-compose -f docker-compose.coverage.yml down
```
### Coverage Reports
All coverage reports are generated in `./target/site/jacoco/`:
- **HTML Report**: `target/site/jacoco/index.html` (open in browser)
- **XML Report**: `target/site/jacoco/jacoco.xml` (for CI/CD tools)
- **CSV Report**: `target/site/jacoco/jacoco.csv` (for spreadsheets)
### Test Framework
The project uses:
- **JUnit 5 (Jupiter)** - Modern testing framework with annotations
- **Mockito** - Mocking framework for complex test scenarios
- **JaCoCo** - Code coverage analysis and reporting
- **Maven Surefire** - Test execution plugin
### Current Test Coverage
| Service | Test Class | Test Cases | Status |
|---------|-----------|------------|--------|
| Hello World Service | HelloWorldServiceImplTest | 10 | ✅ Passing |
### Understanding Coverage Reports
**Coverage Metrics:**
- **Line Coverage**: Percentage of executable lines tested
- **Branch Coverage**: Percentage of decision points (if/else) tested
- **Method Coverage**: Percentage of methods invoked during tests
- **Class Coverage**: Percentage of classes with at least one test
**Coverage Goals:**
- Line Coverage: > 80%
- Branch Coverage: > 70%
- Method Coverage: > 85%
### Running Tests with Maven (Local)
If you have Maven installed locally:
```bash
# Run tests only
mvn test
# Run tests with coverage
mvn clean test
# View coverage report
# Open target/site/jacoco/index.html in your browser
```
### CI/CD Integration
#### GitHub Actions Example
```yaml
- name: Run tests with coverage
run: mvn clean test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: ./target/site/jacoco/jacoco.xml
```
#### Jenkins Example
```groovy
stage('Test') {
steps {
sh 'mvn clean test'
jacoco(
execPattern: 'target/jacoco.exec',
classPattern: 'target/classes',
sourcePattern: 'src/main/java'
)
}
}
```
### Writing New Tests
Create test classes in `src/test/java/` following this pattern:
```java
package com.example.service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.*;
@DisplayName("Your Service Tests")
class YourServiceTest {
private YourService service;
@BeforeEach
void setUp() {
service = new YourServiceImpl();
}
@Test
@DisplayName("Should do something")
void testSomething() {
// Arrange
String input = "test";
String expected = "result";
// Act
String result = service.doSomething(input);
// Assert
assertEquals(expected, result);
}
}
```
### Troubleshooting
#### Tests Not Running
```bash
# Ensure test files end with Test.java
# Verify directory: src/test/java/
# Check pom.xml includes maven-surefire-plugin
```
#### Coverage Reports Not Generated
```bash
# Ensure JaCoCo plugin is in pom.xml
mvn clean test
# Or use Docker
docker-compose -f docker-compose.coverage.yml up --build
```
#### Permission Issues (Linux/Mac)
```bash
chmod +x run-tests.sh
chmod +x run-coverage.sh
```
---
## Service Endpoints ## Service Endpoints
Once running, the following endpoints are available: Once running, the following endpoints are available:

View File

@ -1,346 +0,0 @@
# Unit Testing Guide
This guide explains how to run and write unit tests for the JAX-WS Hello World Service project.
## Quick Start
### Run Tests with Docker (Recommended)
#### Windows
```cmd
run-tests.bat
```
#### Linux/Mac
```bash
./run-tests.sh
```
### Run Tests with Maven (Local)
If you have Maven installed locally:
```bash
mvn test
```
## Test Results Summary
### Current Test Coverage
| Service | Test Class | Test Cases | Status |
|---------|-----------|------------|--------|
| Hello World Service | HelloWorldServiceImplTest | 10 | ✅ Passing |
### Test Case Details
The `HelloWorldServiceImplTest` includes the following test cases:
1. **testGetHelloWorld_WithValidName** - Verifies greeting with valid name
2. **testGetHelloWorld_WithEmptyString** - Handles empty string input
3. **testGetHelloWorld_WithNull** - Handles null input gracefully
4. **testGetHelloWorld_WithSpecialCharacters** - Handles special characters
5. **testGetHelloWorld_WithSpaces** - Handles names with spaces
6. **testGetHelloWorld_WithLongName** - Handles long names
7. **testGetHelloWorld_ReturnsNonNull** - Ensures non-null response
8. **testGetHelloWorld_StartsWithHelloWorld** - Verifies message format
9. **testGetHelloWorld_EndsWithExclamation** - Verifies message ending
10. **testGetHelloWorld_ContainsName** - Verifies name inclusion
## Docker Test Configuration
### Test Architecture
The project uses a multi-stage Dockerfile:
- **Stage 1 (tester)**: Runs unit tests
- **Stage 2 (builder)**: Builds the WAR file
- **Stage 3**: Deploys to Tomcat
### Test Docker Compose
The `docker-compose.test.yml` file is configured to:
- Target the `tester` stage of the Dockerfile
- Mount source code for live testing
- Cache Maven dependencies for faster subsequent runs
- Set appropriate memory limits
### Run Tests Manually
```bash
# Build and run tests
docker-compose -f docker-compose.test.yml up --build
# Clean up after tests
docker-compose -f docker-compose.test.yml down
```
## Testing Framework
### Dependencies
The project uses:
- **JUnit 5 (Jupiter)** - Testing framework
- `junit-jupiter-api:5.9.3` - Test annotations and assertions
- `junit-jupiter-engine:5.9.3` - Test execution engine
- **Mockito** - Mocking framework (for future complex tests)
- `mockito-core:5.3.1` - Core mocking functionality
- `mockito-junit-jupiter:5.3.1` - JUnit 5 integration
- **Maven Surefire** - Test runner plugin
- Configured to run all `*Test.java` files
## Writing New Tests
### Test Structure
Tests follow the standard JUnit 5 structure:
```java
package com.example.service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.*;
@DisplayName("Service Tests")
class YourServiceTest {
private YourService service;
@BeforeEach
void setUp() {
service = new YourServiceImpl();
}
@Test
@DisplayName("Should do something")
void testSomething() {
// Arrange
String input = "test";
String expected = "expected result";
// Act
String result = service.doSomething(input);
// Assert
assertEquals(expected, result);
}
}
```
### Test Best Practices
1. **Use Descriptive Names**: Use `@DisplayName` for readable test descriptions
2. **Follow AAA Pattern**: Arrange, Act, Assert
3. **Test Edge Cases**: Include null, empty, and boundary conditions
4. **Keep Tests Isolated**: Each test should be independent
5. **Test One Thing**: Each test should verify one specific behavior
### Adding Tests for New Services
To add tests for other services (e.g., LoanApprovalService):
1. Create test class in `src/test/java/com/example/service/`
2. Follow the naming convention: `{ServiceName}Test.java`
3. Run tests to verify
Example structure for LoanApprovalService tests:
```java
package com.example.service;
import com.example.model.*;
import com.example.repository.*;
import org.junit.jupiter.api.*;
import org.mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@DisplayName("LoanApprovalService Tests")
class LoanApprovalServiceTest {
@Mock
private CustomerRepository customerRepository;
@Mock
private CreditScoreService creditScoreService;
private LoanApprovalService service;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
service = new LoanApprovalService();
// Inject mocks if needed
}
@Test
@DisplayName("Should approve loan for high credit score")
void testLoanApproval_HighCreditScore() {
// Test implementation
}
}
```
## Test Directory Structure
```
src/
├── main/
│ └── java/
│ └── com/
│ └── example/
│ └── service/
│ ├── HelloWorldService.java
│ └── HelloWorldServiceImpl.java
└── test/
└── java/
└── com/
└── example/
└── service/
└── HelloWorldServiceImplTest.java
```
## Continuous Integration
### Running Tests in CI/CD
The Dockerfile includes testing as the first stage, which means:
- Tests run automatically during Docker build
- Build fails if tests fail
- Ensures code quality before deployment
To run tests in CI/CD pipelines:
```bash
# Option 1: Run full build (includes tests)
docker build -t jaxws-app .
# Option 2: Run tests only
docker build --target tester -t jaxws-test .
# Option 3: Use docker-compose
docker-compose -f docker-compose.test.yml up --abort-on-container-exit
```
## Viewing Test Reports
### Console Output
Test results are displayed in the console with summary:
```
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.example.service.HelloWorldServiceImplTest
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.024 s
Results:
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
```
### Surefire Reports
Maven Surefire generates detailed reports in:
- `target/surefire-reports/` (text and XML formats)
## Troubleshooting
### Tests Not Running
**Problem**: Maven doesn't find tests
**Solution**:
- Ensure test files end with `Test.java`
- Verify test directory structure: `src/test/java/`
- Check pom.xml includes maven-surefire-plugin
### Docker Build Fails on Tests
**Problem**: Docker build fails at test stage
**Solution**:
```bash
# View detailed test output
docker build --target tester -t jaxws-test .
# Check test container logs
docker logs <container-id>
```
### Dependency Issues
**Problem**: Cannot resolve JUnit dependencies
**Solution**:
```bash
# Clear Maven cache and rebuild
docker-compose -f docker-compose.test.yml build --no-cache
```
### Permission Denied on run-tests.sh
**Problem**: Cannot execute run-tests.sh on Linux/Mac
**Solution**:
```bash
chmod +x run-tests.sh
./run-tests.sh
```
## Future Enhancements
Consider adding tests for:
1. **LoanApprovalService**
- Customer registration workflows
- Loan approval logic
- Credit score evaluation
- Blacklist handling
2. **Repository Layer**
- Database operations
- CRUD functionality
- Error handling
3. **Integration Tests**
- End-to-end SOAP request/response
- Database integration
- Multi-service workflows
4. **Performance Tests**
- Load testing
- Stress testing
- Response time validation
## Resources
- [JUnit 5 User Guide](https://junit.org/junit5/docs/current/user-guide/)
- [Mockito Documentation](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html)
- [Maven Surefire Plugin](https://maven.apache.org/surefire/maven-surefire-plugin/)
- [Test-Driven Development Best Practices](https://martinfowler.com/bliki/TestDrivenDevelopment.html)
## Summary
This project now has a complete unit testing setup with:
- ✅ JUnit 5 testing framework
- ✅ 10 passing test cases for HelloWorldService
- ✅ Docker-based test execution
- ✅ Convenient test runner scripts
- ✅ Multi-stage Dockerfile with test stage
- ✅ Maven Surefire configuration
- ✅ Mockito for future mocking needs
To add more tests, simply create new test classes following the established patterns and run them using the provided scripts.

View File

@ -0,0 +1,32 @@
version: '3.8'
services:
coverage:
build:
context: .
dockerfile: Dockerfile.coverage.simple
image: jaxws-coverage:latest
container_name: jaxws-coverage-report
volumes:
# Mount source code
- ./src:/app/src:ro
- ./pom.xml:/app/pom.xml:ro
# Mount target directory to export coverage reports to host
- ./target:/app/target
# Mount Maven cache to speed up builds
- maven-cache:/root/.m2
environment:
- MAVEN_OPTS=-Xmx512m
command: >
sh -c "mvn test &&
echo '=================================================================================' &&
echo 'Coverage report generated successfully!' &&
echo '=================================================================================' &&
echo 'HTML Report: ./target/site/jacoco/index.html' &&
echo 'XML Report: ./target/site/jacoco/jacoco.xml' &&
echo 'CSV Report: ./target/site/jacoco/jacoco.csv' &&
echo '================================================================================'"
volumes:
maven-cache:
driver: local

View File

@ -12,6 +12,8 @@ services:
# Mount source for live testing during development # Mount source for live testing during development
- ./src:/app/src:ro - ./src:/app/src:ro
- ./pom.xml:/app/pom.xml:ro - ./pom.xml:/app/pom.xml:ro
# Mount target directory to access test reports and coverage on host
- ./target:/app/target
# Mount Maven cache to speed up subsequent test runs # Mount Maven cache to speed up subsequent test runs
- maven-cache:/root/.m2 - maven-cache:/root/.m2
command: mvn test command: mvn test

21
pom.xml
View File

@ -108,6 +108,27 @@
</includes> </includes>
</configuration> </configuration>
</plugin> </plugin>
<!-- JaCoCo Plugin for code coverage -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

44
run-coverage.bat Normal file
View File

@ -0,0 +1,44 @@
@echo off
REM Script to generate code coverage reports using Docker
echo ================================================================================
echo Generating Code Coverage Reports
echo ================================================================================
echo.
REM Clean previous reports
if exist target\site\jacoco (
echo Cleaning previous coverage reports...
rmdir /s /q target\site\jacoco
echo.
)
REM Run tests with coverage
docker-compose -f docker-compose.coverage.yml up --build
echo.
echo ================================================================================
echo Coverage Report Generated
echo ================================================================================
echo.
echo HTML Report: target\site\jacoco\index.html
echo XML Report: target\site\jacoco\jacoco.xml
echo CSV Report: target\site\jacoco\jacoco.csv
echo.
echo Open the HTML report in your browser to view coverage details.
echo.
REM Clean up the coverage container
docker-compose -f docker-compose.coverage.yml down
REM Ask user if they want to open the report
set /p OPEN_REPORT="Would you like to open the coverage report now? (y/n): "
if /i "%OPEN_REPORT%"=="y" (
if exist target\site\jacoco\index.html (
start target\site\jacoco\index.html
) else (
echo Error: Coverage report not found!
)
)
pause

50
run-coverage.sh Normal file
View File

@ -0,0 +1,50 @@
#!/bin/bash
# Script to generate code coverage reports using Docker
echo "================================================================================"
echo "Generating Code Coverage Reports"
echo "================================================================================"
echo ""
# Clean previous reports
if [ -d "target/site/jacoco" ]; then
echo "Cleaning previous coverage reports..."
rm -rf target/site/jacoco
echo ""
fi
# Run tests with coverage
docker-compose -f docker-compose.coverage.yml up --build
echo ""
echo "================================================================================"
echo "Coverage Report Generated"
echo "================================================================================"
echo ""
echo "HTML Report: target/site/jacoco/index.html"
echo "XML Report: target/site/jacoco/jacoco.xml"
echo "CSV Report: target/site/jacoco/jacoco.csv"
echo ""
echo "Open the HTML report in your browser to view coverage details."
echo ""
# Clean up the coverage container
docker-compose -f docker-compose.coverage.yml down
# Ask user if they want to open the report (for systems with xdg-open)
read -p "Would you like to open the coverage report now? (y/n): " OPEN_REPORT
if [ "$OPEN_REPORT" = "y" ] || [ "$OPEN_REPORT" = "Y" ]; then
if [ -f "target/site/jacoco/index.html" ]; then
# Try to open with default browser
if command -v xdg-open > /dev/null; then
xdg-open target/site/jacoco/index.html
elif command -v open > /dev/null; then
open target/site/jacoco/index.html
else
echo "Please open target/site/jacoco/index.html manually in your browser."
fi
else
echo "Error: Coverage report not found!"
fi
fi

4
scripts/run_coverage.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
echo "Running tests with code coverage..."
mvn clean test
echo "Coverage report generated in target/site/jacoco/"