Thursday, July 4, 2013

First JUnitCast Test Case for Google Code Jam Problem

Today I will demonstrate how JUnitCast can be used as testing library for one of Google code jam problem Store Credit.  JUnitCast has been explained in my previous blog, make sure you check that out if you have trouble understanding the codes presented here.

Google Code Jam presents some of the most seemingly easy problems yet possess notoriously hard to find bug.

You can find the original problem here: Store Credit

Problem
You receive a credit C at a local store and would like to buy two items. You first walk through the store and create a list L of all available items. From this list you would like to buy two items that add up to the entire value of the credit. The solution you provide will consist of the two integers indicating the positions of the items in your list (smaller number first).
Input
The first line of input gives the number of cases, N. N test cases follow. For each test case there will be:
  • One line containing the value C, the amount of credit you have at the store.
  • One line containing the value I, the number of items in the store.
  • One line containing a space separated list of I integers. Each integer P indicates the price of an item in the store.
  • Each test case will have exactly one solution.
Output
For each test case, output one line containing "Case #x: " followed by the indices of the two items whose price adds up to the store credit. The lower index should be output first.
Limits
5 ≤ C ≤ 1000
1 ≤ P ≤ 1000
Small dataset
N = 10
3 ≤ I ≤ 100
Large dataset
N = 50
3 ≤ I ≤ 2000
Sample

Input

 Output
3
100
3
5 75 25
200
7
150 24 79 50 88 345 3
8
8
2 1 9 4 4 56 90 3
Case #1: 2 3
Case #2: 1 4
Case #3: 4 5

Complete source files will be available soon on Google project.

Figure 1: StoreCredit.properties

Figure 2: JUnitCast Test Class.



Figure 3: JUnit Runner Result



Wednesday, July 3, 2013

Another Unit Testing Technique using JUnit and CAST

This blog is about a unit testing technique I developed as by-product while working with client's projects.  Readers are required to have a practical knowledge of JUnit.  Mockito mocking framework is also used minimally in the example.

This blog is intended to provide information to developers on another technique, as well as providing me a method to document things in a well-known location for future reference.


Background


Unit Testing is a great practice as it guarantees correctness of the code unit.  Unit testing also encourages good code design.  Writing a short, maintainable unit test cases however can be a daunting task.

Here are just some of the challenges in writing a unit test.

  • Identifying scenarios.
  • Ballooning number test methods for each scenario identified.
  • Naming test methods.
  • Setting/Cleaning up
  • Orthogonality  



  • Assertions/Verifications

With this technique, commonly used practice about assertions, and test methods, can be set aside if not eliminated totally.  We will define the concept of variables, rules, and outcomes that will enable us to automatically generate all the test case scenarios needed and verify each result with little effort.

Let us start by defining some concepts.


I. CONCEPTS


 

Subject

This is the class under test.

 


Popsicle sticks.

Figure 1: Colored Popsicle Sticks.


Popsicle sticks is a great tool for introducing arithmetic to very young kids.  This time these sticks will represent test scenarios.  For example, if there are three sticks colored red, green, and blue, this means that we have exactly three unique scenarios to test.

 

Variables

Variables are characteristics that affects the outcome when the subject is executed.  In the above example, the variable is the color. Variables directly affect the number of scenarios.  A total of only three scenarios in the previous example.  Adding a new group of variables like 'size', will result in multiplying the number of colors to the number of sizes to produce the distinct list of scenarios.  The list of scenarios will be a combination of colors and sizes: small red, small green, small blue, medium red, medium green  and so on and so forth.  The subject will be tested exhaustively against all these scenarios without the need for you to write a single test method.

 

Rules

Rules define what is the outcome for each of the sticks.  An example is to vote yes if the stick is blue or green, and vote no if the color is red.  Voting yes or no for each stick is equivalent to testing every scenario.  It is important to realize that a stick must fall into exactly one outcome defined in the rule.

In the following example, 'Vote Yes' and 'Vote No' are the two possible outcomes.  Green and blue stick will fall into 'Vote Yes', while the red stick will fall into 'Vote No'.
    rule0=Vote Yes : green | blue ~ Vote No : red

'Vote No' can be safely rewritten as a negation of  'Vote Yes'.
    rule0=Vote Yes : green | blue ~ Vote No : !( green | blue)

The above example can alternatively be simplified by having only one outcome and specifying a pair parameter. 
    rule0 = Vote Yes : green | blue
    pair0 = Vote Yes : Vote No
























