user3425699
user3425699

Reputation:

Doubts and suggestions about JUnit

I have a java class that contains some methods concerning the binary search in an array of integers. Now I should make a new class that verifies the correctness of these methods, testing this methods with different arrays and different elements to look for. For now, this new class of tests I've done in a "standard" way but I know that I could use JUnit. I searched on the internet a few easy guide to follow but I did not understand much.

For example, if my class "main" BinarySearch.java is made in this way:

public class BinarySearch {

    private BinarySearch() { }

    public static int find(int x, int[] a) {
        int i = 0;
        int inf = 0;
        int sup = a.length - 1;
        if(sup == -1 || x < a[0] || x > a[sup])
            return -1;
        while(inf <= sup) {
            i = (inf + sup) >>> 1; 
            if(x < a[i])
                sup = i - 1;
            else if(x > a[i])
                inf = i + 1;
            else
                return i;
        }
        return -1;
    }

    public static boolean isPresent(int x, int[] a) {
        int i = 0;
        int inf = 0;
        int sup = a.length - 1;
        if(sup == -1 || x < a[0] || x > a[sup])
            return false;       
        while(inf <= sup) {
            i = (inf + sup) >>> 1; 
            if(x < a[i])
                sup = i - 1;
            else if (x > a[i])
                inf = i + 1;
            else
                return true;
        }
        return false;
    }

    public static void sort(int[] a) {
        int b, c;
        int temp;
        int s = a.length - 1;
        for(b = 0; b < s; ++b) {
            for(c = 0; c < s; ++c) {
                if(a[c] < a[c + 1]) {
                    temp = a[c];
                    a[c] = a[c + 1];
                    a[c + 1] = temp;
                }
            }
        }
    }


    public static boolean isSorted(int[] a) {
        for(int i = 0; i < a.length-1; i++) {
            if(a[i] > a[i + 1]) {
                return false;   
            }
        }
        return true;        
    }

    public static void isort(int a[]) {
        for(int i = 1; i < a.length; i++){
            int j = i;
            int b = a[i];
            while(j > 0 && a[j - 1] > b) {
                a[j] = a[j - 1];
                j--;
            }
            a[j] = b;
        }
    }       

}

The test class "standard" is:

public class BinarySearchTestSuite {

    private BinarySearchTestSuite() {}

    static int tot = 0;
    static int pass = 0;
    static int nonPass = 0;
    static int ecc = 0;

    public static void main(String[] args) {

        int[] a1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int[] a2 = {};

        int x1 = 5;
        int x2 = 0;
        int x3 = 10;

        System.out.println();
        System.out.println("---- Test method find ----");

        //Test n.1      
        try {
            tot++;
            System.out.print("Test n.1 - Array: [ ");
            for(int i = 0; i < a1.length; i++)
                System.out.print(a1[i] +  " ");
            System.out.println("]. Element to find: " + x1 + ".");
            if(a1[BinarySearch.find(x1, a1)] == x1) {
                System.out.println(x1 + " is in position " + BinarySearch.find(x1, a1) + ".");
                System.out.println("Test OK.");
                pass++;
            }
            else if(BinarySearch.find(x1, a1) == -1) {
                System.out.println(x1 + " is not present in array");
                System.out.println("TTest OK.");
                pass++;   
            } 
            else {
                System.out.println("Test FAIL.");
                nonPass++;
            } 
        } catch(Exception eccezione) {
            System.out.println("Test FAIL.");
            ecc++;
        }
        System.out.println();

        //Test n.2
        try {
            tot++;
            System.out.print("Test n.2 - Array: [ ");
            for(int i = 0; i < a1.length; i++)
                System.out.print(a1[i] +  " ");
            System.out.println("]. Element to find: " + x2 + ".");
            if(a1[BinarySearch.find(x2, a1)] == x2) {
                System.out.println(x2 + " is in position " + BinarySearch.find(x2, a1) + ".");
                System.out.println("Test OK.");
                pass++;
            }
            else if(BinarySearch.find(x1, a1) == -1) {
                System.out.println(x1 + " is not present in array");
                System.out.println("Test OK.");
                pass++;   
            }   
            else {
                System.out.println("Test FAIL.");
                nonPass++;
            } 
        } catch(Exception eccezione) {
            System.out.println("Test FAIL.");
            ecc++;
        }
        System.out.println();  

        //RESULT
        System.out.println();    
        System.out.println("Test totali: " + tot);
        System.out.println("Test andati a buon fine: " + pass);   
        System.out.println("Test falliti: " + nonPass);
        System.out.println("Test falliti con lancio di una eccezione: " + ecc);         

    } 
}

