You are on page 1of 83

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. ‘ab1234c@gre.ac.uk’
 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

You might also like