Junit Materials For Students PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 29

JUNIT

⚫ JUnit is an open source testing framework for Java

⚫ JUnit test cases are Java classes that contain one or more unit test methods

⚫ It is a simple framework for creating automated unit tests.

⚫ These tests are grouped into test suites

⚫ JUnit tests are pass/fail tests explicitly designed to run without human
intervention JUnit can be integrated with several IDEs, including Eclipse

⚫ The JUnit distribution can be downloaded as a single jar file from


http://www.junit.org

⚫ It has to be kept in the classpath of the application to be tested

Advantages:
• it's simple to use
• it can test a single class at a time, or a suite of tests can be created for a group of
classes
• it greatly increases your confidence in the correctness of your code
• it often improves the design of the class you are testing - since you spend more
time thinking about how an object is actually used, instead of its implementation,
defects in its interface become more obvious.

JUnit with Eclipse

1.Create a new Project com.wipro.JUnit


2. Add JUnit.jar to the Classpath
3. Right click the Project and create a new Source folder called ‘test’
4. Create a new Java class called Calculator in a package junit.first
5. Add 2 methods add and sub to the Calculator class which does addition and
subtraction of 2 numbers respectively

Example:

package junit.first;
public class Calculator
{
public int add(int x,int y)
{
return x+y;
}
public int sub(int x,int y)
{
return x-y;
}
}

Procedure for running JUnitTestCase :


Right click on the Calculator class in the Package Explorer and

select New- >JUnitTestCase

• select "New JUnit4 test“

• set the source folder to "test“ – the test class gets created

Press "Next" and select the methods you want to test

Right click on CalculatorTest class and select Run-As → JUnit Test


• The results of the test will be displayed in JUnit view

• This is because the testAdd and testSub are not implemented correctly

How to write a JUnit test method


All the test methods should be marked with the JUnit annotation - @org.junit.Test

• All the JUnit test methods should be "public" methods

• The return type of the JUnit test method must be “void"

• The test method need not start with the test keyword

Example:

@Test
public void testAdd()
{
Calculator c=new Calculator();
assertEquals("Result",5,c.add(2,3));
}

Now let’s provide implementation to the code and run the test again
package junit.first;
import static org.junit.Assert.*;
import org.junit.Test;
public class CalculatorTest
{
@Test
public void testAdd()
{
Calculator c=new Calculator();
assertEquals(5,c.add(2,3));
}
@Test
public void testSub()
{
Calculator c=new Calculator();
assertEquals(20,c.sub(100,80));
}
}

Unit Test

Unit tests are implemented as classes with test methods. Each test method usually
tests a single method of the target class.

Sometimes, a test method can test more than one method in the target class, and
sometimes, if the method to test is big, you split the test into multiple test methods.

• The unit test class is an ordinary class, with two methods, tesAdd() and testSub.
Notice how this method is annotated with the JUnit annotation @Test. This is done
to signal to the unit test runner, that this is method represents a unit test, that

should be executed. Methods that are not annotated with @Test are not executed by
the test runner.

Inside the testAdd() method an instance of Calculator is created. Then it's add()
method is called with two integer values.
• Finally, the assertEquals() method is called. It is this method that does the actual
testing. In this method we compare the output of the called method (add()) with the
expected output.

• If the two values are equal, nothing happens. The assertEquals() method returns
normally. If the two values are not equal, an exception is thrown, and the test
method stops executing here.

• The assertEquals() method is a statically imported method, which normally resides


in the org.junit.Assert class.

Notice the static import of this class at the top of MyUnitTest. Using the static
import of the method is shorter than writing
Assert.assertEquals().

Assert methods and Annotations


assertArrayEquals()
– Used to test if two arrays are equal to each other

Example:

int[] expectedArray = {100,200,300};

int[] resultArray = myClass.getTheIntArray();

assertArrayEquals(expectedArray, resultArray);

assertEquals()
– It compares two objects for their equality.

Example:

String result = myClass.concat("Hello", "World");


assertEquals("HelloWorld", result);

assertEquals(“Reason for failure”,”HelloWorld”,result);


Will get printed if the test will fail
Note: All assert methods are static methods, hence one has to use static import

import static org.junit.Assert.*;

assertArrayEquals()
Used to test if two arrays are equal to each other. If the arrays are equal, the
assertArrayEquals() will proceed without errors. If the arrays are not equal, an
exception will be thrown, and the test aborted. Any test code after the
assertArrayEquals() will not be executed.

