jDataLab

7 minute read

Is unit testing the same as debugging?

There are many types of testing methods that are performed either by individual programmers or a development team. Among them, unit testing might be the one that is mostly deployed by individuals. The unit tests aim at functional requirements rather than implementation code.

When writing a program, a programmer can write unit test code to find out whether each unit or module produces expected results and works as expected.

Before proceeding to write new units, test all the units that have been written and not tested yet. A good unit test will improve coding efficiency by saving time on building new modules upon defective units.

Unit tests are not designed to detect bugs in the code.

  • A unit test should be written so that it is independent from other units.
  • A unit test should generate valid input data for the target unit.
  • The tester should know the correct/expected result that is expected from the target unit.
  • The expected result from the unit should be able to be determined by reading relevant functional requirements.
  • The tester should know the right way of running the unit and reading the actual result from the unit.
  • Though it is impossible to test every possible occurrence, the tester should write representative unit test cases.
  • In the end, the tester should compare the actual result with the expected result.
  • As a conclusion, the unit test either succeeds or fails.
  • If a unit test has failed, take further action to revise the unit for retesting untill the test succeeds.

Example - Testing by Simple Assertions

This example is based on a Java class Triangle, whose definition is available in the post [Java Review: Classes, Instances, Properties, Methods]( {{site.url}}{{site.baseurl}}{% post_url 2017-01-09-java-review-classes | absolute_url %} ).

Triangle will be tested with JUnit by using simple assertions.

JUnit is one unit testing framework for Java. NetBeans IDE supports JUnit unit testing framework. To complete this example, a Java project should be set up for holding Triangle.java in the package mytools.

To start writing a unit test program, make a new file in the project.