How do I create a test class with JUnit? I need some simple examples.

I know that in the test class I have to write this code:

private final ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
private final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();

@Before
public void setupOutputStreams() {
    System.setOut(new PrintStream(outBuffer));
    System.setErr(new PrintStream(errBuffer));
}

@After
public void cleanupOutputStreams() {
    System.setOut(null);
    System.setErr(null);
}

After this code, how I write the code for the individual test? Then I compile and run this file (BinarySearchTest.java) normally? Or there is another way to do that? I'm a bit confused...

Thanks!

Thanks

Upvotes: 1

Views: 384

Answers (1)

Jeff Bowman
Jeff Bowman

Reputation: 95614

Writing a unit test is easy in JUnit4: Write some small methods that use your code, and use JUnit assertions to ensure that your code produces the answers you're expecting.

@RunWith(JUnit4.class) // JUnit4.class is a "runner".
public class BinarySearchTest {
  // By convention, the test for class Foo is named FooTest. You can name the
  // test anything you'd like, though, especially if you split your test for
  // Foo into more than one file.

  @Test public void isSortedShouldReturnTrueWhenSorted() { // Same with methods.
    assertTrue(BinarySearch.isSorted(new int[] { 2, 4, 6 }));
  }

  @Test public void isSortedShouldReturnFalseWhenUnsorted() {
    assertFalse(BinarySearch.isSorted(new int[] { 4, 2, 6 }));
  }

  @Test public void isSortedShouldReturnTrueWhenEmpty() {
    assertTrue(BinarySearch.isSorted(new int[] {}));
  }

  // Write more tests here!
}

Though many IDEs have built-in ways of running JUnit tests, you can also run tests from the command line. You don't have to write a main method, or count passed and failed tests, or print error messages; JUnit will handle that on its own. Instead, you run JUnit, you tell it where to find your test case, and JUnit runs it.

java -cp /usr/share/java/junit.jar org.junit.runner.JUnitCore your.package.BinarySearchTest
#    ^ classpath includes JUnit    ^ you're running JUnitCore ^ on your test class

For each class you have, for every method you annotate with @Test, JUnit will create a new instance of your test class, run every @Before-annotated method, run your @Test-annotated method, and then run every @After-annotated method. You may not have any methods annotated @Before or @After for simple tests, which is just fine.

The organization of your test cases is mostly yours to decide. Some people prefer to write a single test method that has many assertTrue or assertEquals statements (etc) while others prefer to write many tiny test cases that each address a different aspect (as I did above). That's up to you, but remember that JUnit will stop testing any given method after the first assertion fails or any exception is thrown, so having many smaller methods may give you a better idea of what exactly is wrong. Along those lines, specific method names are helpful: You'll never call them yourself, and having JUnit report that isSortedShouldReturnFalseWhenUnsorted is failing may be much easier than tracing why isSortedWorks might be failing.

  • You can look up all the assertions on the org.junit.Assert documentation page. Note that they're different than the assert keyword. You can also write your own code that throws exceptions on errors.
  • Don't worry about setOut and setErr. Though redirecting those will make for cleaner test output when testing modules that write to stdout and stderr, yours doesn't do that by default, and JUnit doesn't mind either way.

Upvotes: 1

Related Questions