1. UNIT TESTING
JUnit , Mockito and SonarQube
Nayanda Haberty (nayanda.haberty@aprisma.co.id)
2. AGENDA
What we’ll talk about
1 Software Testing in general
2 What is Unit Testing?
3 All about JUnit
4 All about Mockito
5 Using Sonarqube
6 Some demo about unit testing
3. SOFTWARE TESTING DEFINITION
1 Finding error
2
Test with uncommon scenario (such as give null
pointer as input)
3
Test with (if can) every possible scenario4
Check if the program does what it’s not
supposed to do
Do
1 Try demonstrating that errors are not present
2 Try to show that the program performs its
intended functions correctly
3 Establishing confidence that a program does what
is supposed to do
4 Test with some or even one possible scenario
Don’t
Process of executing a program with the intent of finding errors.
4. CODE COVERAGE
FUNCTION COVERAGE
Has each function / method in
the program been called?
STATEMENT COVERAGE
Has each statement in the program
been executed?
BRANCH COVERAGE
Has each branch of each control
structure been executed?
A measurement of how many parts of your code are executed (Usually in percentage)
5. Black-box testing is a method of
software testing that examines the
functionality of an application
without peering into its internal
structures or workings. This method
of test can be applied to virtually
every level of software testing: unit,
integration, system and acceptance.
BLACK BOX TESTING
Black Box
possibleInput1
possibleInput2
possibleInput3
.
.
.
possibleInputN
Pass ?
Fail ?
6. Say we have method “isPrime” to
check whether the number is prime
number or not. The method will
accept an integer data type and
return Boolean data type. This
method will return true if we pass
prime number integer as input, and
false if we pass dividable number
and invalid number as input. To test
the method, we need to input all the
possible input, which is all the
integer number, and check all the
input. Because we doesn’t know how
the method works. It will be an
exhausting test.
BLACK BOX EXAMPLE
boolean isPrime(int number)
-n … 0 1 2 3 … n
false … false false true true … true/false
7. White-Box (also known as clear
box testing, glass box testing,
transparent box testing, and
structural testing) is a method of
testing software that tests
internal structures or workings
of an application, as opposed to
its functionality
WHITE BOX TESTING
Pass ?
Fail ?
Case 3
Case 4
Case 2
Case 1
Input
Output
testCase1
testCase2
testCase3
testCase4
8. With same method (“isPrime”) but
with exposed internal structure, we can
create some testing scope and test the
condition at least once per case (more
is better!) and be sure that every case
are tested. In this scenario, it’s not really
necessary to test the method with
every integer number.
WHITE BOX EXAMPLE
Number >= 2?
Even number?
2?
Dividable by every
odd number which
less or equals than
input’s root?
Pass/Fail?
1
(<2)
2
(even)
7
(odd)
8
(even)
False
True
21
(odd)
9. Unit testing is a software development
process in which the smallest testable
parts of an application, called units, are
individually and independently
scrutinized for proper operation. Unit
testing is often automated but it can
also be done manually.
The goal of unit testing is to isolate
each part of the program and show that
the individual parts are correct.
WHAT IS UNIT TESTING ?
User
Acceptance Test
System
Integration Test
Unit Test
ExecutionTime
Number of Test
10. The units in unit testing is the smallest
parts of class which are methods. We need
to test each method individually and
independently to search every bug and error
(if possible) in every method and fix it before
the class are integrated with the main
program.
Once all the method pass the test, then we
can proceed to Integration Test.
WHAT IS UNIT TESTING ? (OOP)
Class
MyClass
firstMethod
secondMethod
…
nMethod
TEST
EACH
METHOD
PASS ?
Fix the code
Integration
Test
11. Unit Test Class will create object or call
methods from Class A, and running it in
Unit Test methods individually. If Class A
need outside object to run, we’ll need Test
Double Objects to mimic the real object
for Class A. The test double objects can also
be used by Unit Test Class to check any
desired test condition for Class A.
Finally, Unit Test Class will generate result
from testing for us to determine whether
Class A is pass the test or not.
HOW IT WORKS ? (OOP)
Unit Test
Class
Class A
(Under Test)
Fake Objects
Fake Objects
Fake ObjectsTest Double
ObjectsRESULT
12. TEST DOUBLE VARIATION
Name Purpose
Has
Behavior
Injects
input
Inject Output
Has Default
Values
Dummy Attribute or parameter No No No No
Stub Verify indirect input Yes Yes Ignores Inputs
Spy Verify indirect output
Yes
Optional
Capture for
verification
Inputs (Optional)
Mock Verify indirect output
Yes
Optional
Verify
Correctness
Output & Inputs
(Optional)
13. CREATE THE UNIT TEST FIRST?
+ Help developer to really consider what needs to
be done
+
Have “blue print” of system design+
It can be confusing if the unit testing is buggy-
Have immediate feedback while developer work
Create unit test first
+ Unit test will likely have maximum code coverage
- Developer have feedback after unit testing is
finished
- Code will likely doesn’t meet the requirement
Create unit testing after
+ Developer have full creativity to create the code
14. 1 Find the problems early
2 Facilitates changes
3 Simplifies Integration
4 Documentation
THE BENEFITS (AND THE CONS) OF UNIT TESTING
The Pros (+)
1 Time consuming
2 Does not show absence of errors
3 Cannot be run in actual deployment environment
4 Test code is likely to be buggy
The Cons (-)
15. JUNIT
(www.junit.org)
1 Java-based unit testing framework
2 Elegantly simple
3 Easy to write unit tests
4 Easy to manage
5 De facto java standard
6 Generic testing framework
16. JUNIT CONCEPT
Test Runnable
Method
(Runnable)
Test Class
Class A
(Under Test)Pass / Fail
Use
Use
Assert
1 Class A
Class under test
2 Test Class
Class with test methods for
every Class A methods
3 Test Runnable (Runnable)
Runnable method to run Test
Case Class
4 Result
Result from Assert (JUnit API)
to determine is test is pass/fail
17. JUNIT INSTALLATION
1 Using Jar
Download “junit.jar” and “hamcrest-core.jar” at
www.junit.org and put on your class path
2 Using POM (Maven)
Add this dependency in pom.xml on your maven
module / project.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
18. RUNNING JUNIT
1 Using runnable method
We can create runnable method to run the test
class and using assert from test class to check the
result.
2 Right click on test class (Eclipse)
There is eclipse feature which we can right click
on JUnit test class and run it with Junit.
Run with maven (Maven)
We can run JUnit using maven goal “test”, or
even run it automatically every time we use
“package” goal
3
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(TestClass.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
19. SOME OF JUNIT API (JUnit 4.12)
1 org.junit.Assert.*
It will fail the test if not true
- assertTrue(boolean)
Assert that boolean is true
- assertEquals(type, type)
Assert that two variables are equals
- assertArrayEquals(type[], type[])
Assert that two arrays are equals
- assertNotNull(object)
Assert that object reference is not null
2 org.junit.Assume.*
It will ignore the test if not true
- assumeNoException(Throwable)
Assume there is no exception
- assumeTrue(boolean)
Assume boolean is true
- asumeNotNull(object)
Assume object reference is not null
- assumeThat(type, Matcher)
Assume that type is match with Matcher
20. SOME OF JUNIT ANNOTATION (JUnit 4.12)
- @Test
Tells JUnit to run the method with this annotation as a test method.
- @Before
Tells JUnit to run the method with this annotation before running every test method
- @BeforeClasss
Tells JUnit to run the method with this annotation before running everything in the test class
- @After
Tells JUnit to run the method with this annotation after running every test method
- @AfterClass
Tells JUnit to run the method with this annotation after all the test are executed
- @RunWith(Class)
Tells JUnit to run the class with this annotation with “Class” parameter
- @Parameterized.parameter
Tells JUnit to use return value from method with this annotation as parameter for test method
21. In this example, we create a class
named MyMath which have one
static method named isPrime. As we
can see in this slide, this method will
accept integer number as input and
return boolean value as return value.
This method will return true if integer
number is prime and false if not.
JUNIT EXAMPLE (1)
public class MyMath {
private MyMath() {
}
/**
* Method to check is input integer is prime or not
*
* @param number
* is integer input you want to check
* @return true if the input integer is prime, and false if not
*/
public static boolean isPrime(int number) {
if (number >= 2) {
if (number % 2 == 0) {
if (number == 2)
return true;
} else {
int max = (int) Math.sqrt((double) number);
for (int i = 3; i <= max; i += 2) {
if (number % i == 0)
return false;
}
return true;
}
}
return false;
}
}
22. Cause the class’s source code are
exposed, so we can say it’s a white
box test. In order to create unit test
with maximum code coverage, we
can create flow chart of the
programs to identify every possible
test case for the method.
In this case, we need to create test
case with this type of number at least
one : less than 2, bigger than 2 and
even, bigger than 2 and odd,
exactly 2 and prime number as well.
JUNIT EXAMPLE (2)
int number
>= 2 ?
Even?
= 2 ?
Dividable?
false truefalse true
No
No
No
No
Yes
Yes
Yes
Yes
23. To achieve everything we conclude
from previous slide by using “JUnit”,
we can use Parameterized API from
“JUnit” and create every input value
and expected result as parameters. By
using that method, we can create just
one test method for isPrime method
and test it with every parameters.
JUnit will run method with “@Test”
annotation for every object from
List in method with
“@Parameterized.Parameter”
annotation.
JUNIT EXAMPLE (3)
@RunWith(Parameterized.class)
public class MyMathTest {
private int number;
private boolean prime;
public MyMathTest(Integer number, Boolean prime) {
this.number = number.intValue();
this.prime = prime.booleanValue();
}
@Parameterized.Parameters
public static List<Object[]> testParam() {
return Arrays.asList(new Object[][] {
{ -65536, false }, { -21, false },{ -2, false }, { -1, false }, { 0, false },
{ 1, false }, { 2, true }, { 3, true },{ 4, false }, { 17, true },
{ 21, false },{ 40, false }, { 289, false }, { 65536, false },
{ 65538, false }
});
}
@Test
public void testPrime() {
assertEquals("The input number is " + number +
" and isPrime method should return " + prime + "but it return “ +
MyMath.isPrime(number), prime, MyMath.isPrime(number));
}
}
25. MOCKITO CONCEPT
Test Class Class A
(Under Test)
RESULT
Use
1 Class A
Class under test
2 Mock Object
Object use to mimic real object
and to verify test correctness
3 Test Class
Class to create and initialize
scenario, and verify the result
4 Result
Result from mock objects to
check how the object are treated
Fake Objects
Fake Objects
Fake ObjectsMock
Objects
Use
26. MOCKITO INSTALLATION
1 Using Jar
Download “mockito-core.jar” at
www.mockito.org and put on your class path
2 Using POM (Maven)
Add this dependency in pom.xml on your maven
module / project.
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
</dependency>
27. SOME OF MOCKITO API (Mockito 1.10.19)
- mock(Class)
will return object reference of mock to mimic Class
- when(object.methodCall).thenReturn(variable)
if methodCall is called, then it will return variable
- verify(object). methodCall
will verify if methodCall is called
- verify(object, times(int)). methodCall
will verify if methodCall is called with given times
- verify(object, never()). methodCall
will verify if methodCall is never called
- verify(object, atLeastOnce()). methodCall
will verify if methodCall is called at least once
- verify(object, atLeast()). methodCall
will verify if methodCall is called at least in given times
- verify(object, atMost(int)). methodCall
will verify if methodCall is called at most in given times
- inOrder.verify(object). methodCall
will verify if methodCall is called in order we order this scripts
Explanation:
Class : Name of class
Example : MyClass.class
methodCall : Method and it’s parameters
Example : myMethod(9)
object : Name of object
Example : myObject
variable : variable or value
Example : 1
28. USING MOCKITO WITH JUNIT
1 Install JUnit and Mockito
Using Jar or Maven
2 Create Test Class
Create test class with JUnit
3 Add “MockitoJUnitRunner.class”
Add as @RunWith parameter
4 Test
Happy testing!
29. In this example, we have class named
“ClassReport”. The class have method
“getAvgGrade” which will calculate
the average grade from every grade in
List<Student>. But the “Student”
class is save the grade in alphabet
representation like “A”, “B+” or “C”,
which is uncalculated. In order to
extract number representation of
those String, we need to use service
object which in this case is
“gradeService”
But in order to create good unit test,
we need to isolate the object from
other “unreliable class” so we can test
the unit individually.
MOCKITO EXAMPLE (1)
public class ClassReport {
private GradeService gradeService;
private List<Student> students;
public void setGradeService(GradeService gradeService) {
if (gradeService != null)
this.gradeService = gradeService;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
if (students != null)
this.students = students;
}
public double getAvgGrade() {
double avgGrade = 0.0;
int size = students.size();
if(size > 0){
for (Student student : students) {
avgGrade += gradeService.getGradeNum(student);
}
avgGrade /= size;
}
return avgGrade;
}
}
30. We are using JUnit with Mockito here so the
test will run by JUnit. In this test class, we add
“@RunWith()” annotation with
“MockitoJUnitRunner.class” as parameter, it will
tell JUnit to run this test unit with
MockitoJUnitRunner class.
We have setup method that will create mock
object from GradeService class named
“gradeService”. We also can create 2 dummy
Student which we assume have “A” and “B” as
their grade. And we make assumption that A is
equals 4.0, and B is equals 3.0.
Later we create gradeService mock method
behavior that will return 4.0 for studentA and
3.0 for studentB. Finally we can do assertion
with JUnit to test getAvgGrade() method.
MOCKITO EXAMPLE (2)
@RunWith(MockitoJUnitRunner.class)
public class ClassReportTest {
private ClassReport report;
private GradeService gradeService;
private Student studentA;
private Student studentB;
private List<Student> students;
@Before
public void setUp() {
report = new ClassReport();
studentA = mock(Student.class);
studentB = mock(Student.class);
students = new ArrayList<Student>();
students.add(studentA);
students.add(studentB)
gradeService = mock(GradeService.class);
when(gradeService.getGradeNum(studentA)).thenReturn(4.0);
when(gradeService.getGradeNum(studentB)).thenReturn(3.0);
report.setGradeService(gradeService);
}
@Test
public void testAvgGrade() {
report.setStudents(students);
assumeTrue(report.getStudents().equals(students));
double avg = report.getAvgGrade();
double expectedAvg = (4.0 + 3.0) / 2;
assertTrue("average grade should be " + expectedAvg + ", but it return " + avg, avg = expectedAvg);
verify(gradeService, times(1)).getGradeNum(studentA);
verify(gradeService, times(1)).getGradeNum(studentB);
}
}
31. SONARQUBE
(www.mockito.org)
1 Open source quality management platform
2 Web-based application
3 More than 20 programming languages are
covered
4 Code reviewer
5 Can combine metrics altogether
6 Can be configured online
32. SONARQUBE INSTALLATION
1 Download
Download at www.sonarqube.org
2 Extract
Extract into desired directory
3 Run
Go to “sonarDirectory/bin/”
Go to “your_OS_name” directory
Run StartSonar.bat
33. After running
StartSonar.bat, you can
access SonarQube
homepage by using it’s
default page at
http://localhost:9000 .
You’ll see similar page like
this picture.
SONARQUBE HOMEPAGE
34. RUNNING ANALYSIS WITH MAVEN
1 Add plugins at pom.xml
Add text beside to your pom.xml
2 Add/edit “settings.xml”
Add text beside to your “settings.xml”
at your “.m2” directory
3 Run using maven goal
clean verify sonar:sonar
clean install
sonar:sonar
org.sonarsource.scanner.maven:sonar
-maven-plugin:3.0.2:sonar
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.language>java</sonar.language>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<settings>
<pluginGroups>
<pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
</pluginGroups>
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
</properties>
</profile>
</profiles>
</settings>
pom.xmlsettings.xml