Anand Ved

Anand Ved's page

Technical Lead – Cloud Computing Project
10
Aug

Do developers also have to test? How do developers test since they are supposed to be good at coding and not at testing? Well, then the solution is for them to code the test as well!

This blog covers the basics of Junit – a framework designed to write repeatable tests. It is based on the xUnit architecture, which is basically a collection of code-driven testing techniques, allowing testing of various software units such as functions and classes and eliminating the need to write the same tests multiple times.

JUnit is simple to use and write TestCases (written as one word and different from a ‘test case’) that could cover almost all testing scenarios if planned well and covered by the tests. Moreover, it plays a vital role in code maintenance and reduces regression testing usually added by new features or code fixes.

So how do we start about JUniting? Well, the simplest rule of thumb to follow is to plan the input and output for any given scenario, be it a positive scenario or a negative one, and then write a test involving each of these scenarios. This ensures that each condition is checked well before the code release. Moreover, whenever the test suite is run for regression checks, it identifies immediate issues, introduced either due to additional fixes or addition of new features. This may mean that either the new code broke some valid scenario, or the broken scenario is no longer valid and you may turn it into a positive scenario by tweaking that test.

JUnit is based on two key Java design patterns: Command pattern and Composite pattern. A TestCase constitutes the Command object whereas a TestSuite comprises Composite TestCases.

Writing JUnit code is very simple and we would not get into the basics of it in this blog. If you are using Eclipse or any other IDE, it supports creation of JUnit tests for a given class in just a few seconds. However, we shall look at ‘from the scratch’ approach wherein we want to add a customized test suite.

The prerequisite for this would be downloading JUnit 4.x and adding the junit-xxx.jar in your classpath.

Implementing a TestClass

A quick annotation preview for TestClass

A TestClass is implemented using the ‘@Test’ annotation. There is no need to extend the TestClass now with JUnit 4.x and the method names need not start with ‘test’ as required by earlier versions of JUnit.

The ‘@BeforeClass’ annotated method is executed as soon as the TestClass is initialized and the ‘@AfterClass’ annotated method is executed before the TestClass is being finalized. They run only once in the lifetime of the tests.

The ‘@Before’ annotated method is executed before each test is run and the ‘@After’ annotated method is executed after each test has completed execution.

The ‘@Ignore’ annotation is used to ignore the test for execution.

The ‘@Timeout’ annotation takes the time in milliseconds as a parameter and fails if the test does not complete execution within the stipulated time.

A simple TestCase example is given next.

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import test.com.xoriant.testsuite.TestFinalizer;
import test.com.xoriant.testsuite.TestInitializer;

import com.xoriant.SingletonClass;

public class SingletonClassTest
{
    /**
     * @throws java.lang.Exception
     */
    @BeforeClass
    public static void setup() throws Exception
    {
        if (System.getProperty(TestInitializer.TEST_INITIALIZED) == null)
        {
            TestInitializer.setUp();
        }
    }

    @Test
    public final void testGetInstance()
    {
	try
      {
        SingletonClass singletonClass1 = SingletonClass.getInstance();
        SingletonClass singletonClass2 = SingletonClass.getInstance();

        assertEquals(singletonClass1, singletonClass2);
      }
	catch(Exception e)
{
	  fail("Execution failed due to: " + e.toString());
}
    }

    @AfterClass
    public static void tearDown()
    {
        if (System.getProperty(TestFinalizer.TEST_FINALIZED) == null)
        {
            TestFinalizer.tearDown();
        }
    }
}

Implementation of the TestInitializer class

This is a common class utilized by the test cases for loading test data for the tests prior to any execution of the tests. This class may also be invoked for independent test cases.

import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class TestInitializer
{
    public static final String TEST_INITIALIZED = "com.api.testsuite.initialized";

    static
    {
        logger.debug("Setting system property...");
        System.setProperty(PropertyManager.BUNDLE_PROPERTY_NAME, "test_config");
        System.setProperty(TEST_INITIALIZED, "Y");
    }

    /**
     * Sets up the test
     */
    @BeforeClass
    public static void setUp() throws Exception
    {
	  // Initialize the data required for the tests
    }

    @Test
    public void dummyTest()
    {
        assertTrue(true);
    }
}

Implementation of the TestFinalizer class

This class is a common class for removing test data after all the tests in the TestSuite have completed. This class may also be invoked for independent test cases.

import org.junit.AfterClass;
import org.junit.Test;
import static org.junit.Assert.assertTrue;

public class TestFinalizer
{
    public static final String TEST_FINALIZED = "com.api.testsuite.finalized";

    static
    {
        System.setProperty(PropertyManager.BUNDLE_PROPERTY_NAME, "test_config");
        System.setProperty(TEST_FINALIZED, "Y");
    }

    @AfterClass
    public static void tearDown()
    {
          // Remove the test data that was required for the tests
    }

    @Test
    public void dummyTest()
    {
        assertTrue(true);
    }
}

Implementing a TestSuite

A TestSuite is implemented using the ‘@SuiteClasses’ and ‘@RunWith’ annotations. It takes a list of TestClasses as a class array parameter and executes each of them in that order.

