Software Testing
Software Testing
│
├── 1. Based on Testing Method
│ ├── 1.1 Manual Testing
│ │ ├── Exploratory Testing
│ │ ├── Ad-hoc Testing
│ │ └── Usability Testing
│ └── 1.2 Automation Testing
│ ├── Regression Testing
│ ├── API Automation
│ ├── UI Automation (Selenium, Cypress)
│ ├── Performance Testing (JMeter, K6)
│ └── Continuous Testing (CI/CD)
│
├── 2. Based on Testing Levels (SDLC Phases)
│ ├── 2.1 Unit Testing
│ ├── 2.2 Integration Testing
│ │ ├── Big Bang Integration
│ │ ├── Top-Down
│ │ ├── Bottom-Up
│ │ └── Sandwich/Hybrid
│ ├── 2.3 System Testing
│ │ ├── Functional Testing
│ │ ├── End-to-End Testing
│ │ ├── Non-Functional Testing
│ │ └── Recovery Testing
│ └── 2.4 Acceptance Testing (UAT)
│ ├── Alpha Testing
│ └── Beta Testing
│
├── 3. Based on Knowledge of Internal Structure
│ ├── 3.1 Black Box Testing
│ │ ├── Functional Testing
│ │ ├── System Testing
│ │ ├── Acceptance Testing
│ │ └── Usability Testing
│ ├── 3.2 White Box Testing
│ │ ├── Unit Testing
│ │ ├── Code Coverage Testing
│ │ ├── Path Testing
│ │ ├── Loop Testing
│ │ └── Security Code Analysis
│ └── .3 Gray Box Testing
│ ├── Integration Testing
│ ├── API Testing
│ ├── Database Testing
│ └── Session/State Testing
│
│
└── 4. Based on Focus Area
├── 4.1 Functional Testing
│ ├── Smoke Testing
│ ├── Sanity Testing
│ ├── Regression Testing
│ ├── API Testing
│ └── End-to-End Testing
└── 4.2 Non-Functional Testing
├── Performance Testing
│ ├── Load Testing
│ ├── Stress Testing
│ ├── Spike Testing
│ └── Endurance (Soak) Testing
├── Security Testing
│ ├── Vulnerability Scanning
│ ├── Penetration Testing
│ ├── Risk Assessment
│ └── Authentication/Authorization Testing
├── Usability Testing
│ └── UI/UX Evaluation
├── Compatibility Testing
│ ├── Browser Compatibility
│ ├── OS Compatibility
│ └── Device Compatibility
├── Reliability & Stability Testing
└── Compliance Testing
Manual Testing
Performed manually by testers to identify defects without automation tools.
1. Exploratory Testing
Tester explores the application without predefined test cases.
2. Ad-hoc Testing
Unstructured testing performed randomly to find defects.
3. Usability Testing
Checks how user‑friendly and intuitive the interface is.
Automation Testing
Uses scripts and tools to automate repetitive tests.
1. Regression Testing
Ensures new changes do not affect existing functionality.
2. API Automation
Automates API test cases to validate endpoints.
3. UI Automation
Automates browser actions using tools like Selenium/Cypress.
4. Performance Testing
Measures speed, stability, and scalability.
5. Continuous Testing
Automated tests run continuously in CI/CD pipelines.
2. Based on Testing Levels (SDLC Phases)
2.1 Unit Testing
Testing individual functions or components in isolation to ensure they work correctly.
Usually done by developers.
2.2 Integration Testing
Testing interactions between integrated modules to find interface or communication
defects.
Big Bang Integration
All modules are integrated and tested at once. Simple but hard to debug.
Top-Down Integration
Testing begins from top modules and moves downward using stubs for
lower modules.
Bottom-Up Integration
Testing starts from low-level modules upward using drivers for higher
modules.
Sandwich/Hybrid Integration
Combination of top-down and bottom-up methods to test middle layers early.
2.3 System Testing
Complete end-to-end testing of the entire application based on requirements.
Functional Testing
Checks whether the software performs all required business functions
properly.
End-to-End Testing
Validates full workflows across databases, APIs, UI, and integrated systems.
Non-Functional Testing
Evaluates performance, security, usability, scalability, and reliability.
Recovery Testing
Checks the system’s ability to recover from crashes, failures, or network
issues.
2.4 Acceptance Testing (UAT)
Final validation performed by end users or clients to ensure software meets business
needs.
Alpha Testing
Conducted internally to detect usability and functional defects before public
release.
Beta Testing
Performed by real users in a real environment to gather feedback before
final launch.
Black Box Testing
Tester knows nothing about internal code—focus on inputs and outputs.
White Box Testing
Tester knows code structure and validates logic paths.
Gray Box Testing
Tester has limited knowledge of internal structure.
Smoke Testing
Basic checks to ensure major features work.
Sanity Testing
Quick check after minor fixes.
End-to-End Testing
Validates entire workflows from start to end.
Load/Stress/Spike/Endurance Testing
Validates performance under different workload conditions.
Security Testing
Identifies vulnerabilities and security gaps.
Compatibility Testing
Ensures app works on different devices, OS, and browsers.
Reliability Testing
Ensures system performs consistently over time.
Compliance Testing
Ensures software follows required standards or regulations.
Manual Testing
Manual testing is still essential, even with automation, because tests must be run manually at
least once.
Acceptance testing is hard to automate due to unclear or complex requirements, making QA
expertise vital.
Good manual testing depends on:
Proper test data management
Ability to deploy new code quickly to verify fixes
Production data may be too large or sensitive to copy directly;
Every organization differs, so follow the KISS principle (Keep It Simple, Stupid) for effective
testing processes.
Pros and Cons of Test Automation
Test automation promises higher software quality, greater confidence in releases, and
reduced manual testing effort. However, in many organizations, real automation is limited due
to practical challenges and human factors.
Key Problems
Low-value cheap tests: Unit tests are easy to automate but often perceived as less
useful than manual testing.
Difficulty creating realistic test environments: Integration test environments
require hardware, licensing, and resources, making automation harder.
Tests need frequent updates: As software changes, tests must be maintained,
creating a feeling that automation increases workload.
Lack of DevOps culture: Poor collaboration between developers and operations
leads to low responsibility for failing tests.
Unreliable tests: Flaky tests cause developers to disable them, leading to ignored
build failures.
Writing good automated tests is hard: High-quality integration tests require deep
system understanding.
Overall Insight
Most challenges come from people, perceptions, and team dynamics rather than technology
alone.
Recommended Strategy
Leverage enthusiasm for test automation
Avoid unrealistic goals
Adopt incremental improvements
Unit Testing – Summary
Unit testing focuses on testing small, well-defined parts of a system in isolation. This makes
the tests easier to write, run, and maintain. Build tools like Maven provide built-in support for
organizing, running, and reporting unit tests, usually through simple conventions and
annotations.
Although unit and functional tests may use similar tools or libraries, their purposes differ, so
it’s important to ensure you're writing the correct type of test for the situation.
xUnit and JUnit
JUnit is a popular unit-testing framework for Java and part of the broader xUnit family of
testing frameworks. Variants exist for many languages, such as NUnit for C#. JUnit enables
developers to define and run tests easily.
Key JUnit Concepts
Test Runner: Executes tests and collects results (e.g.,command line, Maven
Surefire).
Test Case: A single test definition, usually created using annotations such as
@Test . Surefire also locates test classes that have the Test suffix in the class name
Test Fixture: A fixed setup (environment + data) that your test needs before it runs.
In JUnit, we use annotations:
🔹 @Before
Runs before each test
Used to setup environment
🔹 @After
Runs after each test
Used to clean/reset environment
import [Link].*;
public class CalculatorTest {
Calculator calc;
@Before
public void setup() {
calc = new Calculator(); // create fresh object
[Link]("Setup done");
}
@Test
public void testAddition() {
int result = [Link](2, 3);
[Link](5, result);
}
@Test
public void testSubtraction() {
int result = [Link](5, 2);
[Link](3, result);
}
@After
public void teardown() {
calc = null; // cleanup
[Link]("Cleanup done");
}
}
Test Suite: A group of related test cases sharing similar fixtures.
import [Link];
import [Link];
// This tells JUnit to run this class as a test suite
@RunWith([Link])
// List of test classes to include in the suite
@[Link]({
[Link],
[Link]
})
// Empty class – used only as a holder for annotations
public class AllTests {
}
Test Execution: Running test cases (or test suites), setting up required data
(fixtures), and checking results.
When you run [Link](your test suite file)
Setup done
Cleanup done
Setup done
Cleanup done
Tests run: 2, Failures: 0
Test Result Formatter: Formats test results (typically in XML) for tools like Jenkins.
JUnit Test Result
<testsuite name="CalculatorTest" tests="2" failures="1">
<testcase name="testAdd" classname="CalculatorTest"/>
<testcase name="testSub" classname="CalculatorTest">
<failure message="expected 2 but was 3"/>
</testcase>
</testsuite>
Converts test execution results into a structured format (usually XML) so that tools
like Jenkins can read and display them.
Assertions: Statements that validate conditions during tests, such as
assertEquals() , assertTrue() , and assertFalse() .
JUnit integrates smoothly with Java build tools and provides a strong foundation for effective
automated unit testing.
Chapter 6 – Testing the Code
In modern software development, releasing code frequently requires strong confidence
in the quality of the software. To achieve this, developers rely heavily on automated
testing. Testing ensures that software works correctly and that new changes do not
break existing functionality.
This chapter introduces several testing techniques and tools used in DevOps
environments such as:
Manual Testing
Unit Testing using JUnit
Integration Testing
GUI Testing using Selenium
Performance Testing using JMeter
Behavior Driven Development using Cucumber
Running automated tests using Jenkins CI
1. Manual Testing
Manual testing is the traditional method where testers execute test cases manually
without using automation tools. Although automation is powerful, manual testing is still
necessary, especially for:
Acceptance testing
User interface evaluation
Exploratory testing
Best Practices for Manual Testing
Maintain consistent test data
Deploy new builds quickly for verification
Protect sensitive user data in test environments
Keep testing processes simple (KISS principle)
2. Pros and Cons of Test Automation
Advantages
Improves software quality
Faster testing cycles
Supports Continuous Integration and Continuous Delivery
Reduces repetitive manual testing
Challenges
Writing automated tests requires effort
Test environments can be difficult to configure
Tests may break when software changes
Integration tests require complex infrastructure
To succeed with automation, teams should:
Start small
Work incrementally
Encourage collaboration between developers and operations teams
3. Unit Testing
Unit testing focuses on testing individual components of an application in isolation. It is
usually written by developers and is one of the easiest types of tests to automate.
Java developers commonly use the JUnit framework for unit testing.
Example JUnit Assertions
assertEquals(str1, str2);
assertTrue(val1 < val2);
assertFalse(val1 > val2);
Example Unit Test
import static [Link].*;
import [Link];
public class CalculatorTest {
@Test
public void testAddition(){
int result = 2 + 3;
assertEquals(5, result);
}
}
Key JUnit Concepts
Test Runner: Executes tests and collects results (e.g.,command line, Maven
Surefire).
Test Case: A single test definition, usually created using annotations such as
@Test . Surefire also locates test classes that have the Test suffix in the class
name
Test Fixture: A fixed setup (environment + data) that your test needs before it
runs.
In JUnit, we use annotations:
🔹 @Before
Runs before each test
Used to setup environment
🔹 @After
Runs after each test
Used to clean/reset environment
import [Link].*;
public class CalculatorTest {
Calculator calc;
@Before
public void setup() {
calc = new Calculator(); // create fresh object
[Link]("Setup done");
}
@Test
public void testAddition() {
int result = [Link](2, 3);
[Link](5, result);
}
@Test
public void testSubtraction() {
int result = [Link](5, 2);
[Link](3, result);
}
@After
public void teardown() {
calc = null; // cleanup
[Link]("Cleanup done");
}
}
Test Suite: A group of related test cases sharing similar fixtures.
import [Link];
import [Link];
// This tells JUnit to run this class as a test suite
@RunWith([Link])
// List of test classes to include in the suite
@[Link]({
[Link],
[Link]
})
// Empty class – used only as a holder for annotations
public class AllTests {
}
Test Execution: Running test cases (or test suites), setting up required data
(fixtures), and checking results.
When you run [Link](your test suite file)
Setup done
Cleanup done
Setup done
Cleanup done
Tests run: 2, Failures: 0
Test Result Formatter: Formats test results (typically in XML) for tools like
Jenkins.
JUnit Test Result
<testsuite name="CalculatorTest" tests="2" failures="1">
<testcase name="testAdd" classname="CalculatorTest"/>
<testcase name="testSub" classname="CalculatorTest">
<failure message="expected 2 but was 3"/>
</testcase>
</testsuite>
Converts test execution results into a structured format (usually XML) so that
tools like Jenkins can read and display them.
Assertions: Statements that validate conditions during tests, such as
assertEquals() , assertTrue() , and assertFalse() .
JUnit integrates smoothly with Java build tools and provides a strong foundation for
effective automated unit testing.
5. Mocking
Mocking allows developers to simulate external systems during testing. Instead of
connecting to real services (like databases), tests use mock objects.
A popular Java mocking framework is Mockito.
Example
List mockedList = mock([Link]);
when([Link](0)).thenReturn("Hello");
assertEquals("Hello", [Link](0));
6. Test Coverage
Test coverage measures the percentage of code executed during testing.
Suppose your program has 100 lines of code:
Your tests execute 80 lines
👉 Test Coverage = 80%
Higher coverage usually indicates better testing, but 100% coverage is not always
necessary.
Tools used for measuring coverage include:
Cobertura
Clover
JaCoCo
How Cobertura Works (Simple Idea)
👉 It modifies your compiled code (bytecode) by inserting extra instructions.
So internally:
Your Code → Modified Code → Run Tests → Track execution
👉 These extra instructions:
Count which lines are executed
Generate coverage report
Does 100% Coverage Mean Perfect Code?(Coverage ≠ Quality)
You can have:
High coverage❌ but useless tests
Lower coverage ✅ but meaningful tests
💻 Example 1: Useless Coverage
private int positiveValue;
void setPositiveValue(int x){
[Link] = x;
}
int getPositiveValue(){
return positiveValue;
}
Test Case:
@Test
public void testGetter() {
Calculator c = new Calculator();
[Link](10);
assertEquals(10, [Link]());
}
👉 Result:
Coverage increases ✔
But what are we testing? ❓
👉 Just checking: Java assigns values correctly
👉 Not very useful ❌
💡 Example 2: Meaningful Testing
Now improve the setter:
void setPositiveValue(int x){
if(x < 0){
throw new IllegalArgumentException("Negative not allowed");
}
[Link] = x;
}
Test Cases:
@Test
public void testValidValue() {
[Link](10);
assertEquals(10, [Link]());
}
@Test(expected = [Link])
public void testNegativeValue() {
[Link](-5);
}
👉 Now testing:
Logic ✔
Validation ✔
Error handling ✔
👉 This is useful testing ✔
Automated Integration Testing
Automated integration testing checks how different components of a system work
together. It is similar to unit testing in terms of tools and frameworks, but the key
difference is that it uses real systems instead of mocks.
Unit testing → uses mock data
Integration testing → uses real databases, APIs, or services
Ensures components interact correctly
Can be executed using the same test runners (e.g., Maven, JUnit)
For example, instead of mocking a database, an integration test connects to a real
database. This makes testing more realistic but also more complex.
Requires predictable and repeatable data
May use production data copies (after cleaning sensitive data)
Needs proper setup like database backup and restore
Docker in Automated Testing
Docker helps create consistent and isolated environments for integration testing. It
allows you to simulate real systems using containers.
Run multiple services (app, database) in containers
Simulate real production-like environments
Reset systems easily to a known state
Use Docker Compose to manage multiple containers
Example: You can run a database container and an application container together and
test how they communicate.
Jenkins can start/stop Docker containers during CI
Helps automate full system testing
Reproducible environments
Easy environment reset
Simulating distributed systems
However, challenges exist:
Hard to detect when services are fully started
May require scripts (polling logs, checking ports)
Some setup can be complex
Arquillian
Arquillian is a testing tool designed for Java applications that helps perform tests closer
to real production environments.
Used for testing Java application servers (e.g., WildFly)
Bridges the gap between unit testing and integration testing
Deploys code inside the application server for testing
The main idea of Arquillian is to test applications in an environment that closely
resembles the real system.
Provides more realistic results than mocking
Helps detect issues that occur only in real environments
Involves trade-offs like setup complexity
Overall, Arquillian shows how testing can move closer to real-world conditions,
improving software reliability.
Performance Testing
Performance testing is used to evaluate how a system behaves under different
workloads. It is especially important for large-scale applications and public websites
where many users access the system simultaneously.
To get accurate results, performance testing should be done in an environment that is
as close as possible to the production system.
Load Testing
The most common type of performance testing is load testing.
Simulates multiple users sending requests to the system
Measures response time, throughput, and errors
Helps identify system bottlenecks
In load testing, artificial (synthetic) requests are generated to check how the server
handles high traffic.
Apache JMeter
Apache JMeter is a popular open-source tool used for performance testing.
Generates heavy load on servers
Measures response times and performance metrics
Supports multiple protocols such as:
HTTP
LDAP
SOAP
JDBC
Although simpler than tools like LoadRunner, JMeter is powerful and widely used.
Integration with Build Tools and CI
JMeter can be integrated into modern development workflows:
Use Maven plugin to run performance tests during build
Run tests automatically in Jenkins CI server
Use Jenkins performance plugin to execute and analyze results
Performance Testing Workflow
A typical performance testing process in CI/CD looks like this:
Build the application
Deploy it to a test environment (similar to production)
Run JMeter test scenarios
Collect and analyze performance data
This helps teams predict how the application will behave in real-world conditions and
ensures that it can handle expected user traffic.
Automated Acceptance Testing
Automated acceptance testing ensures that the software works correctly from the end
user's perspective. It verifies whether the system meets business requirements and
user expectations.
One popular tool for this is Cucumber, which follows Behavior-Driven Development
(BDD).
Tests are written in plain English-like language
Easy for non-programmers (testers, product owners) to understand
Bridges the gap between developers and business teams
How Cucumber Works
Cucumber uses feature files written in a language called Gherkin. These files describe
application behavior in a readable format.
Feature → What we want to test
Scenario → Specific test case
Steps → Actions and expected results
Example Feature File
Feature: Addition
I would like to add numbers with my pocket calculator
Scenario: Integer numbers
* I have entered 4 into the calculator
* I press add
* I have entered 2 into the calculator
* I press equal
* The result should be 6 on the screen
This description is easy to understand even for non-technical users.
Java Example : If you use the Java 8 lambda version of Cucumber, a
test step could look somewhat like this
Calculator calc;
public MyStepdefs() {
Given("I have entered (\\d+) into the calculator", (Integer i) -> {
[Link](i);
});
When("I press (\\w+)", (String op) -> {
[Link](op);
});
Then("The result should be (\\d+)", (Integer i) -> {
assertThat([Link](), i);
});
}
Here, each step in the feature file is mapped to Java code using regular expressions.
Advantages
Readable and easy to understand
Encourages collaboration between teams
Focuses on user behavior, not just code
Challenges
Feature files must be written in a structured format
Requires matching steps using regular expressions
Small wording changes can break test code
Sometimes developers end up writing everything
Automated GUI Testing
Automated GUI (Graphical User Interface) testing is used to test how users interact with
an application’s interface. While it provides many benefits, it is also challenging to
maintain because user interfaces frequently change during development.
UI elements (buttons, fields) may move or change
Tests can easily break due to small UI updates
Maintenance effort can be high
Problems with Older GUI Testing Tools
Earlier GUI testing tools worked by simulating mouse clicks on fixed screen positions.
If a button moved → test failed
Tests were fragile and unreliable
Frequent UI changes increased maintenance cost
Selenium (Modern Approach)
Selenium is a widely used web GUI testing tool that solves many of these problems.
Instead of clicking based on position, it interacts with elements using the DOM
(Document Object Model).
Find elements using IDs, names, CSS selectors
More stable than coordinate-based testing
Works with multiple browsers
Supports automation through code
Example
WebDriver driver = new FirefoxDriver();
[Link]("[Link]
[Link]([Link]("login")).click();
Sikuli (Alternative Approach)
Sikuli is another GUI testing tool that uses image recognition. It is based on OpenCV
and identifies UI elements visually.
Works even if UI elements move
Useful for desktop applications and games
Relies on screenshots instead of DOM
Conclusion
Automated GUI testing is powerful but requires careful design. Tools like Selenium and
Sikuli provide different approaches:
Selenium → best for web applications
Sikuli → best for visual or desktop applications
Choosing the right tool depends on your application and testing needs.
Integrating Selenium Tests in Jenkins
Selenium automates browser actions by opening a browser, loading your application,
and interacting with elements using the DOM (Document Object Model).
Tests can be created by recording actions or writing code
Usually written using Selenium API (preferred)
Executed in CI tools like Jenkins
One challenge is that Jenkins servers are often headless (no UI). So we must
configure browsers and drivers properly.
Simple Selenium Example with [Link]
We will test a simple [Link] application that returns the sum of two numbers (2 + 3 =
5).
Step 1: [Link] Application
// [Link]
const express = require('express');
const add = require('./math');
const app = express();
[Link]('/', (req, res) => {
const sum = add(2, 3);
[Link](`Sum is: ${sum}`);
});
[Link](8080, () => {
[Link]("Server running on port 8080");
});
[Link]
// [Link]
function add(a, b){
return a + b;
}
[Link] = add;
Run the server:
node [Link]
Step 2: Simple Selenium Test
// [Link]
const { Builder, By } = require('selenium-webdriver');
(async function testApp() {
let driver = await new Builder().forBrowser('chrome').build();
try {
await [Link]("[Link]
let bodyText = await [Link]([Link]("body")).getText();
if([Link]("Sum is: 5")){
[Link]("Test Passed ✔");
} else {
[Link]("Test Failed ❌");
}
} finally {
await [Link]();
}
})();
Run the test:
node [Link]
What This Test Does
Opens Chrome browser
Loads your [Link] app
Reads page content
Checks if output is "Sum is: 5"
Jenkins Usage
node [Link] &
node [Link]
Include above two commands in jenkins pipeline in testing stage.
Jenkins runs the test and shows pass/fail output.
JavaScript Testing
Since most modern applications have web interfaces, JavaScript testing frameworks
are very important for ensuring frontend and backend correctness.
Karma → Test runner for executing JavaScript unit tests
Jasmine → Behavior-driven testing framework (similar to Cucumber)
Protractor → End-to-end testing framework for Angular applications
Protractor
Protractor is similar to Selenium but specifically designed for Angular applications.
Built on top of Selenium WebDriver
Supports writing tests in JavaScript
Understands Angular-specific features automatically
Unlike Selenium, Protractor has built-in knowledge of Angular’s model-view structure,
making it easier to locate elements and handle dynamic content.
Automatically waits for Angular tasks to finish
Provides special methods to interact with Angular components
Why Not Only Selenium?
Although Selenium can test any web application, Protractor simplifies testing for
Angular apps because it understands Angular internals.
Selenium → General-purpose testing
Protractor → Angular-specific optimization
Jest Example (Unit Testing)
Jest is a popular JavaScript testing framework used for unit testing. Let us test the
same add function used in our [Link] example.
[Link]
// [Link]
function add(a, b){
return a + b;
}
[Link] = add;
[Link]
// [Link]
const add = require('./math');
test('adds 2 + 3 to equal 5', () => {
expect(add(2, 3)).toBe(5);
});
Install and run Jest:
npm install --save-dev jest
"scripts": {
"test": "jest"
}
npm test
What This Test Does
Calls the function add(2, 3)
Checks if result equals 5
If correct → Test passes ✔
If wrong → Test fails ❌
Conclusion
Karma and Jasmine → Unit and behavior testing
Protractor → Angular-specific end-to-end testing
Jest → Simple and powerful unit testing tool
Using these tools together helps ensure that JavaScript applications are reliable and
maintainable.
Testing Backend Integration Points
Backend integration testing focuses on testing server-side components such as REST
APIs and SOAP services. These tests verify that different backend systems
communicate and work correctly together.
Tests APIs instead of UI
More stable than GUI tests
Requires less maintenance
Cost-effective and faster to execute
Why Backend Testing is Important
Backend interfaces (APIs) usually change less frequently compared to user interfaces.
This makes backend testing more reliable and easier to maintain.
Ensures correct data exchange between systems
Validates business logic
Detects integration issues early
SoapUI Tool
SoapUI is a popular tool used for testing web services such as REST and SOAP APIs.
It provides both a graphical interface and command-line support.
Create and run API test cases easily
Supports REST and SOAP services
Allows incremental test development
Provides structured test environment
Usage in Different Roles
Testers → Use GUI to create and run test cases
Developers → Integrate tests using Maven or command line
DevOps Engineers → Run tests in CI tools like Jenkins
CI/CD Integration
SoapUI tests can be integrated into build pipelines:
Run tests using Maven plugins
Execute tests from command line
Automate testing in Jenkins CI server
This ensures backend APIs are tested automatically whenever code changes.
Advantages
Stable and reliable testing
Easy to automate
Works well in CI/CD pipelines
Open-source version available
Limitations
GUI can be complex for beginners
Some advanced features are paid
Requires understanding of APIs (JSON/XML)
Conclusion
Backend integration testing is an efficient way to ensure that APIs and services work
correctly. Tools like SoapUI make it easy to create, run, and automate these tests,
making them an essential part of modern DevOps pipelines.
Test-Driven Development (TDD)
Test-Driven Development (TDD) is a software development approach where tests are
written before the actual code. It became popular as part of Extreme Programming
(XP) in the 1990s.
TDD focuses on understanding requirements first and ensuring correctness through
continuous testing.
TDD Cycle (Steps)
1. Write the Test
Start by writing a test based on requirements, use cases, or user stories.
2. Run the Test (Fail)
Execute the test. It should fail because the feature is not implemented yet.
3. Write Code
Write the minimum code required to make the test pass.
4. Run All Tests
Ensure the new test and existing tests all pass (no regression).
5. Refactor
Improve and clean the code without changing its behavior.
Key Ideas
Focus on requirements before coding
Write small, testable units
Ensure continuous validation
Maintain high code quality
Advantages
Produces reliable and bug-free code
Improves understanding of requirements
Creates strong test suites for CI/CD
Supports safe refactoring
Conclusion
TDD is a powerful development practice that integrates well with DevOps. Although it
requires discipline, it results in better design, cleaner code, and automated tests that
can be used in continuous integration pipelines.
REPL-Driven Development
REPL-driven development is a programming style commonly used with interpreted
languages such as Python, Ruby, JavaScript, and Lisp. REPL stands for Read–
Eval–Print–Loop, which allows developers to write and execute code interactively.
Developers write small and independent functions.
Functions should avoid or minimize global state and side effects.
Each function can be tested immediately while writing it in the REPL
environment.
This helps in quick debugging and better understanding of the code.
This approach differs slightly from Test-Driven Development (TDD). In TDD, tests are
written before the actual code is implemented. In REPL-driven development, the focus
is on writing simple, testable functions and verifying them interactively.
Encourages writing clean and modular code.
Works well with unit testing frameworks.
Helps developers build and test logic incrementally.
Combining REPL-driven development with unit testing can create a highly effective and
efficient development process.
13. Complete Testing Pipeline
In a typical DevOps pipeline, tests run in the following order:
1. Unit Tests
2. Integration Tests
3. API Tests
4. GUI Tests
5. Performance Tests
These tests are executed automatically using a CI server like Jenkins.
Summary
Software testing is essential for delivering reliable software. By combining different
testing strategies such as unit testing, integration testing, GUI testing, and performance
testing, teams can ensure high software quality.
Modern DevOps pipelines integrate these tests with CI/CD systems like Jenkins,
enabling continuous testing and faster software delivery.