1.JUNIT Introduction
Testing is the process of checking the functionality of an application to ensure it runs as per requirements. Unit testing comes into picture at the developers’ level; it is the testing of single entity (class or method). Unit testing can be done in two ways –manual testing & automated testing
1. Manual Testing: If you execute the test cases manually without any tool support, it is known as manual testing. It is time consuming and less reliable.
2. Automated Testing: If you execute the test cases by tool support, it is known as automated testing. It is fast and more reliable.
XUnit architecture introduced automated unit testing. There are many unit testing frame works for different programming. Few of the unit testing frame works are:
-
JAVA - JUnit,
-
C - CUnit,
-
C++ - CPPUnit,
-
.NET - .NUnit etc..
XUnit architecture was first implemented for java.It is known as JUnit
JUnit
It is an open-source testing framework for java programmers. The java programmer can create test cases and test his/her own code.It is one of the unit testing framework. Current version is junit 5.you can download it from JUnit website (github) or use below maven dependency in your pom.xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
The Junit 4.x framework is annotation based. Here’re some basic JUnit annotations
-
@Test -Given method is the test method.= public void
-
@Test(timeout=1000) -method will be failed if it takes more then 1000 milliseconds (1 sec).
-
@BeforeClass - method will be invoked only once, before starting all the tests. public static void
-
@AfterClass -method will be invoked only once, after finishing all the tests public static void
-
@Before -method will be invoked before each test. Run before @Test, public void
-
@After - method will be invoked after each test. Run after @Test, public void
The most important package in JUnit is junit.framework, which contains all the core classes. Some of the most important classes are given below
1.Assert - set of assert methods.
2.TestCase - It is the testing of single entity (class or method)
3.TestSuite - A test suite bundles a few unit test cases and runs them
together.
4.TestResult - Contains methods to collect the results of executing a
test case.
By default Maven uses the following naming conventions when looking for tests to run:
-
Test*
-
*Test
-
*TestCase
1.Assert
The org.junit.Assert
class provides methods to assert the program logic. Assert
methods are usually used to compare the actual value with the expected
value. All assert methods are static methods. Return type of all assert
methods are void
-
void assertEquals(boolean expected,boolean actual): checks that two primitives/objects are equal. It is overloaded.
-
void assertTrue(boolean condition): checks that a condition is true.
-
void assertFalse(boolean condition): checks that a condition is false.
-
void assertNull(Object obj): checks that object is null.
-
void assertNotNull(Object obj): checks that object is not null.
2.Test Case
It is the testing of single entity (class or method)
public class TestJunit1 {
String message = "Robert";
MessageUtil messageUtil = new MessageUtil(message);
@Test
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
assertEquals(message, messageUtil.printMessage());
}
}
3.Test Suites
A test suite bundles a few unit test cases and runs them together.
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
//JUnit Suite Test
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestJunit1.class ,TestJunit2.class
})
public class JunitTestSuite {
}
4.Test Runners
Test runner is used for executing the test cases.
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(TestJunit.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
TestResult(Result) − Contains methods to collect the results of executing a test case.
Example 1 : Testing Annotations Working
package basic;
import org.junit.*;
public class AnnotationsTest {
// Run once, e.g. Database connection, connection pool
@BeforeClass
public static void runOnceBeforeClass() {
System.out.println("@BeforeClass - runOnceBeforeClass");
}
// Run once, e.g close connection, cleanup
@AfterClass
public static void runOnceAfterClass() {
System.out.println("@AfterClass - runOnceAfterClass");
}
// Should rename to @BeforeTestMethod
// e.g. Creating an similar object and share for all @Test
@Before
public void runBeforeTestMethod() {
System.out.println("@Before - runBeforeTestMethod");
}
// Should rename to @AfterTestMethod
@After
public void runAfterTestMethod() {
System.out.println("@After - runAfterTestMethod");
}
@Test
public void TestMethod1() {
System.out.println("@Test - TestMethod1");
}
@Test
public void TestMethod2() {
System.out.println("@Test - TestMethod2");
}
}
=================== output =================
@BeforeClass – runOnceBeforeClass
@Before - runBeforeTestMethod
@Test - TestMethod1
@After – runAfterTestMethod
@Before - runBeforeTestMethod
@Test - TestMethod2
@After – runAfterTestMethod
@AfterClass - runOnceAfterClass
Note: All sources of production code commonly reside in the src/main/java directory, while all test source files are kept at src/test/java
2.JUnit Hello World!
To write testcases we must figute out below points
-
Class to be tested
-
Write Testcases for selected class
-
Run the Test (Commandline / TestRunner class)
//1. Class to be tested
package junit;
public class Calculator {
public int square(int x){
return x*x;
}
}
//2. Write Testcases for selected class
package junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class CalculatorTest {
@Test
public void squareTest() {
Calculator calculator = new Calculator();
int sqr = calculator.square(2);
//Checking for 2
assertEquals("2*2=4 Passed",4, sqr);//pass
assertEquals("2*2=4 Passed",6, sqr); //Fail
}
}
//3. Run the Test (Commandline / TestRunner class)
Using command line
java -cp .;junit-4.XX.jar;hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
//Using TestRunner class
package junit;
import org.junit.runner.*;
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(CalculatorTest.class);
for (Failure failure : result.getFailures()) {
System.out.println("Failure : " + failure.toString());
}
System.out.println("Success : " + result.wasSuccessful());
}
}
Failure : squareTest(junit.CalculatorTest): 2*2=4 Passed expected:<6> but was:<4>
Success : false //for assertEquals("2*2=4 Passed",6, sqr); //Fail
Success : true //for assertEquals("2*2=4 Passed",4, sqr);//pass
4.JUnit Examples
4.1 Assert all Methods Example
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.hamcrest.core.CombinableMatcher;
import org.junit.Test;
public class AssertTests {
@Test
public void testAssertArrayEquals() {
byte[] expected = "trial".getBytes();
byte[] actual = "trial".getBytes();
assertArrayEquals("failure - byte arrays not same", expected, actual);
}
@Test public void testAssertEquals() {
assertEquals("failure - strings are not equal", "text", "text");
}
@Test public void testAssertFalse() {
assertFalse("failure - should be false", false);
}
@Test public void testAssertNotNull() {
assertNotNull("should not be null", new Object());
}
@Test public void testAssertNotSame() {
assertNotSame("should not be same Object", new Object(), new Object());
}
@Test public void testAssertNull() {
assertNull("should be null", null);
}
@Test public void testAssertSame() {
Integer aNumber = Integer.valueOf(768);
assertSame("should be same", aNumber, aNumber);
}
// JUnit Matchers assertThat
@Test public void testAssertThatBothContainsString() {
assertThat("albumen", both(containsString("a")).and(containsString("b")));
}
@Test public void testAssertThatHasItems() {
assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
}
@Test public void testAssertThatEveryItemContainsString() {
assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
}
// Core Hamcrest Matchers with assertThat
@Test public void testAssertThatHamcrestCoreMatchers() {
assertThat("good", allOf(equalTo("good"), startsWith("good")));
assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4))));
assertThat(new Object(), not(sameInstance(new Object())));
}
@Test public void testAssertTrue() {
assertTrue("failure - should be true", true);
}
}
4.2 Test Suite
Test suite is used to bundle a few unit test cases and run them together. @RunWith and @Suite annotations are used to run the suite tests.
In below Example we are running Test1 & Test2 together using Test Suite.
//1. Class to be tested
package testsuite;
public class Calculator {
public int square(int x) {
return x * x;
}
public int sum(int x, int y) {
return x + y;
}
}
//2. Write Testcases for selected class
//1.Test1.java
package testsuite;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class Test1 {
@Test
public void squareTest() {
Calculator calculator = new Calculator();
int sqr = calculator.square(2);
assertEquals("2*2=4 Passed",4, sqr);
}
}
-------------------------------------------------------------------
//2.Test2.java
package testsuite;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class Test2 {
@Test
public void addTest() {
Calculator calculator = new Calculator();
int sum = calculator.sum(8,2);
assertEquals("8+2=10 Passed",10, sum);
}
}
//3.Create Test Suite Class
package testsuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
Test1.class,
Test2.class
})
public class CalculatorTestSuite {
}
//4. Run the Test (Commandline / TestRunner class)
Remember, TestRunner class is same for all Examples
package testsuite;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(CalculatorTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println("Failure : " + failure.toString());
}
System.out.println("Success : " + result.wasSuccessful());
}
}
4.3 Ignore Test
@Ignore annotation is used to create Ignore test. We use @ignore in two cases
1. At Method Level : if a method annotated with @Ignore, that method will not be executed.
2. At Class Level Level : if a class annotated with @Ignore, all its methods will not be executed.
//1. Class to be tested
package ignoretest;
public class IgnoreTestClassLevel {
private String str1;
private String str2;
private String str3;
public IgnoreTestClassLevel(String str1, String str2) {
this.str1 = str1;
this.str2 = str2;
}
public String addStrings() {
str3 = str1 + str2;
System.out.println("addStrings : " + str3);
return str1 + str2;
}
public String upperCase() {
str3 = (str1 + str2).toUpperCase();
System.out.println("upperCase : " + str3);
return str1 + str2;
}
}
//2. Ignore Test at Method Level
package ignoretest;
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;
public class IgnoreTestMethodLevel {
StringUtil util = new StringUtil("a", "b");
String res = "";
@Ignore
@Test
public void testAddStrings() {
System.out.println("Inside testAddStrings()");
res = "ab";
assertEquals(res, util.addStrings());
}
@Test
public void testUpperCase() {
System.out.println("Inside testUpperCase()");
res = "AB";
assertEquals(res, util.upperCase());
}
}
Inside testUpperCase()
upperCase : AB
Success : true
//3. Ignore Test at Class Level
package ignoretest;
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;
@Ignore
public class IgnoreTestClassLevel {
StringUtil util = new StringUtil("a", "b");
String res = "";
@Test
public void testAddStrings() {
System.out.println("Inside testAddStrings()");
res = "ab";
assertEquals(res, util.addStrings());
}
@Test
public void testUpperCase() {
System.out.println("Inside testUpperCase()");
res = "AB";
assertEquals(res, util.upperCase());
}
}
Empty Output, because none of its test methods will be executed.
Empty Output, because none of its test methods will be executed.
4.4 Time Test
@Test(timeout)- timeout parameter along with @Test annotation as used for Time Test.If a test case takes more time than the specified number of milliseconds, then JUnit will automatically mark it as failed.
Example: Time Test example for above StringUtil.java Class
Example: Time Test example for above StringUtil.java Class
package ignoretest;
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;
public class StringUtilTimeTest {
StringUtil util = new StringUtil("a", "b");
String res = "";
@Test(timeout = 1000)
public void testAddStrings() {
System.out.println("Inside testAddStrings()");
res = "ab";
assertEquals(res, util.addStrings());
}
@Test
public void testUpperCase() {
System.out.println("Inside testUpperCase()");
res = "AB";
assertEquals(res, util.upperCase());
}
}
4.5 Exceptions Test
@Test(expected)- expected parameter along with @Test annotation as used for Exceptions Test. we can test whether our code throws an expected exception or not
Example: ExceptionsTest
Example: ExceptionsTest
package junit;
public class Calculator {
public int square(int x) {
return x * x;
}
public int div(int a, int b) {
return a / b;
}
}
package junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class CaluculatorExceptionTest {
@Test(expected = ArithmeticException.class)
public void divTest() {
Calculator calculator = new Calculator();
int res = calculator.div(12,0); //success
// int res = calculator.div(12,0); //error
assertEquals(4, res);
}
}
4.6 Parameterized Test
Parameterized tests allow a developer to run the same test over and over again using different values.we use @RunWith(Parameterized.class) to achive this type of tests.
Example
public class EvenNumbers {
public Boolean checkEven(final Integer num) {
for (int i = 1; i <= num; i++) {
if (i % 2 == 0) {
return true;
}
}
return false;
}
}
There are five steps to create Parameterized tests−
-
First, test class is annotated with @RunWith which is a Parameterized.class.
-
Then create a public static method which is annotated with @Parameters. it returns a Collection of Objects as test data set.
-
Next, create a public constructor, which takes in one row of test data.
-
Create an instance variable that is for each column of the test data row.
-
Create tests case(s) using the instance variables as a source of the test data.
-
The test case invokes once per each row of data.
package parameterizedtest;
import java.util.*;
import org.junit.*;
import static org.junit.Assert.assertEquals;
@RunWith(Parameterized.class)
public class PrimeNumberCheckerTest {
private Integer inum;
private Boolean res;
private EvenNumbers evenObj;
@Before
public void initialize() {
evenObj = new EvenNumbers();
}
public PrimeNumberCheckerTest(Integer inum, Boolean res) {
this.inum = inum;
this.res = res;
}
@Parameterized.Parameters
public static Collection evenNumbers() {
return Arrays.asList(new Object[][] {
{ 2, true },
{ 6, true },
{ 18, true },
{ 19, false },
{ 48, true }
});
}
@Test
public void testPrimeNumberChecker() {
System.out.println("Parameterized Number is : " + inum);
assertEquals(res, evenObj.checkEven(inum));
}
}
Parameterized Number is : 2
Parameterized Number is : 6
Parameterized Number is : 18
Parameterized Number is : 19
Parameterized Number is : 48
4.7 JUnit List Example
package other;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hamcrest.collection.IsEmptyCollection;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;
import static org.hamcrest.number.OrderingComparison.lessThan;
import static org.hamcrest.MatcherAssert.assertThat;
public class ListExample{
@Test
public void testAssertList() {
List<Integer> actual = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> expected = Arrays.asList(1, 2, 3, 4, 5);
//All passed / true
//1. Test equal.
assertThat(actual, is(expected));
//2. Check List has this value
assertThat(actual, hasItems(2));
//3. Check List Size
assertThat(actual, hasSize(4));
assertThat(actual.size(), is(5));
//4. List order
// Ensure Correct order
assertThat(actual, contains(1, 2, 3, 4, 5));
// Can be any order
assertThat(actual, containsInAnyOrder(5, 4, 3, 2, 1));
//5. check empty list
assertThat(actual, not(IsEmptyCollection.empty()));
assertThat(new ArrayList<>(), IsEmptyCollection.empty());
//6. Test numeric comparisons
assertThat(actual, everyItem(greaterThanOrEqualTo(1)));
assertThat(actual, everyItem(lessThan(10)));
}
}
4.8 JUnit Map Example
public class MapExample {
@Test
public void testAssertMap() {
Map<String, String> map = new HashMap<>();
map.put("j", "java");
map.put("c", "c++");
map.put("p", "python");
map.put("n", "node");
Map<String, String> expected = new HashMap<>();
expected.put("n", "node");
expected.put("c", "c++");
expected.put("j", "java");
expected.put("p", "python");
//All passed / true
//1. Test equal, ignore order
assertThat(map, is(expected));
//2. Test size
assertThat(map.size(), is(4));
//3. Test map entry, best!
assertThat(map, IsMapContaining.hasEntry("n", "node"));
assertThat(map, not(IsMapContaining.hasEntry("r", "ruby")));
//4. Test map key
assertThat(map, IsMapContaining.hasKey("j"));
//5. Test map value
assertThat(map, IsMapContaining.hasValue("node"));
}
}
4.9 JUnit Tools
Following are the JUnit Tools used for Testing −
References
https://www.tutorialspoint.com/junit/