• assertEquals

The assertEquals() method can compare any two objects to each other. If the two
objects compared are not same, then an AssertionError will be thrown.

The new assertEquals methods use Autoboxing, and hence all the
assertEquals(primitive, primitive) methods will be tested as assertEquals(Object,
Object).

This may lead to some interesting results. For example autoboxing will convert

all numbers to the Integer class, so an Integer(10) may not be equal to Long(10).

This has to be considered when writing tests for arithmetic methods.

Example:
Calc class and it’s corresponding test CalcTest will give you an error.
public class Calc {
public long add(int a, int b) {
return a+b;
}
}

import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CalcTest {
@Test
public void testAdd() {
assertEquals(5, new Calc().add(2, 3));
}
}
You will end up with the following error.
java.lang.AssertionError: expected:<5> but was:<5>

This is due to autoboxing. By default all the integers are cast to Integer, but we were
expecting long here. Hence the error. In order to overcome this problem, it is
better if you type cast the first parameter in the assert

Equals to the appropriate return type for the tested method as follows
assertEquals((long)5, new Calc().add(2, 3));

assertTrue() , assertFalse()

– Used to test whether a method returns true or false

assertTrue (testClass.isSafe());

assertFalse(testClass.isSafe());

• assertNull(),assertNotNull()

– Used to test a variable to see if it is null or not null


assertNull(testClass.getObject());

assertNotNull(testClass.getObject());

• assertSame() and assertNotSame()


– Used to test if two object references point to the same object or not

Example:

String s1="Hello";

String s2="Hello";

assertSame(s1,s2); ->true

assertTrue() , assertFalse()
• If the isSafe() method returns true, the assertTrue() method will return normally.
Else an exception will be thrown, and the test will stop there.

• If the isSafe() method returns false, the assertFalse() method will return normally.
Else an exception will be thrown, and the test will stop there.

assertNull(),assertNotNull()

• If the testClass.getObject() returns null, the assertNull() method will return


normally, else the assertNull() method will throw an exception, and the test will be
stopped.

• The assertNotNull() method works oppositely of the assertNull() method. It throws


an exception if a null value is passed to it, and returns normally if a non-null value is
passed to it.

• assertSame(),assertNotSame()

• Used to check if two object references point to the same object or not.
Fixtures
– The set of common resources or data that you need to run one or more tests
• @Before
– It is used to call the annotated function before running each of the tests
• @After
– It is used to call the annotated function after each test method

Example:

public class CalculatorTest {


Calculator c=null;
@Before
public void before()
{
System.out.println("Before Test");
c=new Calculator();
}
@After
public void after()
{
System.out.println("After Test"); }
@Test
public void testAdd() {
System.out.println("Add function");
assertEquals("Result",5,c.add(2,3));
}
@Test
public void testSub() {
System.out.println("Sub function");
assertEquals("Result",20,c.sub(100,80));
}
}

OUTPUT:
Before Test
Add function
After Test
Before Test
Sub function
After Test

ANNOTATIONS:
Let's consider the case in which each of the tests that you design needs a common
set of objects. One approach can be to create those objects in each of the methods.
Alternatively, the JUnit framework provides two special methods, setUp()
and tearDown(), to initialize and clean up any common objects.

This avoids duplicating the test code necessary to do the common setup and cleanup
tasks. These are together referred to as fixtures. The framework calls the setup()
before and tearDown() after each test method—thereby ensuring that
there are no side effects from one test run to the next.
In Junit 4.x the @Before annotation does the role of the setUp() method and the
@After annotation performs the role of the tearDown() method of JUnit 3.x

@BeforeClass
– The annotated method will run before executing any of the test method
– The method has to be static

@AfterClass
– The annotated method will run after executing all the test methods
– The method has to be static

Example:

public class CalculatorTest {


static Calculator c=null;
@BeforeClass
public static void before()
{
System.out.println("Before Test");
c=new Calculator();
}
@AfterClass
public static void after()
{
System.out.println("After Test");
}
@Test
public void testAdd() {
System.out.println("Add function");
assertEquals("Result",5,c.add(2,3));
}
@Test
public void testSub() {
System.out.println("Sub function");
assertEquals("Result",20,c.sub(100,80));
}
}

O/P :
Before Test
Add function
Sub function
After Test

@Ignore
– Used for test cases you wanted to ignore

– A String parameter can be added to define the reason for ignoring