In the following Choose File Type dialog box, select Unit Tests for Categories and Test for Existing Class for File Types. image-title-here{:class="img-responsive”}

Click Next to see the following dialog box. image-title-here{:class="img-responsive”}

In the dialog box above, browse to select the class Triangle. Uncheck the first four buttons in the middle checkbox column.

Click Finish button.

A new unit test class TriangleTest has been created under the Test Packages. The following block shows the sample unit test code that should be exactly same as what in NetBeans 8.1 with JUnit 4.12.

1{% include src/TriangleTest.java %}

Run the test

Inside the Projects tab of NetBeans, right click TriangleTest.java and select Run File. The output should be similar to the picture below. It shows all 5 tests failed. image-title-here{:class="img-responsive”}

Schedule the test

Basically, the units should be tested one after the other. There are five units to be tested in Triangle, getA, getB, getC, allPositive and isValid.

A default test name is formatted by prepending the target unit name with ‘test’.

Each unit test method is annotated with @Test.

Disable a Test Method

To disable other tests, a simple way is to comment the test methods to be disabled. In this case, three getter methods should be tested before other methods. If getA is the first one to be tested, comment all the other test methods (In NetBeans, select the block. Go to Source menu and do Toggle Comment.)

Design the Test

After commenting all the other test methods in TriangleTest, the original testGetA method needs to be modified for testing purpose.

 1    /**
 2     * Test of getA method, of class Triangle.
 3     */
 4    @Test
 5    public void testGetA() {
 6        System.out.println("getA");
 7        Triangle instance = null;
 8        int expResult = 0;
 9        int result = instance.getA();
10        assertEquals(expResult, result);
11        // TODO review the generated test code and remove the default call to fail.
12        fail("The test case is a prototype.");
13    }

Firstly, it should be known that getA takes no argument and it returns the length of side a of a triangle in an integer. Though getA doesn’t ask for input, it is associated with a triangle. The test method testGetA must prepare a triangle instance, which explains line 7 in the code block above.

Triangle instance = null;

Replace null with an expression that instantiates a new triangle instance named instance.

Instantiation is explained in the post

[Java Review: Instantiation w/ the keyword new]( {{site.url}}{{site.baseurl}}{% post_url 2017-01-10-java-instantiation-new %} )

Line 8 of the testGetA method declares a variable expResult for the expected result from calling getA on the given triangle instance named instance.

Line 9 of the testGetA calls getA on the instance and stores the method return in a variable result.

The assertEquals Method

Now, compare expResult with result by the statement

assertEquals(expResult, result);

assertEquals is one of the assertion methods for testing whether two arguments are actually equal.

assertTrue and assertFalse are two other assertion methods for checking whether the actual result is true or false as expected.

The Revised testGetA method

 1    /**
 2     * Test of getA method, of class Triangle.
 3     */
 4    @Test
 5    public void testGetA() {
 6        System.out.println("getA");
 7        Triangle instance = new Triangle(3, 4, 5);
 8        int expResult = 3;
 9        int result = instance.getA();
10        assertEquals(expResult, result);
11    }

Run the revised test. The test output should be similar to the picture below.

image-title-here{:class="img-responsive”}

Test getB and getC methods

Test allPositive method

 1    /**
 2     * Test of allPositive method, of class Triangle.
 3     */
 4    @Test
 5    public void testAllPositive() {
 6        System.out.println("allPositive");
 7        // case 1
 8        Triangle instance = new Triangle(-3, 4, 5);
 9        boolean expResult = false;
10        boolean result = instance.allPositive();
11        assertEquals(expResult, result);
12        // case 2
13        instance = new Triangle(3, 4, 5);
14        expResult = true;
15        result = instance.allPositive();
16        assertEquals(expResult, result);
17        // case 3
18        instance = new Triangle(0, 4, 5);
19        expResult = false;
20        result = instance.allPositive();
21        assertEquals(expResult, result);
22    }
23	{% endhighlight %}
24
25### Test *isValid* method
26<div class="highlight"><pre style="background-color:#eed;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1</span>    <span style="color:#228b22">/**
27</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2</span><span style="color:#228b22">     * Test of isValid method, of class Triangle.
28</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3</span><span style="color:#228b22">     */</span>
29<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4</span>    <span style="color:#707a7c">@Test</span>
30<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5</span>    <span style="color:#8b008b;font-weight:bold">public</span> <span style="color:#00688b;font-weight:bold">void</span> <span style="color:#008b45">testIsValid</span>() {
31<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6</span>        System.<span style="color:#658b00">out</span>.<span style="color:#658b00">println</span>(<span style="color:#cd5555">&#34;isValid&#34;</span>);
32<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7</span>        <span style="color:#228b22">// case 1
33</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8</span><span style="color:#228b22"></span>        Triangle instance = <span style="color:#8b008b;font-weight:bold">new</span> Triangle(3, 4, 5);;
34<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9</span>        <span style="color:#00688b;font-weight:bold">boolean</span> expResult = <span style="color:#8b008b;font-weight:bold">true</span>;
35<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10</span>        <span style="color:#00688b;font-weight:bold">boolean</span> result = instance.<span style="color:#658b00">isValid</span>();
36<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11</span>        assertEquals(expResult, result);
37<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12</span>        <span style="color:#228b22">// case 2
38</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13</span><span style="color:#228b22"></span>        instance = <span style="color:#8b008b;font-weight:bold">new</span> Triangle(0, 4, 5);
39<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14</span>        expResult = <span style="color:#8b008b;font-weight:bold">false</span>;
40<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15</span>        result = instance.<span style="color:#658b00">isValid</span>();
41<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16</span>        assertEquals(expResult, result);
42<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17</span>        <span style="color:#228b22">// case 3
43</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18</span><span style="color:#228b22"></span>        instance = <span style="color:#8b008b;font-weight:bold">new</span> Triangle(-1, 4, 5);
44<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19</span>        expResult = <span style="color:#8b008b;font-weight:bold">false</span>;
45<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20</span>        result = instance.<span style="color:#658b00">isValid</span>();
46<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21</span>        assertEquals(expResult, result);
47<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22</span>        <span style="color:#228b22">// case 4
48</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23</span><span style="color:#228b22"></span>        instance = <span style="color:#8b008b;font-weight:bold">new</span> Triangle(1, 3, 5);
49<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24</span>        expResult = <span style="color:#8b008b;font-weight:bold">false</span>;
50<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25</span>        result = instance.<span style="color:#658b00">isValid</span>();
51<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26</span>        assertEquals(expResult, result);
52<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27</span>    }
53<span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28</span>		{% endhighlight %}</code></pre></div>