This means outcome is 'Vote Yes' if the color is green or blue, otherwise all other scenarios go into the opposite of 'Vote Yes', as specified by the pair key.  This construct works only for exactly two outcomes.

     Legend
  •     The pipe | is used as the logical OR operator.
  •       The ampersand & is used as the logical AND operator.
  •       The tilde ~ is used to separate the expected outcomes.
  •       Exclamation ! is used to negate the expression.
  •       Parenthesis ( ) is used to enforce precedence.

Warning!

A leak is when a stick does not fall into any of the identified outcomes. A leak is an uncaught scenario caused by incorrect rule, or a valid exclusion.  An example of a valid exclusion is when a red small stick cannot exist.  One reason could be a business rule that a red small stick is impossible exist.  Valid exclusions must to be defined to prevent breaking the rule that each stick must fall into exactly one outcome.  Exclusion is worth mentioning but for simplicity, it will not be used in the examples.

Exclusion is expressed as:
    exempt0 = small & red


PEA Pattern

Figure 2.

This is not a design pattern.  PEA refers to three ordered steps in structuring a unit test code.  Preparation, Execution, and Assertion.

  1. Preparation is where state of the subject is initialized. This is where dependencies like method arguments, methods invocation behaviors are initialized and mapped to the variables.
  2. Execution is when logical unit of the subject is executed.  The outcome of the execution is also expected to be identified in this step.  The outcome can be the return value of the method, an exception, or any representation of the result when the subject's code is executed.
  3. Assertion is where the observed outcome of the execution is checked against the expected outcome.
   

II. Introducing JUnitCast


JUnitCast is an extension of JUnit 4, using Parameterized test runner.  This library implements the concepts above.  Cast stands for Catch All Scenario Testing, or Catch All STicks.

Click here to go to JUnitCast project home page.





Let us analyze a working example in the next section.


III. Examples


Suppose we have a worker that needs to determine if the current day is a working or a rest day.  We will define that a non working is when the current day is Sunday, or any other day that falls on a holiday.

1. Create the Java class.

Figure 3: Worker.java
The hasWork method  will determine if today is work or rest day.   Notice that the methods isHoliday and getDayOfTheWeek is left unimplemented to demonstrate isolated testing of the logical unit hasWork method.

 

 2. Create the Test Class.

Oh wait, not yet!  First, we will create a property file and define the case description, variables, and rules in any order.  This is part of the preparation step.

Figure 4: WorkerTest.properties

Why property file?  This is to better isolate crucial testing parameters.  This also improves the readability of the test class by externalizing some of the preparation codes.  Note that variables and outcomes will be referenced later in our test class.  This can be done in the test class instead when desired.

Note: Backslash is used as line continuity in properties file.

Now create the test class:


WorkerTest.properties

Notice that the most significant part of the test class is inside the methods prepare and execute.  It is important to understand what is happening inside these two methods.

 3. Run the test

Figure 6: JUnit Runner
The test description alone provides meaningful information to determine if the rules configured is correct or not.


Has Work is the test description we put in the casedesc key in the property file.
After 'Expect=' is the expected outcome based on the rule defined.
Scenario[<List>] is the unique combination of all the variables defined.
 
JUnit 4.11 is required to display a descriptive test listings as shown in figure 4.
Prior to 4.11 Parameters annotation will not have the 'name' attribute resulting in the list appearing as [0], [1], [2],..[14].

 

4. Check Code Coverage

Figure 7: Code Coverage


 5. Change Request

When the requirement changes, the implementation logic inevitably changes.  But what about the test class?  How easy will the test class adapt to changes?

Consider one or all of the following:

  • Some workers work only on Monday, Wednesday, and Friday.  Action needed: Update the rule in the properties file.
  • Working holiday is introduced.  Action needed: Update the first variable group, update the rule, update prepare method().
  • Any day is a working day if the employer requests an overtime.  Action needed: Insert new variables group (No Required OT, Required OT), update the prepare() method, and update the rule
  • There is work only if time is from 12mn up to 12 noon.  Action needed: Insert new variables hours (0, 1, 2, 3,..23) , update the prepare() method, and update the rule.

 6. Another Example Runner Result

Figure 8: JUnit runner result of testing the logical AND operator.


IV. Conclusion

The technique presented deviates from the way we typically code unit tests.  Testing logic is no longer necessary.  Instead, we identify variables, define rules, then write mapping codes in prepare and execute methods. Having hundreds, even thousands of test cases, is a trivial task. Covering all branches of the code is a breeze, but the challenge is actually for you to limit the test cases to only those that really matters.

 

V. Thank you.


Thank you for reading.  Please leave questions or feedback as a comment below. 
Happy coding, and unit testing!

More examples are available in the project home page.  Other features include typed scenarios, multiple outcomes, constructor initialization test, multiple test cases, common variables, and scenario exclusions.