COMP8040 – Cloud Application
Frameworks
Testing, Test-Driven Development and Continuous
Integration
Introduction
Complexity is an issue with Cloud
Applications
Many components, often logically and
spatially dispersed
Components must be tested in isolation
But also tested as a whole
We must continuously test how our
components are integrating
(c) Larkin Cunningham
2
Testing
(c) Larkin Cunningham
3
System Under Test (SUT)
SUT can be a single component (or unit),
such as a Data Access Object or Service
Object
We will consider SUT to be an object
that has defined inputs and outputs
In other words, an API, such as one
defined using a Java or PHP Interface
However, we will also consider the
“behaviour” of the SUT when discussing
Mocking
(c) Larkin Cunningham
4
SUT
The SUT should be something that is
verifiable
E.g. for a given input, we expect a certain
output (or that certain behaviour is
followed)
Can test expected outcome versus actual
outcome
Corrections made when there is a
mismatch
(c) Larkin Cunningham
5
Traditional Approach
It has long been the approach to write
tests first
This predates the idea of Test-Driven
Development
A unit test document would contain a
table of suggested test inputs and
expected outputs for each testable unit
However, a very manual process that is
prone to abuse
(c) Larkin Cunningham
6
Agile Approach
Central tenet of the “Agile Manifesto” is
Test-Driven Development or TDD
Agile Manifesto a bit like US Declaration
of Independence or Irish Constitution
A set of 12 guiding principles that, when
followed, should result in quality software
being delivered
If you agree with the principles, you can
sign the manifesto!
(c) Larkin Cunningham
7
Agile Manifesto
I will refer back to some of the principles
over the next few weeks.
One of interest to testing (principle #7):
“Working software is the primary measure of
progress”
How do we know “where we stand” if
we leave testing until the end?
We should test as we go so that there
are fewer surprises at the end
(c) Larkin Cunningham
8
Test Often and Early
The earlier we discover an issue, the
cheaper it is to resolve
But it should also speed up development
The larger the system, the more you will
get payback by testing early
You should write tests at the time you
write the functional code… when you
have the clearest understanding of it
(c) Larkin Cunningham
9
Test First Approach
As mentioned, even traditional approach
suggests writing tests first
This forces the designer and/or developer
to consider use cases up front
Only that which can be tested should be
included
If you can’t test it, why not?
◦ Redesign?
(c) Larkin Cunningham
10
Test-Driven Development
TDD developed by Kent Beck as part of
Extreme Programming (an agile approach)
Three steps:
◦ Write the test first for the next piece of
functionality you are tackling
◦ Write the functional code until the test(s)
pass
◦ Refactor both test and functional code to
improve structure
(c) Larkin Cunningham
11
Test-Driven Development
The system becomes “self testing”,
allowing for considerable automation
Though TDD dictates writing the test
first, this is not always done in practice
Often the upfront design is not very
formal and coders get right into the code
Difficult to write tests first in that
scenario
(c) Larkin Cunningham
12
Pragmatism
Important thing is that code is verifiable,
not whether test was written first
Pragmatism rules
Speaking of pragmatism, Andrew Hunt and
David Thomas, in their thought-provoking
book, The Pragmatic Programmer, suggest a
number of tips
◦ http://pragprog.com/the-pragmaticprogrammer/extracts/tips
(c) Larkin Cunningham
13
Pragmatic Programming Tips
Test Your Software, or Your Users
Will
Test ruthlessly. Don’t make your users
find bugs for you.
Use Assertions to Prevent the
Impossible
Assertions validate your assumptions. Use
them to protect your code from an
uncertain world.
(c) Larkin Cunningham
14
Pragmatic Programming Tips
Coding Ain’t Done ‘Til All the Tests
Run
‘Nuff said.
Refactor Early, Refactor Often
Just as you might weed and rearrange a
garden, rewrite, rework, and re-architect
code when it needs it. Fix the root of the
problem.
(c) Larkin Cunningham
15
Pragmatic Programming Tips
Design to Test
Start thinking about testing before you
write a line of code.
Test State Coverage, Not Code
Coverage
Identify and test significant program
states. Just testing lines of code isn’t
enough.
(c) Larkin Cunningham
16
Pragmatic Programming Tips
Test Early.Test Often.Test
Automatically.
Tests that run with every build are much
more effective than test plans that sit on a
shelf.
Find Bugs Once
Once a human tester finds a bug, it should
be the last time a human tester finds that
bug. Automatic tests should check for it
from then on.
(c) Larkin Cunningham
17
Assertions
“Use Assertions to Prevent the
Impossible”
We make assumptions all the time – but
you should never assume
If component A receives values x and y, then
it will return the value z
We can code these assertions to ensure
that our components are functioning
correctly
(Note I did not say “behave” correctly)
(c) Larkin Cunningham
18
Test Frameworks
There are several popular frameworks for
many programming platforms
Some have been ported, or have inspired,
on a cross-platform basis
E.g. the so-called xUnit test frameworks,
such as JUnit, Nunit, PHPUnit, etc.
You had an introduction to basic JUnit
Let’s briefly examine PHPUnit in Laravel
(c) Larkin Cunningham
19
PHPUnit and Laravel
See http://laravel.com/docs/testing and
http://phpunit.de/manual/current/en/index.html
Can do standard tests, e.g. test a service or
repository class
Also has support for front-end testing – e.g.
calling routes and getting data from a view
or seeing if a view redirects
Note: Spring MVC (later…) has a
ModelAndViewAssert class, but this is
outside of the scope of the module
(c) Larkin Cunningham
20
PHPUnit and Laravel
Test classes go in app/tests
Run all tests by issuing the command
“phpunit” from command prompt, while in
the project root folder
PHPUnit config found in phpunit.xml in root
of project
By default has:
<testsuites>
<testsuite name="Application Test Suite">
<directory>./app/tests/</directory>
</testsuite>
</testsuites>
(c) Larkin Cunningham
21
PHPUnit and Laravel – Simple Test
class AuthorViewTest extends TestCase {
/**
* Test the author list view
*
* @return void
*/
public function testBookShowView()
{
$response = $this->call('GET', '/book/1');
$this->assertContains('23232342',
$response->getContent());
}
}
We will look at more Laravel testing in later
lectures….
(c) Larkin Cunningham
22
Automation
JUnit and PHPUnit facilitate automation
This means we can run entire suites of
tests at the press of a button
It also facilitates Continuous Integration,
which we will discuss in more detail
shortly
We can instantly see if our system is
broken
(c) Larkin Cunningham
23
Test Consistency
Spring’s test library includes transactional
support to roll back changes made in a
database
However, this is not necessary if we use
an in-memory database, such as HSQLDB
or SQLite (when not using a file)
(c) Larkin Cunningham
24
Test Consistency
If we are using an in-memory database
and start a Spring or Laravel application
anew, it will start with a fresh database
every time
Very useful for consistent testing
If the data was different for each run, we
would not be able to test set scenarios
over and over
(c) Larkin Cunningham
25
Test Consistency
For example, if we want to check that
applying a 10% increase to Bob’s salary
will result in a salary of €44,000, it would
not make sense if for the first test, our
initial test data was a salary of €40,000
and for the second it was €44,000 and for
the third it was €48,400 and so on
In-memory database with SQL DDL and
Inserts ensures test consistency
(c) Larkin Cunningham
26
Test Consistency
However, there can be issues with this
SQL dialect might be different between
the In-memory database, e.g. HSQLDB,
and your production database, e.g. MySQL
Do you code to the lowest common
denominator and ensure SQL syntax used
is compatible with both?
Do you make modifications to SQL when
deploying?
(c) Larkin Cunningham
27
Test Consistency
Or do you not go with In-memory and go
with a full test database server?
If you do, then you need a new strategy to
maintain test data consistency
What about a custom database script that
is run each time we run a suite of tests?
It could load fresh data each time
But could be time consuming – might take
too long for testing to begin
(c) Larkin Cunningham
28
Test Consistency
Alternative is to make use of database
transaction handling
Transaction begins and rolls back at the
end of testing… or if the testing fails
Spring makes this easy
Guess how?
Using annotations…
(c) Larkin Cunningham
29
JUnit – Spring Transactions
Annotate Test Class with:
◦ @TransactionConfiguration(defaultRollback=true)
Annotate unit test methods with:
◦ @Transactional
(c) Larkin Cunningham
30
Code versus State Coverage
“Test State Coverage, Not Code
Coverage”
If you aim for full code coverage your test
suite should test:
◦
◦
◦
◦
Every branch (if-else, switch/case, etc)
Every function
Every statement
Every condition – see what happens for both
true and false
◦ And…
(c) Larkin Cunningham
31
Code versus State Coverage
Each state should be tested
If we focus just on state coverage, we are
not interested in what happens in
between
E.g. we can focus on use cases and test
scenarios – states might include entry and
exit states to/from the SUT
Our JUnit test case methods will focus on
testing use cases
(c) Larkin Cunningham
32
Code Coverage
Can tend towards full code coverage with
additional test libraries and tools
Libraries like Mockito and PowerMock
allow you to test behaviour, e.g. ensure
that certain methods have been called by
the unit under test
Cobertura is a reporting tool that shows
you the level of coverage of your tests
◦ http://cobertura.github.io/cobertura/
(c) Larkin Cunningham
33
Code Coverage
Corbertura example showing an
exception we haven’t test for:
(c) Larkin Cunningham
34
Integration Testing
Not only test units in isolation, but in
context
Usually SUT will have dependencies
If we never test the SUT along with its
dependencies, might get out of synch with
other components
Particularly important when developing
distributed components (big concern for
Cloud Applications)
◦ If you change your API, have you tested that
dependent components still work?
(c) Larkin Cunningham
35
Integration Testing
Spring’s annotations and dependency
injection facilitates integration testing
However, what about complex test
scenarios?
What if my test depends on a web service
or queue or database
◦ Environmental dependency
Can use mocking and stubbing
(c) Larkin Cunningham
36
Mocking and Stubbing
For a good article on the difference, see:
◦ http://martinfowler.com/articles/mocksArentS
tubs.html
Stub requires you to develop a new Stub
component with method stubs that
return made-up / test data
It does allow you to remove
environmental dependencies from your
tests
(c) Larkin Cunningham
37
Mocking and Stubbing
However, stubbing requires you to
implement the full interface whether your
test(s) require it or not and requires
more code outside of the test to be
maintained
Mocking allows you to avoid having to
implement a full interface
You create a mock object and define
mock behaviour
(c) Larkin Cunningham
38
Mocking and Stubbing
Mocks allow you to verify behaviour as
well as state
Can verify, for example, that a method
was called 3 times or that methods were
called in a certain sequence
Approaches code coverage
This behaviour verification is outside the
scope of this module and only applies on
a case by case basis anyway
(c) Larkin Cunningham
39
Mockito Demo
Several Mocking libraries out there for
Java
◦
◦
◦
◦
JMock
PowerMock
Mockito
EasyMock
We will look later at Mockery for PHP
However, now let us take a look at
Mockito in action with Spring…
(c) Larkin Cunningham
40
Live Demo performed…
(c) Larkin Cunningham
41
Summary
Test Early and Often
Testing forces you to think about your
design and might help you code faster
Automate your tests to instantly see
whether your system is broken
Use JUnit, PHPUnit, or similar, to test the
integration of components
Avoid environmental issues by mocking
(c) Larkin Cunningham
42
© Copyright 2026 Paperzz