Here, we initialize the TestSuite by adding required test data into the database in the TestInitializer class. Similarly, we cleanup the data using the TestFinalizer class. The ‘@RunWith‘ annotation allows us to define a customized TestSuite with listeners that get triggered at appropriate events in the test execution cycle.

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

import test.com.xoriant.SingletonClassTest;

@RunWith(CustomSuite.class)
@SuiteClasses( { TestInitializer.class, SingletonClassTest.class, TestFinalizer.class })

public class AllTests
{
}

Implementing a custom TestSuite

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

import test.com.xoriant.SingletonClassTest;

@RunWith(CustomSuite.class)
@SuiteClasses( { TestInitializer.class, SingletonClassTest.class, TestFinalizer.class })

public class AllTests
{
}

Some of the best practices for JUnit tests that should be followed

  • Do not run tests with interdependent test data. This could create maintenance problems later on.
  • The source folders of the actual classes and the test classes should be different so that the tests are separate from the original source files and do not need to be shipped along with production code.
  • Keep the test class packages same as the class in question to be tested. This allows protected methods to be tested.
  • JUnit can be integrated with nightly builds and executed as an ant task. This would enable running the tests on a daily basis and avoiding production problems.
  • Utilize proper initialization and destruction methods. Never initialize test data in constructors.
  • Keep tests up-to-date to avoid revisiting the tests to be fixed.

Summarizing, in this blog, we saw how to leverage the JUnit testing framework and its derivative API TestCase to increase the testing efficiency for Java based projects.

It is to be noted that apart from Java, JUnit has also been ported for several other popular programming languages such as C#, C++, Perl, PHP and many others. The ultimate objective of using JUnit is to test before you code so that you can rest after you code!


Anand Ved
Anand Ved– Technical Lead – Cloud Computing Project

16
Jun

In this blog we are going to introduce Agile methodology of software development. We would traverse through the Principles and Processes in Agile and Outcome of “Going Agile”.

Agile Methodology

Agile involves the best practices of Waterfall, Prototyping and Spiral methodologies. It is more focused on short cycles of build and release similar to Spiral methodology and each cycle undergoes through Waterfall process of planning and analysis, design, implementation and testing. Any task unit that is developed undergoes multiple refactoring and polishing similar to Prototype methodology until it evolves into a finished product or a feature.

Agile promotes teamwork and collaboration, encourages frequent evaluation, reduces risks and promotes adaptability to new requirements and company goals. Agile methods adopt planning that is adapted to accommodate inevitable changes early on into the project as compared to predictable planning methods that resists changes and thus suffer consequences between static plans and dynamic reality.

Agile is based on the following key principles:

  • Active user involvement:

The stakeholders – for whom the system is built, are involved in the development of such a system in defining requirements and review processes.

  • Empowerment of the team

Agile team is almost independent in making decisions in terms of ownership of the task and its estimation and design including what is being delivered at the end of the iteration is also agreed upon. The onus of achieving this “commitment” lies within the team.

  • Evolution of requirements

New requirements on the project are identified based on the latest trends in the market. Various tools for automation and continuous build and integration support development processes and help control regression.

  • Shorter Delivery cycles

Due to short delivery cycles of the project, advantage of ‘Time to Market’ is available to the stakeholders. Moreover, most of the risks are identified and mitigated at quite an early stage of the project.

Agile methods usually follow the given processes:

  • Task break ups

Team picks up tasks based on priority defined by the stakeholders. The task is broken up into smaller units and each unit is estimated. The estimate includes analysis, design and approach, unit testing and acceptable criteria. Once the task estimation is done and the delivery date identified, it’s the Team’s responsibility to stick to the commitment.

  • Iterations

Usual iteration cycles for delivery range from 2 weeks to 4 weeks with usually shorter timelines preferable. Single Iteration involves a complete SDLC right from planning, analysis, design, development and testing. A feature may involve multiple iterations before it is production quality.

  • Team

Team composition in agile projects is cross-functional. The team takes up the responsibility of required functionality during delivery of tasks in the iteration. Usual size of team is 4 to 9 people to promote team communication and collaboration. Agile emphasizes on face to face communication between team members, however in case of distributed teams, communication methods like video-conferencing, voice, email, IM etc are suggested.

  • Progressive product maturity

Usually any feature or product involves multiple iterations before it is ready to be deployed into production.  Agile encourages usages of tools and techniques like early and continuous integration, team estimation, test driven design and development, code refactoring etc to improve project quality.

Outcome of “Going Agile”

  • Early ROI for stakeholders on project with all round early risk mitigation.
  • Provide a competitive edge and adaptability to new and additional requirements during project development.
  • According to the survey from Dr Dobbs Journal, Agile methodology provides far better productivity compared to other methodologies.
  • Self Organizing team with better collaboration and communication.

In summary, Agile is a Win-Win for all the parties involved in the development and execution of the project.

Well-known agile methods are:

  • DSDM
  • SCRUM
  • Extreme Programming (XP)

Look for more in this space on DSDM, Scrum and Extreme Programming.


Anand Ved
Anand Ved– Technical Lead – Cloud Computing Project

, , ,