Code Coverage - 10 Course Points

What is JUnit Testing?

JUnit is a framework which can be used to write tests for your code. Tests are important, because they allow you to ensure each piece works individually as expected, in a controlled enviroment. Throughout the semester, JUnit will become a valuable resource if you learn to use it, as it can help you debug assignments. In this assignment, you will be using JUnit to test some given functions within different java classes under the src/code/ directory. We include the JUnit library in your project files, under the lib folder. Do not remove these jar files. To write tests, we create a “test” directory in the same folder as the “src” directory. Then we will create a test java file. For this lab since we are testing random unrelated code, it will be named “CodeTest.java”. We then declare the package, import the junit framework, import anything we need for our tests, and then declare the class as normal. Note: You are given all of this in the project files.

How to write JUnit Tests

To create a JUnit test, you simply define a method starting with the word “test”, and usually followed by a method or feature name you want to test. You should annotate it as a test method, by placing “@Test” right above the method declaration. For example, the FizzBuzz class has a fizzBuzz(int n) method you will test, so the test in CodeTest.java is defined as: JUnit tests relies on assert statements, which are methods you can call to check if certain things are equal. The most important assert statements are:
  • assertEquals(expected, actual): Checks if the expected value matches the actual value.
  • assertTrue(condition): Verifies that the given boolean condition is true.
  • assertFalse(condition): Verifies that the given boolean condition is false.
  • assertNull(value): Verifies that the value is null.
  • assertNotNull(value): Verifies that the value is not null.
You can use these to check that specified conditions are true. This is useful in order to check the return values of methods, or check object attributes after running methods. The flexibility of these methods is why JUnit is such a powerful tool. EXAMPLE: We can write a simple test method for the a multiplication method. We will first define our test method in the CodeTest.java, as the “testMultiply()” method, annotated with the @Test tag. Then, we use assertions (mainly assertEquals(a,b)) to test the method with various inputs, and check their outputs for correctness. To run this test, we will use the Java test runner, located on the VSCode sidebar (after you install the correct extensions listed on the Course FAQ). From this tab, you can choose your available test classes, and run either the whole class (all the tests) or any individual test. A test fails when one of the assertion statements is not succesfully passed. For example, if we say that 3 times 2 equals 4, the assertion statement checking the calculation will fail. When the assertion statement fails: it will throw an AssertionError or ComparisonFailure, stop the current test, and then move onto the next test. We can see above that the assertion expected the value to be 4, but the method call multiplies 3 and 2 so it returns 6 instead. Thus this throws an AssertionError and fails that test. With this in mind, you can write simple tests in CodeTest.java as shown above, by testing solely using various inputs & expected outputs.

Overview

To complete this lab, you will fill out the empty unit tests in CodeTest.java. Each of these test methods corresponds to one class in the src/code package. 

You will be graded on the unit tests passing and the code coverage of the tests. Code coverage is how much of the target code gets executed by the tests. Since the algorithms you will test are short, it will only take a few different inputs to fully cover the code. 

Provided Classes

Under the code package, a few classes are included, each with one static method:

  • FizzBuzz.java has fizzBuzz(int n), which returns different strings depending on the input number.
  • Palindrome.java has isPalindrome(String s) which returns true or false depending on if the input is a palindrome.
  • BinarySearch.java has binarySearch(int[] arr, int target) which is a simple Binary Search implementation
  • MaxInArray.java has maxInArray(int[] arr) which returns the max int in the array
  • Factorial.java has factorial(int n) which returns the factorial of the given int
Do not edit any of these files.

In addition, a test package is provided, with CodeTest.java. This is the unit testing file you will write your code in and submit.

Directions

  • DO NOT add new import statements.
  • DO NOT add any new class attributes
  • DO NOT change any of the method’s signatures.
  • DO NOT modify the given constructor. 

To Run: Open the project directory in VSCode, and click the Run Button in the CodeTest class to run your tests. Make sure you are in the correct directory, you should open the CodeCoverage folder which directly contains the src, and lib folders.

