COMP1549: Advanced Programming
Part a: Unit Testing
Part b: Version Control
Dr Markus Wolf
23rd February, 2023 - Week 6
COMP1549: Advanced Programming 1
Unit Testing
COMP1549: Advanced Programming 2
Why do we test our code?
◉ Is it to:
show what brilliant programmers we are by
demonstrating that our program doesn’t contain any
bugs
◉ or
find the bugs that certainly exist in our code before
anyone else spots them?
◉ “A good test is one that is likely to uncover a flaw
that was previously unknown.” (Sundsted 1999)
COMP1549: Advanced Programming 3
A Basic Problem of Testing
Even for simple programs there is never enough
time to carry out exhaustive testing (e.g. all
possible combinations of input)
Hence the development of strategies for
creating tests with the greatest chance of
revealing bugs
Two key strategies: Black-box testing and
White-box testing
COMP1549: Advanced Programming 4
Black Box
INPUTS ??? OUTPUTS
We don't know what's in the box but we do know what it is
meant to do - i.e. given a certain input we can predict the
correct output
COMP1549: Advanced Programming 5
Choosing Good Test Cases
◉ Imagine testing a function called calcCost
INPUTS calcCost OUTPUTS
Two integer If both parameters are >=
parameters zero return integer
representing: representing cost (price x
quantity)
• price per unit
• quantity of units Otherwise throw
IllegalArgumentException
COMP1549: Advanced Programming 6
Choosing Good Test Cases
• Choose 8 test cases with what you think are the best
chances of uncovering a bug
case Test case inputs Expected
output
1 price 5, quantity 4 20
2
3
4
5
6
7 Are 8 test cases enough?
8
COMP1549: Advanced Programming 7
White box
INPUTS ??? OUTPUTS
AT THE VERY LEAST
choose test cases so
We can see the code in the "box" at every line in the
code gets executed at
Still need to choose test cases with least once during
the best chance of catching the bugs testing
COMP1549: Advanced Programming 8
public void adjustSpeed() {
if (speed > 0) {
if (distance < 10) {
accelerate = false;
breakk = true;
} else if (distance < 50) {
accelerate = false;
} else if (speed < speedLimit) {
accelerate = true;
breakk = false;
} What are the minimum
} else { number of test cases
accelerate = true; required to ensure that all
breakk = false; the lines of code the
} method are executed?
resetReadings();
}
COMP1549: Advanced Programming 9
Another problem of testing
◉ Software doesn’t stay tested
◉ “But I only made a one line bug fix to the
MedicalRecord class to fix that
NullPointerException. I can’t possibly have
caused the whole Hospital system to crash.”
◉ Oh yes it can!!!!
◉ Hence the need for regression testing - a suite of
repeatable tests that can be used to test that
things still work after (perhaps seemingly
unrelated) modifications have been made
COMP1549: Advanced Programming 10
Unit/Component testing
◉ The type of testing most likely to be carried
out by programmers on their own code
◉ Shares many techniques and concepts with
other types of testing (integration testing,
system testing, etc.)
◉ The rest of the lecture focuses on this
COMP1549: Advanced Programming 11
Unit Testing
◉ The first unit testing software was called SUnit
Developed by Kent Beck (from Extreme
Programming fame) and Erich Gamma (one of the
Gang of Four, from Design Patterns fame)
Used for testing SmallTalk code
◉ Test frameworks now exist for many
programming languages
JUnit for Java, CppUnit for C++, NUnit for .NET,
many others
Known collectively as xUnit
Support built into most IDEs
COMP1549: Advanced Programming 12
The Problem
◉ Untested Code may not work
Large applications may have many complex code
paths that have never been entered during
development
Worse – code may only work some of the time
(because of threading or timing or other external issues
– such as network failure)
Even worse – some code appears to work, but in
actual fact doesn’t (this happens far more often than
you would believe possible)
COMP1549: Advanced Programming 13
The Problem cont.
◉ Untested code is hard to maintain
If you add one piece of functionality – it is possible it
will break an existing part of you application. How will
you know?
◉ Untested code is a black box – even with the
source code
Untested code means the assumptions of the
developer are buried deep down in source code. What
if their assumptions were wrong?
Documentation always falls behind developed code.
No one likes doing documentation
COMP1549: Advanced Programming 14
Am I Infected?
◉ Erich Gamma coined the phrase to describe
programmers who made writing tests part of their daily
programming
◉ Symptom: seeing a programming problem in terms of
tests first and implementation later
◉ Spend less time debugging and more time designing
◉ Write many tests – test often – learn testing skills
◉ The process is called Test-Driven Development (TDD)
COMP1549: Advanced Programming 15
Test-Driven Development
◉ When you want a write some new code -
write the test first
Will automatically give you the highest level view
of the problem domain you are attempting to
address
◉ Then implement just enough code for your
test to pass
May well mean developing dummy classes that
return set values
COMP1549: Advanced Programming 16
Keep Testing
◉ Checking your tests fail is as important as
checking your tests pass
◉ When you implement new functionality or
change existing code, run all the tests, not
just the one you think is affected
Ensure that nothing you are introducing in your
new code breaks your existing tests
COMP1549: Advanced Programming 17
This seems like a lot of work
◉ Soon it will save you time
◉ You know all of your code works
◉ You add something and immediately know whether your
code still works or where it is going wrong
The compiler tells you about syntax errors. Your test will warn
you of logic error
◉ You fix something – you know you REALLY fixed it
◉ You think you fixed it – but you didn’t. A well written test
will reveal your error straight away
COMP1549: Advanced Programming 18
There’s more
◉ A well written test documents your
components
It shows you how to use your component, not just
with words but with an example
◉ If you run your test – your documentation
stays up to date (unlike real documentation
which is always done last)
COMP1549: Advanced Programming 19
Isolation of Tests
◉ Tests should be isolated
It should be possible to run any test in isolation
One test should not be affected by another – the
outcome of a test should not be dependent on
another test succeeding
This enables tests being run in any order
◉ There is overhead in isolating tests
Each test needs to set all state it needs to
execute – e.g. open connection to database,
instantiate all required objects, etc.
COMP1549: Advanced Programming 20
Initialise and Cleanup
◉ Creating state for each test can result in very
lengthy and repetitive test code
◉ Code can be simplified by extracting common
code to:
Create state necessary for a test – setup
Return to original state after test – teardown
◉ Test methods can concentrate on running the
actual tests
Use the setup and teardown to create state and
return to original state, if necessary. May only be
required if test makes use of external resources, e.g.
DB, server, network connection, etc.
COMP1549: Advanced Programming 21
Mock Object
◉ A Mock Object is an object designed to ape
real behaviour
◉ When you are developing complex
components it can be useful to work to the
fixed point of a particular Mock Object until
you are ready to implement that object
properly
COMP1549: Advanced Programming 22
Mock Object
◉ Replace expensive, unreliable or slow resources
with a mock object
E.g. a Database, network connection, sending
emails, etc.
◉ Enables you to perform the test without relying
on external sources not to fail
Is my code faulty or is it the connection?
◉ Speeds up the testing
◉ However – a mock is not the real object, so it’s
possible your test passes, but the real system
fails
Make it possible to switch between a mock and the
real object
COMP1549: Advanced Programming 23
Test Advice
◉ What should I test?
Every non trivial algorithm
Anything that has ever broken
◉ Tests should be
Quick – If they take too long you won’t run them
so often
Self contained - If there is an error in one test it
shouldn’t propagate to others
KISS (Keep It Short and Simple)
COMP1549: Advanced Programming 24
JUnit and Eclipse
◉ Support for JUnit tests is built-in to Eclipse
◉ The testing tools don’t offer features for
testing UIs (e.g. automatically entering text or
clicking buttons)
So, very important to put all your application
logic in “testable” classes – thin UI layer
◉ Visibility restrictions apply
Every method you want to test has to be visible
to the test code – the test code is placed in the
same package, so you can test default visibility
COMP1549: Advanced Programming 25
Testing Example
◉ Let’s create some unit tests to test the
calculator application we created in a
previous week (Components)
Markus A. Wolf
COMP1549: Advanced Programming 26
Testing Example
◉ We created the application as two separate
modules:
CalculatorModule – containing the logic
CalculatorGUI – containing the user interface
layer
◉ We already have a neat structure where no
logic remains in the UI
◉ The Calculator class contains the methods
to carry out the calculations
Markus A. Wolf
COMP1549: Advanced Programming 27
Calculator Class
package calculatorModule;
import calculatorModule.logger.CalculatorLogger;
public class Calculator {
public float add(float num1, float num2) {
float result = num1 + num2;
CalculatorLogger.LogResult(result,
CalculatorOperation.addition);
return result;
}
public float subtract(float num1, float num2) {
float result = num1 - num2;
CalculatorLogger.LogResult(result,
CalculatorOperation.subtraction);
return result;
}
...
COMP1549: Advanced Programming 28
Creating a Unit Test
◉ Right-click on the CalculatorModule project
Select JUnit Test Case
COMP1549: Advanced Programming 29
Creating Unit Tests
Select the test framework Junit 4
and Jupiter use annotations
The class will be placed
in a separate test
package
Set the name for
the class
containing the
unit tests
Initialisers and
finalisers could be
generated
This is the class we will
generate tests for
COMP1549: Advanced Programming 30
Creating Unit Tests
Select the methods for which
you want to create tests
COMP1549: Advanced Programming 31
JUnit and Modules
◉ As our project uses modules, we need to add
JUnit 5 to the module path
◉ We also need to a dependency for
org.junit.jupiter.api to the module-info file
COMP1549: Advanced Programming 32
Test Class
◉ Eclipse automatically creates a test class and
skeleton code
A static import allows us to call
static methods directly, without
specifying the class name
Placed in a
separate package
Markus A. Wolf
COMP1549: Advanced Programming 33
Attributes
◉ From version 4 onwards of Junit uses
attributes to annotate test elements
@Test – defines a test
@BeforeAll – runs once before any of the test
methods in the class
@BeforeEach – runs once before each test in
the class
@AfterAll – runs once after the last test in the
class
@AfterEach – runs once after each test in the
class
@Ignore – makes it possible to ignore a test
COMP1549: Advanced Programming 34
Assertions
◉ Assertions are used to test whether an actual
post-condition is the same as an expected
post-condition
◉ JUnit contains many static methods for
assertion in the Assertions class
◉ All static methods in the Assertions class will
evaluate either to true (the test has passed) or
false (not passed), with the exception of fail
which will always fail
◉ If more than one assertion exist within one test,
the test will stop as soon as the first assertion
fails
COMP1549: Advanced Programming 35
Assertions
◉ Some of the static methods:
assertEquals – true if both arguments have
same value (makes call to Equals method for
non-primitive data types)
assertSame – true if two references point to the
same object
assertTrue – true if it is passed something that
evaluates to true
assertArrayEquals - true if two arrays contain the
same elements
assertNull – true if what is passed in is null
More…
COMP1549: Advanced Programming 36
Testing Add()
@Test
void testAdd() { This is what we
float a = 2.5f; expect
float b = 8.2f;
Calculator calculator = new Calculator();
float expectedResult = a + b; This is what
float result = calculator.add(a, b); add() returns
assertEquals(expectedResult, result);
}
Do the results We could use a third parameter -
match? delta (the variation in result that
would still pass)
COMP1549: Advanced Programming 37
Running Tests in Eclipse
◉ When you click on the run button, select the
Run As JUnit Test option
How many tests
are failed
The tests that are
run
COMP1549: Advanced Programming 38
Ignoring Tests
Sometimes it may be useful to ignore
tests
E.g. if test functionality is not implemented yet
Use Disabled annotation
@Disabled Test will be
ignored
@Test
public void testMultiply() {
testMultiply is
now omitted
COMP1549: Advanced Programming 39
Testing Exception
◉ What if we want to test exception
handling?
◉ It is possible to write tests that only pass if
an exception of the expected type is
thrown @Test
public void testDivideByZero() {
int a = 12;
Tests for an
int b = 0;
exception
Calculator instance = new Calculator();
assertThrows(ArithmeticException.class,
()-> instance.divideInt(a, b));
}
Test passed
Had to add a method that divides
integers, as a float would be set to
Infinity and not throw an exception40
COMP1549: Advanced Programming
Software Version Control
with Git
COMP1549: Advanced Programming 41
Dealing with Change
◉ How do you manage your coursework?
Modifying existing code (e.g. adapting code from
the lecture)
Backing up working code
Checking if an idea works (Do I use a Hashtable
or a HashMap?)
Sharing code in group projects
COMP1549: Advanced Programming 42
Bad Solutions
◉ Copy and Paste code snippets
◉ Copy entire directories
◉ Emailing code to people
COMP1549: Advanced Programming 43
Open Source
◉ You thought coursework was bad?
◉ Linux kernel has thousands of regular
developers and millions of files
◉ Developers spread over the globe across
multiple time zones
COMP1549: Advanced Programming 44
Big Code Bases
◉ Operating systems code
Linux kernel approx. 12 million lines of code
Windows operating system approx. 50 million
lines of code
◉ NetBeans IDE 8 750k lines of code
◉ Modern PC games
Unreal 3 approx. 500,000 lines of code
◉ Facebook runs on 62 million lines of code
COMP1549: Advanced Programming 45
Making a Mess
◉ The Linux kernel runs on different processors
(ARM, x86, MIPS). These can require
significant differences in low level parts of the
code base
◉ Many different modules
◉ Old versions are required for legacy systems
◉ Because it is open source, anyone can
download and suggest changes
◉ How can we create a single kernel from all of
this?
COMP1549: Advanced Programming 46
Not Just Code
◉ A Code Base does not just mean code!
◉ Also includes:
Documentation
Build Tools (Makefiles, etc.)
Configuration files
COMP1549: Advanced Programming 47
Good Solution
◉ Control the process automatically
◉ Manage these things using a version control
system (VCS)
◉ A version control system is a system which
enables the management of a code base
COMP1549: Advanced Programming 48
Version Control - VCS
◉ Keep track of changes
◉ Support collaborative development
◉ Version control is not just useful for collaborative
working, essential for quality source code
development
◉ Often we want to undo changes to a file
start work, realise it's the wrong approach, want to
get back to starting point
like "undo" in an editor…
keep the whole history of every file and a changelog
also want to be able to see who changed what,
when
COMP1549: Advanced Programming 49
Git /Github
◉ Git
a distributed version control system
tracks files and directories
Note: Git is primarily a command-line tool, but we
will use the GitPlugin for Eclipse
◉ GitHub
a website where you can upload a copy of your Git
repository
a Git repository hosting service, which offers all of
the distributed revision control and source code
management functionality of Git as well as adding its
own features
COMP1549: Advanced Programming 50
Git Repositories – “repos”
◉ Digital directories - where your project is stored
◉ A repository is the basic unit of Git, most
commonly a single project
◉ Repositories can contain folders and files,
including images
anything your project needs
◉ Repositories can be local or remote to the user
COMP1549: Advanced Programming 51
Git – Basic Workflow
1. Get a Git repository
Create a new repository in a local project –
Initialise Repository
or
Clone an existing repository
COMP1549: Advanced Programming 52
Git - Basic Workflow
2. Record any changes to the repository
Commit
Saves the changes you have made to the files in the
local repository since the last time you committed
Commits are local until you push them to the
repository
When you commit, you are “staging” the changes you
make to be later pushed to the remote repository for
other users to see publicly
COMP1549: Advanced Programming 53
Git - Basic Workflow
2. Record any changes to the repository
Push
Saves local commits to the remote repository
COMP1549: Advanced Programming 54
Git - Basic Workflow
2. Record any changes to the repository
Push
Saves local commits to the remote repository
Remote repository check if Local Repo == Remote
Repo – New Changes
If Local and Remote repos are not the same –they
must be synchronised with the Pull command
COMP1549: Advanced Programming 55
Git - Basic Workflow
2. Record any changes to the repository
Pull
Retrieve the most recent versions of the files in the
repository and merge
Branches that you pull will be merged into the current
local branch, so make sure that you only pull from the
remote branch that corresponds to the branch you are
currently working in
COMP1549: Advanced Programming 56
GitLab
◉ At the University we have a GitLab server set
up for you to use
◉ GitLab is a DevOps lifecycle tool
Git repository manager
Wiki
Issue-tracking
CI/CD pipeline (Continuous
Integration/Continuous Delivery)
Software is always in a state that can be deployed
incorporating latest changes
COMP1549: Advanced Programming 57
GitLab
◉ GitLab is available at the University at
https://flas-git.gre.ac.uk/
◉ NOTE: this website is only accessible from a
computer on the University network or
VMWare
◉ All students on COMP1549 have been given
an account:
Username: student username e.g. ‘ab1234c’
Password: your email e.g. ‘
[email protected]’
Can be changed after you log in
COMP1549: Advanced Programming 58
Eclipse and Git
◉ Eclipse comes incorporated with Git support
◉ You can:
Clone a repository from a remote location
(GitLab)
Initialise a repository and push it to a remote
location (GitLab)
Commit changes
Checkout
Show Changes
More…
COMP1549: Advanced Programming 59
Eclipse and Git
◉ Eclipse has a dedicated Git perspective
COMP1549: Advanced Programming 60
Creating a GitLab Project
◉ We will look at how you can:
Create an empty project on GitLab
Clone it in Eclipse
Create a Eclipse project with some code
Add the Eclipse project to the Git repository
Commit changes
Push changes
COMP1549: Advanced Programming 61
Create a Project in GitLab
◉ Log in on GitLab and create a new blank
project
The name of the
project
We will make it
internal, so only
We will initialise
authenticated users
it so we can
can access it
immediately
clone it
COMP1549: Advanced Programming 62
Create a Project in GitLab
Click on Clone to see
the URL
Here we can copy the
URL that we need for
cloning the project
COMP1549: Advanced Programming 63
Clone a Project in Eclipse
◉ Adding repositories in Eclipse is done in the
Git Repositories panel (in the Git perspective)
COMP1549: Advanced Programming 64
Clone a Project in Eclipse
The copied URL
Your credentials from
GitLab
COMP1549: Advanced Programming 65
Clone a Project in Eclipse
Select the master branch
COMP1549: Advanced Programming 66
Clone a Project in Eclipse
The name of the remote
repository
If there was an existing
Eclipse project in the
repository, this would
create the project now
COMP1549: Advanced Programming 67
Clone a Project in Eclipse
◉ If all goes well, we should now see the project
in the Git Repositories panel
COMP1549: Advanced Programming 68
Create an Eclipse Project
◉ Let’s create a normal Eclipse Java project
I created a Java project
called MyGitApp with a
single class
A very simple class
COMP1549: Advanced Programming 69
Add an Eclipse Project
◉ One can add an Eclipse project to an existing
Git repository
Git commands are found
under the Team option Selecting this option will
allow us to add the
project to Git
COMP1549: Advanced Programming 70
Add an Eclipse Project
◉ We can now add the Eclipse project to the
cloned repository We can see that
the project is
now linked to a
Our cloned repository is Git repository
available here
The > symbol shows that
there uncommitted files
or changes
COMP1549: Advanced Programming 71
Adding Files
◉ Files are not automatically included, so you
need to add them to index
COMP1549: Advanced Programming 72
Adding Files
◉ It is also possible to add files to the index
from the Commit panel
Selecting this option will
open the Commit panel
COMP1549: Advanced Programming 73
Adding Files
◉ All new files which haven’t been indexed are
included in the list of Unstaged changes
New files, which are unstaged, so nothing to
commit yet
You can select any new files you want to
submit to Git, right-click and select the “Add
to index” option
COMP1549: Advanced Programming 74
Commit Changes
Add a message which sums
up the changes we are
committing
You can just
All the new files are now commit
staged, so will be committed
Or commit
and push
I committed and pushed,
so here is a confirmation
that changes have been
pushed
COMP1549: Advanced Programming 75
Making Changes
◉ Now let’s edit the MyGitApp.java file
Eclipse has noticed that Amended the print
there are uncommited statement
changes to our project
COMP1549: Advanced Programming 76
Commit Change
◉ Now I have committed to the local repository
and did not commit and push
We can see that there are
committed changes
which haven’t been
pushed
We can see the commit in
the local repository
COMP1549: Advanced Programming 77
Push Changes to Remote
Repository
◉ Now we will push changes from the local to
the remote repository
COMP1549: Advanced Programming 78
Push Changes to Remote
Repository
Our changes have been
pushed to the GitLab project
COMP1549: Advanced Programming 79
Import a Project
◉ It is also possible to import a project from a
Git Repository
You can use this option, if
you have already cloned a
project in the Git perspective
COMP1549: Advanced Programming 80
Import a Project
Select a Git repository
You can import existing
Eclipse projects or create a
new one, if none exists yet
COMP1549: Advanced Programming 81
Other VCS
◉ Git is a very popular VCS, but it’s not the only
CVS
Concurrent Versions System
Free
Released in 1990
Client-server
SVN
Also called Subversion
Open source
Successor to CVS
Maintained by Apache
Many others (including AzureDevOps Server by
Microsoft)
COMP1549: Advanced Programming 82
End of week 6!
COMP1549: Advanced Programming 83