Unit Testing and JUnit
Unit Testing and JUnit
Compiled by Esmael .M
1
What is Software Testing
•Software testing is a process of identifying the correctness of software by considering its all
attributes (Reliability, Scalability, Portability, Re-usability, Usability) and evaluating the execution of
software components to find the software bugs or errors or defects.
• Testing is a group of techniques to determine the correctness of the application under the
predefined script but, testing cannot find all the defect of application.
• Testing includes an examination of code and also the execution of code in various environments,
conditions as well as all the examining aspects of the code.
2
Cont..
3
What is Manual Testing?
•Testing any software or an application according to the client's needs without using any automation tool is
the developer will inspect every line of code before handing it over to the testing team or the concerned test
engineers.
the test engineer will analyze the software against requirements, identify the defects or bug, and sends it back to
the development team
o Integration Testing
o System Testing
5
Unit Testing
• the test engineer will test the module of an application independently or test all the module functionality
• executing the unit testing is to confirm the unit components with their performance
6
Integration Testing
• test the data flow between dependent modules or interface between two features
7
System Testing
• test environment is parallel to the production environment. It is also known as end-to-end testing
• undergo each attribute of the software and test if the end feature works according to the business
requirement.
• analyze the software product as a complete system
8
Non-function Testing
2. Non-function Testing
Non-functional testing will help us minimize the risk of production and related costs of the software
o Performance Testing
o Usability Testing
o Compatibility Testing
9
Contt…
o Performance Testing
o Load Testing
o Stress Testing
o Scalability Testing
o Stability Testing
o Load Testing
10
Non-function Testing
o Usability Testing
analyze the user-friendliness of an application and detect the bugs in the software's end-user interface
o Compatibility Testing
we will check the functionality of an application in specific hardware and software environments
11
Automation Testing
o It uses specific tools to automate manual design test cases without any human interference.
12
contt..
Manual testing Automation testing
Testing in which a human tester In automation testing, automation tools are used to
executes test cases execute the test cases
human resources are involved It is much faster than the manual testing
It is repetitive and error-prone Here automated tools are used that make it interesting
and accurate
BVT (build verification testing) is time- It's easy to build verification testing
consuming and tough in manual testing
13
contt..
Instead of frameworks, this testing Frameworks like keyword, hybrid, and data drive to
use checklist, guidelines, and accelerate the automation process.
stringent process for drafting test
cases.
The process turnaround time is It completes a single round of testing within record time;
higher than the automation testing therefore, a process turnaround time is much lower than a
process (one testing cycle takes lots manual testing process.
of time)
The main goal of manual testing is Automation testing can only guarantee a positive customer
user-friendliness or improved experience and user-friendliness.
customer experience.
It is best for usability, exploratory It is widely used for performing testing, load testing and
and adhoc testing regression testing.
14
Automation testing process
The tool must lie in your budget, support the technologies used in the application, skilled resources are necessary,
and tools have a good reporting mechanism.
15
Automation testing process
Step 9: Reporting
16
Automation testing tools
•Selenium
•Katalon
17
Advantages of automation testing
18
Unit Testing and JUnit
19
Outline
21
Unit Testing
• Unit testing: Looking for errors in a subsystem in isolation.
• Generally a "subsystem" means a particular class or object.
• The Java library JUnit helps us to easily perform unit testing.
• The basic idea:
• For a given class Foo, create another class FooTest to test it,
containing various "test case" methods to run.
• Each method looks for particular results and passes / fails.
• JUnit provides "assert" commands to help us write tests.
• The idea: Put assertion calls in your test methods to check things you
expect to be true. If they aren't, the test will fail.
22
Why JUnit
• Allows you to write code faster while increasing quality
• Elegantly simple
• Check their own results and provide immediate feedback
• Tests are inexpensive
• Increase the stability of software
• Developer tests
• Written in Java
• Free
• Gives proper understanding of unit testing
23
JUnit
24
JUnit
• JUnit is a framework for writing unit tests
• A unit test is a test of a single class
• A test case is a single test of a single method
• A test suite is a collection of test cases
• Unit testing is particularly important when software
requirements change frequently
• Code often has to be refactored to incorporate the changes
• Unit testing helps ensure that the refactored code continues to work
25
A JUnit test class
import static
org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class name {
...
@Test
void name() { // a test case method
...
}
}
26
The structure of a test method
• A test method doesn’t return a result
• If the tests run correctly, a test method does nothing
• If a test fails, it throws an AssertionFailedError
• The JUnit framework catches the error and deals with it; you
don’t have to do anything
27
Test suites
• In practice, you want to run a group of related tests (e.g. all the tests
for a class)
• To do so, group your test methods in a class with annotations
@SelectPackages or @SelectClasses
28
Organize The Tests
• Create test cases in the same package as the code under test
• For each Java package in your application, define a TestSuite class that
contains all the tests for validating the code in the package
• Define similar TestSuite classes that create higher-level and lower-level test
suites in the other packages (and sub-packages) of the application
• Make sure your build process include the compilation of all tests
29
JUnit Best Practices
• Separate production and test code
• Compile into separate trees, allowing deployment without tests
• Don’t forget OO techniques, base classing
• Test-driven development
1. Write failing test first
2. Write enough code to pass
3. Refactor
4. Run tests again
5. Repeat until software meets goal
6. Write new code only when test is failing
30
Problems with unit testing
• JUnit is designed to call methods and compare the results they return
against expected results
• This ignores:
• Programs that do work in response to GUI commands
• Methods that are used primarily to produce output
31
An Introduction to JUnit
Part 1: The Basics
32
JUnit – Java Unit Testing Tool
33
JUnit 5
• Requires Java 8 (or higher) at runtime
• Can still test code that has been compiled with previous
versions of the JDK
• Supported by popular IDEs
• IntelliJ IDEA
• Eclipse
• NetBeans
• Visual Studio Code
• Supported by build tools
• Gradle
• Maven
• Ant
34
Running JUnit
• JUnit has been integrated into most IDE’s
• We will use the latest Eclipse/NetBeans IDE
• Download and install Eclipse/NetBeans IDE for Java Developers
• JUnit can also be run independently
• Command-line, builder server
• Using a simple build tool Ant
35
Test Case Verdicts
A verdict is the result of executing a single
test case.
Pass Fail
• The test case • The test case execution
execution was was completed
completed • The function being
• The function being tested did not perform
tested performed as as expected
expected
Error
The test case execution was not completed,
due to
an unexpected event, exceptions, or
improper set up of the test case, etc.
36
JUnit Tests
• A JUnit test is represented as a class (test class).
• Each test case is a method in a test class.
• A typical test case does the following
• create some objects/data to test
• do something interesting with the objects
• determine pass or fail based on the results
• A test suite may consist of multiple test classes.
37
JUnit Assertions
• Assertions are Boolean expressions
• An AssertionFailedError is thrown if the assertion is false
• Can check for many conditions, such as
• equality of objects and values
• identity of references to objects
• Determine the test case verdict
• Pass: all assertions are true
• Fail: one or more assertions are false
38
A Simple JUnit Test Case
/** Test of setName() method, of class Value */
@Test
public void createAndSetName() {
Value v1 = new Value();
v1.setName("Y");
Assert.assertEquals(expected, actual);
}
39
A Simple JUnit Test Case
/** Test of setName() method, of class Value */
@Test
public void createAndSetName() { Identify this Java method
Value v1 = new Value(); as a test case
v1.setName("Y");
Assert.assertEquals(expected, actual);
}
40
A Simple JUnit Test Case
/** Test of setName() method, of class Value */
@Test
public void createAndSetName() {
Value v1 = new Value(); Confirm that setName
v1.setName("Y"); saves the specified
name in the Value
String expected = "Y"; object
String actual = v1.getName();
Assert.assertEquals(expected, actual);
}
41
A Simple JUnit Test Case
/** Test of setName() method, of class Value */
@Test
public void createAndSetName() { Check to see that the
Value v1 = new Value(); Value object really
v1.setName("Y");
did store the name
Assert.assertEquals(expected, actual);
}
42
A Simple JUnit Test Case
/** Test of setName() method, of class Value */
@Test
public void createAndSetName() {
Value v1 = new Value(); Assert that the
v1.setName("Y"); expected and actual
should be equal. If
String expected = "Y"; not, the test case
String actual = v1.getName();
should fail.
Assert.assertEquals(expected, actual);
}
43
Using JUnit in Eclipse/NetBeans
• Download and install JDK
Download and install Eclipse/NetBeans IDE for Java Developers
44
Run JUnit in Eclipse: An Example
[see JUnit1.rar]
45
The Example Program: The Class Under Test
46
The JUnit Test
47
The JUnit Test (cont’d)
@Test
public void testSearch2() {
int[] a = { 1, 3, 5, 7 };
assertTrue(search(a, 2) == -1);
}
@Test
public void testCheckedSearch1() { … }
@Test
public void testCheckedSearch2() { … }
@Test
public void testCheckedSearch3() { … }
}
48
Run JUnit in Eclipse: An Example
49
Run JUnit in Eclipse: An Example
• Click “Next”
• Java Settings
• Click “Libraries”
• Click “Add Library …”
50
Run JUnit in Eclipse: An Example
• Add Library
• Choose “JUnit”
• JUnit Library
• Choose “JUnit 5”
• Click “Finish”
51
Run JUnit in Eclipse: An Example
• Run as
• JUnit test
52
Run JUnit in Eclipse: An Example
53
Assertion Methods
54
Assertions in Test Cases
During execution of a test case:
• If an assertion is true,
• Execution continues
• If any assertion is false,
• Execution of the test case stops
• The test case fails
• If an unexpected exception is encountered,
• The verdict of the test case is an error.
• If all assertions were true,
• The test case passes.
55
Assertion Methods: Boolean Conditions
57
Assertion Methods: Object Identity
• Assert two object references are identical
assertSame(expected, actual)
• True if: expected == actual
assertNotSame(expected, actual)
• True if: expected != actual
• The order does not affect the comparison,
• But, affects the message when it fails
• With a failure message
assertSame(message, expected, actual)
assertNotSame(message, expected, actual)
58
Assertion Methods: Object Identity
• Examples
assertNotSame("Should not be same.",
new Object(), new Object());
Integer num1 = Integer.valueOf(2013);
assertSame("Should be same.", num1, num1);
Integer num2 = Integer.valueOf(2014);
assertSame("Should be same.", num1, num2);
java.lang.AssertionError:
Should be same. expected same:<2013> was not:<2014>
59
Assertion Methods: Object Equality
• Assert two objects are equal:
assertEquals(expected, actual)
• True if: expected.equals( actual )
• Relies on the equals() method
• Up to the class under test to define a suitable equals()
method.
• With a failure message
assertEquals(message, expected, actual)
60
Assertion Methods: Object Equality
• Examples
assertEquals("Should be equal.", "JUnit", "JUnit");
org.junit.ComparisonFailure:
Should be equal. expected:<J[Unit]> but was:<J[ava]>
61
Assertion Methods: Equality of Arrays
62
Assertion Methods: Equality of Arrays
• Examples
int[] a1 = { 2, 3, 5, 7 };
int[] a2 = { 2, 3, 5, 7 };
assertArrayEquals("Should be equal", a1, a2);
63
Exception Testing
• A.k.a., robustness testing
• The expected outcome of a test is an exception.
public static int checkedSearch(int[] a, int x) {
if (a == null || a.length == 0)
throw
new IllegalArgumentException("Null or empty array.");
…
}
checkedSearch(null, 1);
64
Exception Testing: Specify the Excepted
Exception
• Specify an expected exception in a test
case
• A particular class of exception is expected to
@Testoccur
void exceptionTesting() {
Exception exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
}
• The verdict
• Pass: if the expected exception is thrown
• Fail: if no exception, or an unexpected 65
Exception Testing: The fail() Assertion
• Assertion methods
• fail()
• fail(message)
• Unconditional failure
• i.e., it always fails if it is executed
• Used in where it should not be reached
• e.g., after a statement, in which an exception should have been
thrown.
66
Exception Testing: Use fail() Assertion
• Catch exceptions, and use fail() if not thrown
@Test
public void testCheckedSearch3() {
try {
checkedSearch(null, 1);
fail("Exception should have occurred");
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Null or empty array.");
}
}
• Allows
• inspecting specific messages/details of the exception
• distinguishing different types of exceptions
67
Summary: Key Concepts
• Unit testing refers to the practice of testing certain functions
and areas – or units – of our code. This gives us the ability to
verify that our functions work as expected.
• Testing needs to be thorough
• Eclipse/NetBeans provides a platform for doing unit tests using
JUnit as a built-in feature.
68
JUnit Best Practices
69
JUnit Best Practices
• Each test case should be independent.
• Test cases should be independent of execution order.
• No dependencies on the state of previous tests.
70
JUnit Test Fixtures
• The context in which a test case is executed.
• Typically include:
• Common objects or resources that are available for use by
any test case.
• Activities to manage these objects
• Set-up: object and resource allocation
• Tear-down: object and resource de-allocation
71
Set-Up
• Tasks that must be done prior to each test case
• Examples:
• Create some objects to work with
• Open a network connection
• Open a file to read/write
72
Tear-Down
• Tasks to clean up after execution of each test case.
• Ensures
• Resources are released
• the system is in a known state for the next test case
73
Method Annotations for Set-Up and Tear-Down
74
Example: Using a File as a Test Fixture
@AfterEach
public void deleteOutputFile() { @Test
output.close(); public void test2WithFile() {
output.delete();
} // code for test case
…
}
}
75
Method Execution Order
1. createOutputFile()
2. test1WithFile()
3. deleteOutputFile()
4. createOutputFile()
5. test2WithFile()
6. deleteOutputFile()
Not guaranteed:
test1WithFile runs before test2WithFile
76
Once-Only Set-Up
• @BeforeAll annotation
• one method only
• Run the method once only for the entire test class
• before any of the tests, and
• before any @BeforeEach method(s)
• Useful for starting servers, opening connections, etc.
• No need to reset/restart for each test case
• Shared, non-destructive
@BeforeAll
public static void anyName() {
// class setup code here
}
77
Once-Only Tear-Down
• @AfterAll annotation
• one method only
• Run the method once only for the entire test class
• after any of the tests
• after any @AfterEach method(s)
• Useful for stopping servers, closing connections, etc.
@AfterAll
public static void anyName() {
// class clean up code here
}
78
Timed Tests
• Useful for simple performance test
• Network communication
• Complex computation
• The @Timeout annotation
• Time unit defaults to seconds but is configurable
@Test
@Timeout(5)
public void testLengthyOperation() {
...
}
Annotation Description
The annotation @Test identifies that a
@Test public void method()
method is a test method.
Will execute the method before each test.
@BeforeEach public void method() Can prepare the test environment (e.g.
read input data, initialize the class).
Will execute the method after each test.
@AfterEach public void method() Can cleanup the test environment (e.g.
delete temporary data, restore defaults).
80
JUnit 5 Unit Testing Framework
Annotation Description
Will execute the method once, before the
start of all tests. Can be used to perform
@BeforeAll public void method()
time intensive activities, for example to
connect to a database.
Will execute the method once, after all
tests have finished. Can be used to perform
@AfterAll public void method()
clean-up activities, for example to
disconnect from a database.
Fails if the method takes longer than 5
@Timeout(5)
seconds.
@Timeout(value = 100, unit = Fails if the method takes longer than 100
TimeUnit.MILLISECONDS) milliseconds
81
Parameterized Tests
• Repeat a test case multiple times with different data
• Define a parameterized test
• Declared just like regular @Test methods but use the
@ParameterizedTest annotation instead
• Must declare at least one source that will provide the arguments
for each invocation
• Consume the arguments in the test method
82
Parameterized Test Example
@ParameterizedTest
@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
void palindromes(String candidate) {
assertTrue(StringUtils.isPalindrome(candidate));
}
83