My name is Vasyl Khrystiuk‎ > ‎process‎ > ‎main‎ > ‎

junit


Strarting point for this article was: http://www.ibm.com/developerworks/ru/edu/j-junit4/
Another good references: http://www.tutorialspoint.com/junit/

Intro

Testing is big and important part in software development, so correct testing and understanding of its principles is important too.

Testing is also in center of Test Driven Development(TDD) process, which is popular nowadays due to its benefits. (there are many other types of software development processes).
More about TDD:
In this article we will not touch TDD more, because this topic is special. Meanwhile testing is very common process.
Some info about TDD is here.
Also there are nothing about mocking frameworks.


Types of testing and testing levels

Testing levels (more about each http://www.protesting.ru/testing/testtypes.html):
  • Component Testing or Unit Testing
  • Integration Testing (moving the test of the units' interplay)
  • System Testing
  • Acceptance Testing

Types of testings(more about each http://www.protesting.ru/testing/testtypes.html):
  • Functional types
    • Functional testing
    • Security and Access Control Testing
    • Interoperability Testing
  • Load testing
    • Performance and Load Testing
    • Stress Testing
    • Stability / Reliability Testing
    • Volume Testing
  • Installation testing
  • Usability Testing
  • Failover and Recovery Testing
  • Configuration Testing
  • Smoke Testing
  • Regression Testing
  • Build Verification Test
  • Sanity Testing

Intro to junit

Output from it:
 INFO (SomeLogicTest.java:26) - SomeLogicTest static loading
 INFO (SomeLogicTest.java:38) - setUpBeforeClass we r
 INFO (SomeLogicTest.java:30) - SomeLogicTest object created
 INFO (SomeLogicTest.java:54) - setUp we r
 INFO (SomeLogicTest.java:70) - testAdd run here
 INFO (SomeLogicTest.java:62) - tearDown we r
 INFO (SomeLogicTest.java:30) - SomeLogicTest object created
 INFO (SomeLogicTest.java:54) - setUp we r
 INFO (SomeLogicTest.java:79) - testMultiply run here
 INFO (SomeLogicTest.java:62) - tearDown we r
 INFO (SomeLogicTest.java:46) - tearDownAfterClass we r

So first go static class loading. Then executing static methods with annotation @BeforeClass. Then per each test are created new Test class instance. And before test methods with annotation @Before executing and after - with annotation @After.


Exception testing

@Test(expected=IndexOutOfBoundsException.class)
public void verifyIndexOutOfBoundsException() throws Exception{        
    List<Integer> list = new ArrayList<Integer>();
    list.get(1);
}

Time conditions

@Test(timeout=1)
public void verifyTimedCondition() throws Exception{        
    Thread.sleep(1000);
}
This test falls.

Test ignore annotation and runtime test passing 

See example above.
@Ignore("this test falls by design")
@Test(timeout=1)
public void verifyTimedCondition() throws Exception{        
    Thread.sleep(1000);
}
This test will be ignored anyway. Also we can ignore test based on runtime condition via org.junit.Assume:

import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;


public class Some4Test {
    @Test
    public void testSome() {
        Assume.assumeTrue(false);
        Assert.fail("will not fail");
    }
}

Test suite

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ Some1Test.class, Some2Test.class })
public class SuiteExampleTest {

    @BeforeClass
    public static void setUpClass() {
        System.out.println("Master setup");

    }

    // in suite class additional test cases will not work
    @Test
    public void some() {
        System.err.println("some");
    }

    @AfterClass
    public static void tearDownClass() {
        System.out.println("Master tearDown");
    }
/* output
Master setup
some test 1 class
some test 2 class
Master tearDown
 */
}
Also is suite for running all inner classes:
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class Some5Test {

    public static class InnerTestClass{
        @Test
        public void doInner1Class1Test() {
        }
    }
    
    public static class InnerTestClassSecond{
        @Test
        public void doInner2Class1Test() {
        }
        @Test
        public void doInner2Class2Test() {
        }
    }
    
}

Parameterized testing

package ua.org.msangel.j2ee.hib.model;

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

import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class Some1Test {
    
    private int numberToTest;
    private boolean testResult;

    
    public Some1Test(int number, boolean result){
        this.numberToTest = number;
        this.testResult=result;
    }

    @Test
    public void test() {
        System.err.println("some test 1");
    }
    
    @Test
    public void parityNumbers() {
        assertTrue(((numberToTest%2)==0)==testResult);
    }
    
    @Parameters
    public static Collection<?> getNumersForTest(){
        return Arrays.asList(new Object[][] {{2,true},{3,false},{4, true}});
    }

}



Assert statements

From org.junit.Assert:
  • assertTrue
  • assertFalse
  • fail
  • assertEquals
  • assertArrayEquals
  • assertNotNull
  • assertNull
  • assertSame
  • assertNotSame
  • assertThat(T actual, Matcher<T> matcher) Matcher: is(...), isIn(...), not(...), equalTo(...), isOneOf(...), is(Class.class), notNullValue(), hasItem(), hasItems(), hasItemsInArray(), hasValue(), lessThen(), allOf()

Rules

Add extra functionality to tests. All documentation is in javadocs. In my current junit library i found these rules:
  • ExpectedException - same as @Test(expected) but in code and access to exception object(and information)
  • ExternalResource - extend this to work with resources what require processing before work and after
    • TemporaryFolder - temp folder for testing usage
  • RuleChain - chain of rules
  • TestWatcher - extend this to watch for test processing
    • TestName - access curent test method name 
  • Timeout - same as @Test(timeout) but applied to all tests in class
  • Verifier - extend this to controll and verify test flow
    • ErrorCollector - subclass of Verifier, which collects errors but fail only in end of test method
Also you can create own rule.

Runners

As you saw before - each test can run via different runners classes (like Parameterized.class, Suite.class, etc.)
There are many other types of runners(for example for runnint tests for junit 3 version). Also we can write own runner.

Multithread testing

Junit theories

Junit theories is like parameterized testing, but allow to combine parameters by intersection.
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

@RunWith(Theories.class)
public class Some3Test {

    @DataPoint
    public static String val = "a";
    
    @DataPoints
    public static String[] getVals(){
        return new String[]{ "ab", "cds"};
    }
    
    @DataPoints
    public static String[] candidates = {"c", "bf"};
    
    @Theory
    public void testTheory(String variant1, String variant2){
        if(variant1.length()>variant2.length()){
            System.err.println("this theory is about: "+ variant1+"+"+variant2);            
        }
        
    }
    
}
Output is:
this theory is about: bf+a
this theory is about: bf+c
this theory is about: ab+a
this theory is about: ab+c
this theory is about: cds+a
this theory is about: cds+c
this theory is about: cds+bf
this theory is about: cds+ab


BDD - Behavior Driven Development

TODO:
Looks pretty good.
and some looks poverful: 




assumeThat()













Comments