@Ignore(“Not Ready to Run”)

@Test

public void testComuteTax() { }

• @Test
– Used to identify that a method is a test method
Two optional parameters are supported by Test Annotation.
1. ‘expected’ is used to declare that a test method should throw an exception. If it
doesn't throw an exception or if it throws a different exception than the one declared,
the test fails.

Example,

@Test(expected=IndexOutOfBoundsException.class)

public void checkOutOfBounds()

new ArrayList<String>().get(1);

2.‘timeout’, causes a test to fail if it takes longer than a specified amount of clock
time (measured in milliseconds). The following test fails:

@Test(timeout=1000)

public void infinityCheck()

while(true);

Timeout
– It defines a timeout period in miliseconds with “timeout” parameter

– The test fails when the timeout period exceeds.


@Test (timeout = 1000)

public void testinfinity() {

while (true)

Parameterized test
New feature added in JUnit 4

• Used to test a method with varying number of Parameters

Steps for testing a code with multiple parameters

– The testing class should be annotated with

@RunWith(Parameterized.class)

– The class should have these 3 entities

• A single constructor that stores the test data

– Is expected to store each data set in the class fields

•A static method that generates and returns test data

– This should be annotated with @Parameters

– It should return a Collection of Arrays

– Each array represent the data to be used in a particular test run


– Number of elements in an array should correspond to the number of elements
in the constructor

– Because each array element will be passed to the constructor for every run

• A test method

Structure of a parameterized test class


•The method that generates test data must be annotated with @Parameters, and it
must return a Collection of Arrays. Each array represents the data to be used in a
particular test run. The number of elements in each array must correspond to the
number of parameters in the class's constructor, because each array element will be
passed to the constructor, one at a time as the class is instantiated over and over.

•The constructor is simply expected to store each data set in the class's fields, where
they can be accessed by the test methods. Note that only a single constructor may be
provided. This means that each array provided by the data-generating method must
be the same size, and you might have to pad your data sets with nulls if you don't
always need a particular value.

Example:

package junit.first;
import junit.first.Stringmanip.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class StringmanipTest2
{
// Fields
private String datum;
private String expected;

/*
Constructor.
*/
public StringmanipTest2(String datum, String expected)
{
this.datum = datum;
this.expected = expected;
}
/*
Test data generator.
This method is called the the JUnit parameterized test runner and returns
a Collection of Arrays. For each Array in the Collection, each
array element corresponds to a parameter in the constructor.
*/

@Parameters
public static Collection<Object[]> generateData()
{
// In this example, the parameter generator returns a List of
// arrays. Each array has two elements: { datum, expected }.
// These data are hard-coded into the class, but they could be
// generated or loaded in any way you like.
Object[][] data = new Object[][]{
{ “Smita", “SMITA" },
{ “smita", “SMITA" },
{ “SMITA", “SMITA" }
};
return Arrays.asList(data);
}

/*
This test method is run once for each element in the Collection returned by the
test data generator -- that is, every time this class is instantiated. Each time this
class is instantiated, it will have a different data set, which is available to the
test method through the
instance's fields.
*/
@Test
public void testUpperCase()
{
Stringmanip s = new Stringmanip(this.datum);
String actualResult = s.upperCase();
assertEquals(actualResult, this.expected);
}
}

Two cases are there:


– Case 1 :We expect a normal behavior and then no exceptions
– Case 2: We expect an anomalous behavior and then an exception
Case 1:
@Test
public void testDiv()
{
try
{
c.div(10,2);
assertTrue(true); //OK
}catch(ArithmeticException
expected)
{
fail("Method should not
fail");
}}
Case 2:
@Test
public void testDiv()
{
try
{
c.div(10,0);
fail("Method should fail");
}catch(ArithmeticException
expected)
{
assertTrue(true);
}}

public void div(int a,int b)throws ArithmeticException


{
int c=0;
c=a/b;
System.out.println(c);}

Test Suite
Test Suite is a Convenient way to group together tests that are related
• Used to bundle a few unit test cases and run it together
• Annotations used for this
– @RunWith
• Used to invoke the class which is annotated to run the tests in that class
– @Suite
• Allows you to manually build a suite containing tests from many classes
Example:

package junit.first;
public class Stringmanip {
String datum;
public Stringmanip(String datum) {
this.datum = datum;
}
public String upperCase() {
return datum.toUpperCase();
}
}

package junit.first;
import junit.first.Stringmanip.*;
import java.util.*;
import org.junit.Test;
import org.junit.runners.*;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class StringmanipTest2
{
// Fields
private String datum;
private String expected;
public StringmanipTest2(String datum, String expected) {
this.datum = datum;
this.expected = expected;
}

@Parameters
public static Collection<Object[]> generateData()
{ Object[][] data = new Object[][] {
{ “Smita", “SMITA" },
{ “smita", “SMITA" },
{ “SMitA", “SMITA" }
};
return Arrays.asList(data);
}
@Test
public void testUpperCase()
{
Stringmanip s = new Stringmanip(this.datum);
String actualResult = s.upperCase();
assertEquals(actualResult, this.expected);
}
}

package junit.first;
public class Calc {
public int add( int v1, int v2) {
return v1+v2;
}
public int sub( int v1, int v2) {
return v1-v2;
}
// You can add more functions here as needed..
}

package junit.first;
import static org.junit.Assert.*;
import org.junit.Test;
public class CalcTest {
Calc c = new Calc();
@Test
public void testAdd() {
assertEquals(5, c.add(10,-5));
assertEquals(5, c.add(10,-5));
assertEquals(5, c.add(20,-15));
assertEquals(5, c.add(0,5));
}
@Test
public void testSub() {
assertEquals(5, c.sub(10,5));
assertEquals(95, c.sub(100,5));
assertEquals(5, c.sub(20,15));
assertEquals(5, c.sub(10,5));
}

In JUnit, both @RunWith and @Suite annotation are used to run the suite test.
• When a class is annotated with @RunWith,
JUnit will invoke the class it references to run the tests in that class.
• Using Suite as a runner allows you to manually build a suite containing tests f
rom many classes.
@RunWith(Suite.class)
@Suite.SuiteClasses({
CalcTest.class,
StringmanipTest2.class
})
public class AllTests
{
}

When all the test cases are executed successfully, itshows green color signal
When any one test cases fails, it shows brown color signal

Sample programs

Circle.java:
package com.kce.entity;

public class Circle {

private double radius;

public double getRadius() {


return radius;
}

public void setRadius(double radius) throws ArithmeticException{

if (radius >= 0) {
this.radius = radius;
} else {
throw new ArithmeticException();
}

public double getArea() {


return Math.PI * radius * radius;
}
}

Circletest:
package com.kce.test;

import static org.junit.Assert.assertEquals;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import com.kce.entity.Circle;

public class CircleTest {


@BeforeClass
public static void first() {
System.out.println("before");
}

@Before
public void beforeEach() {
System.out.println("before each test");
}

@Test
public void testGetArea1() {
Circle c = new Circle();
c.setRadius(1);
assertEquals(0, c.getArea(), 0.001);
}

@Test(expected = ArithmeticException.class)
public void testGetArea2() {
Circle c = new Circle();
c.setRadius(-12);

@After
public void afterEach() {
System.out.println("after each test");
}

@AfterClass
public static void last() {
System.out.println("after");
}

Factorial.java
package com.kce.entity;

public class Factorial {

public long getFactorial(int number) {


int fact = 1;
for (int i = 1; i <= number; i++) {
fact *= i;
}
return fact;
}
}

Factorialtest:
package com.kce.test;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.kce.entity.Factorial;

@RunWith(Parameterized.class)
public class FactorialTest {

private int input;


private long expected;

public FactorialTest(int input, long expected) {


this.input = input;
this.expected = expected;
}

@Parameters
public static Collection<Object[]> getData(){
Object[][] data = {
{0,1},
{1,1},
{5,120},
{7,5040},
{6,720}
};
return Arrays.asList(data);
}

@Test
public void testGetFactorial() {
Factorial f = new Factorial();
assertEquals(this.expected, f.getFactorial(this.input));
}

}
================================================================================

Testsuite.class
package com.kce.test;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({CircleTest.class,FactorialTest.class})
public class TestSuite {

===========================================================
Testrunner.class
package com.kce.test;

import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {


public static void runTests() {
Result result = JUnitCore.runClasses(TestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.getException());
}
int failCount = result.getFailureCount();
int totalTestCases = result.getRunCount();
System.out.println("No. of Failed Testcases:" + failCount + "/" +
totalTestCases);
System.out.println("Score:" + (totalTestCases - failCount) + "/" +
totalTestCases);
}

public static void main(String[] args) {


runTests();
}
}
============================================================

You might also like