Monday, 19 January 2026

Understanding Software Testing Using a Simple JSP Web App

 

🎯 Lab Context (Very Important)

This project is a basic Maven web application created for learning DevOps concepts.

  • It displays a simple Hello World page (index.jsp)

  • It runs on Tomcat

  • Initially, it has no Java logic and no tests

  • Our goal is NOT to build a full application

  • Our goal IS to understand testing in CI/CD

⚠️ This lab focuses on learning testing concepts, not building features.


 

1️⃣ What Is Software Testing? 

✅ What

Software testing is how we verify that code behaves as expected.

In simple words:

“If I change something, how do I know I didn’t break it?”

✅ Why Testing Exists (DevOps Perspective)

In DevOps:

  • Code changes are frequent

  • Builds are automated

  • Deployments are fast

Without tests:

  • Bugs reach production

  • Pipelines deploy broken code

  • Teams lose confidence

Tests act as safety checks in the pipeline. 

✅ Types of Testing (High-Level)

TypeWhat it testsTool
 Unit TestJava logicJUnit
UI TestWeb pagesSelenium
Integration TestMultiple componentsTest frameworks
Security TestVulnerabilitiesSnyk
Quality ScanCode qualitySonarQube








2️⃣ Why We Do NOT Test index.jsp with JUnit

What index.jsp is:

  • A view

  • Mostly HTML

  • Rendered by Tomcat

What JUnit is designed for:

  • Java classes

  • Java methods

  • Business logic

JUnit:
❌ does not start Tomcat
❌ does not render JSPs
❌ does not test HTML

✅ Key Learning

Not all code is tested the same way.

This is a very important DevOps concept.

3️⃣ The Real-World Testing Pattern (What Companies Do)

Instead of testing JSPs directly, companies:

  • Keep JSPs simple

  • Put logic in Java classes

  • Unit-test the Java logic

Simple Architecture

Browser ↓ index.jsp (VIEW – not unit tested) ↓ HelloService (LOGIC – unit tested)

This keeps testing:

  • fast

  • reliable

  • automation-friendly



4️⃣ Why We Add a Small Java Class (Even for Hello World)

You may ask:

“Why add Java code if the app is just Hello World?”

Answer:

Because testing needs executable logic.

Without Java code:

  • No tests can run

  • No coverage can be generated

  • JaCoCo has nothing to measure

So we add the smallest possible logic to teach testing correctly.


5️⃣ Step-by-Step: Add Testable Java Logic

Step 5.1 — Create a simple Java class

Path

MyWebApp/src/main/java/com/mywebapp/HelloService.java

You can do this directly in bitbucket or locally and push
to bitbucket


package com.mywebapp; public class HelloService { public String getMessage() { return "Hello World"; } }
Commit changes

📘 This class:

  • Contains logic

  • Can be executed

  • Can be tested

  • Can be measured by coverage tools


6️⃣ Step-by-Step: Write a Unit Test (JUnit)

Step 6.1 — Create a test class

Path

MyWebApp/src/test/java/com/mywebapp/HelloServiceTest.java


package com.mywebapp; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class HelloServiceTest { @Test void shouldReturnHelloWorldMessage() { HelloService service = new HelloService(); assertEquals("Hello World", service.getMessage()); } }

What this test does:

  • Calls the method

  • Checks the output

  • Passes if correct

  • Fails if changed


7️⃣ Running Tests (Understanding the Commands)

🔹 Run tests only

mvn clean test

This:

  • Compiles code

  • Runs unit tests

  • Does not generate coverage


🔹 Run tests WITH coverage (important for this lab)

mvn clean verify -Pcoverage

What -Pcoverage means:

  • Activates the coverage profile

  • Enables JaCoCo

  • Attaches the JaCoCo agent

  • Generates coverage data

📍 Output file:

MyWebApp/target/site/jacoco/jacoco.xml

8️⃣ What Is Code Coverage? (Simple Explanation)

Coverage answers:

“How much of my Java code was executed by tests?”

Examples:

  • 0% → No tests ran

  • 50% → Some code executed

  • 100% → All code executed

⚠️ Coverage does NOT mean “bug-free”
It means tested execution paths


9️⃣ How This Fits into Jenkins (Big Picture)

In Jenkins:

  1. Code is checked out

  2. Maven runs tests

  3. JaCoCo generates coverage

  4. SonarQube reads the coverage

  5. Pipeline decides:

    • PASS → deploy

    • FAIL → stop

This is real CI/CD behavior.


In Your Free style job Add below in your maven config

change from

clean install -Dv=${BUILD_NUMBER} sonar:sonar

To

clean verify -Pcoverage -Dv=${BUILD_NUMBER} sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml


✅ Report File Pattern

**/target/site/jacoco/jacoco.xml



1) Add Maven Surefire plugin

Your build log showed an ancient surefire (2.12.4)

which often results in “No tests to run”

even when tests exist.

UPDATE YOUR POM

Add this inside <build><plugins> (outside the profile):

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> </plugin>

FINAL POM BELOW

<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mywebapp</groupId> <artifactId>mywebapp</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>MyWebApp</name> <properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <jacoco.version>0.8.11</jacoco.version> </properties> <profiles> <profile> <id>coverage</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.version}</version> <!-- 1️⃣ Prepare the agent before tests --> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <!-- 2️⃣ Generate the XML report after tests --> <execution> <id>report</id> <phase>verify</phase> <goals> <goal>report</goal> </goals> <configuration> <!-- We only need the XML form for SonarQube --> <outputDirectory>${project.build.directory}/site/jacoco</outputDirectory> <outputEncoding>UTF-8</outputEncoding> <formats> <format>XML</format> </formats> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> </profiles> <dependencies> <!-- Old JUnit already present — keep it --> <!-- Example dependency for unit tests --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>MyWebApp</finalName> <plugins> <!-- JDK 21 Maven Compiler --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <release>21</release> </configuration> </plugin> <!-- WAR packaging support --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.4.0</version> </plugin> <plugin> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>5.2.0.4988</version> </plugin> </plugins> </build> </project>


No comments:

Post a Comment

Understanding Software Testing Using a Simple JSP Web App

  🎯 Lab Context (Very Important) This project is a basic Maven web application created for learning DevOps concepts. It displays a sim...