To Run JUnit Tests: Make sure you install the Test Runner for Java extension and all other required extensions, listed on the Course FAQ page. Right click CodeTest.java and select Run Tests. 

Task 1: Test fizzBuzz(int n)

The first task is writing a unit test for the FizzBuzz.fizzBuzz() method

This method takes one parameter as input, an integer n.

The return values are as follows:

  • if n is divisible by 5 AND 3 -> return “FizzBuzz”
  • if n is divisible by ONLY 5 -> return “Buzz”
  • if n is divisible by ONLY 3 -> return “Fizz”
  • if n is NOT divisible by 5 OR 3 -> return “” + n

Use assertion statements (as show in the How to write JUnit Tests section), to test the above cases. Make one call to fizzBuzz() per-each assertion statement (one for each of the cases above). 

i.e. assertEquals(“Expected String (from above)”, actual function call)

Task 2: Test binarySearch(int[] array, int target)

The second task is writing a unit test for the BinarySearch.binarySearch() method

Binary Search is an algorithm used to search for a target integer in a sorted array. It does so by first checking the middle item. If target < mid (target comes BEFORE the middle item), then it searches the bottom half of the array. If target > mid (target comes AFTER the middle item), then it searches the top half of the array.

This method takes two parameters as input, the array of ints to search and the int target to search for. There are only three main cases:

  • Target < Mid
  • Target > Mid
  • Target Not in array

Use assertion statements same as in Task 1 to test this method. For this, you will need to create input data in the form of int arrays.

i.e. int[] array1 = new int[]{1,2,3,4,5};

Task 3: Test isPalindrome(String input)

The third task is writing a unit test for the Palindrome.isPalindrome() method

A palindrome is a word which is spelled the same way forwards and backwards (i.e. “racecar”)

This method takes one parameters as input, a String. The method returns true if that String is a palindrome, or false otherwise. 

  • Input String is a palindrome -> return true 
  • Input String is NOT a palindrome -> return false
  • Input String is null -> return false
  • Input String is 0 or 1 letters long -> return true
  • Input String is an empty string (”  “) -> return true

Use assertion statements same as in Tasks 1 and 2 to test this method. Make sure to cover all of the above cases, one assertion statement per case.

Task 4: Test factorial(int n)

The fourth task is writing a unit test for the Factorial.factorial() method

This method takes one parameter as input, an integer n. The method returns the int factorial of the number.

  • Input number is < 0 -> return -1
  • Input number is 0 or 1 -> return 1
  • Input number is even -> return factorial of n
  • Input number is odd -> return factorial of n

Use assertion statements same as in previous tasks to test this method. Make sure to cover all of the above cases, one assertion statement per case.

Task 5: Test maxInArray(int[] arr)

The fifth task is writing a unit test for the MaxInArray.maxInArray() method

This method takes one parameter as input, an array of integers. The method returns the maximum value in that array.

  • Input array is empty or null -> return Integer.MIN_VALUE
  • Input array has one element -> return that element
  • Input array is all negative -> return max
  • Input array is all positive -> return max
  • Input array has positives AND negatives -> return max

Use assertion statements same as in previous tasks to test this method. Make sure to cover all of the above cases, one assertion statement per case.

In addition, you will need to create multiple different integer arrays as input to test with.

Before submission

REMOVE all print statements you have written in CodeTest.java 

Collaboration policy. Read our collaboration policy on our course syllabus.

Submitting the assignment. Submit CodeTest.java separately via the web submission system called Autolab. 

Getting help

If anything is unclear, don’t hesitate to drop by office hours or post a question on Piazza.

  • Find instructors and Lead TA office hours here
  • Find tutoring hours on Canvas -> Tutoring
  • In addition we have the Coding and Social Lounge (CSL) , a community space staffed with ilab assistants which are undergraduate students further along the CS major to answer questions.

By Colin Sullivan