Testing

From now on, we will be developing unit tests for all of our code. Unit testing is widely used in the software industry to create automated tests to make sure the methods you have created work correctly before you use them in larger projects. Writing extensive unit tests early will save you a lot of time debugging later on.

In order to be able to create tests for our code, we will need to make sure to open the lab folder, rather than just a single file. So before you begin, make sure you open the Lab 3 folder in VS Code and can see all your files in the explorer window.

Now open DataSet.java. DataSet is a simple class that contains an ArrayList of Doubles and can compute some very simple statistics on them. HOWEVER, we suspect that some of the methods may have been written incorrectly. We’re going to write tests for our methods to make sure they work the way we want.

In DataSet.java, right click anywhere in the file, and select “Source Action” from the right click menu. Then, select “Generate Tests”. It may pop up the following message:

If so, click “Enable tests” and select “JUnit Juniper” when it asks which framework to add. It will then install JUnit.

You will then need to right click again, select “Source Action” and then “generate tests.” It will ask you to select a test framework - select JUnit 5.

This will then prompt you to put in a class name for your test file, with the default name of DataSetTest. Select this default. It’s traditional that when writing unit tests for a class Thing, the test class is named ThingTest. Next, it will prompt you with what methods you want to create tests for. Select all of them except add(), and hit okay.

You should now see a new java file named DataSetTest.java, which contains a class named DataSetTest with a lot of empty test methods.

If you click on the flask icon (the bottom-most icon in the left menu), you should see a list of all your newly generated test methods. Click on the double triangle run icon next to TESTING to run them. Since all your tests are empty, you should see a lot of green checks indicating that they passed.

Let’s start by testing the size() method. Inside the testSize() method in DataSetTest.java, create a new DataSet ds = new DataSet();. Start by testing that it has size of 0 after you create it. Enter

assertEquals(0, ds.size());

on the next line. assertEquals(expected, actual) will test that actual is equal to expected and if it is not, then the test will fail. You will also need to add the import statement

import static org.junit.jupiter.api.Assertions.assertEquals;

Make sure the import statement looks the way the above line does. If it doesn’t have “Assertions” then you have imported the wrong assertEquals and your code won’t work.

There are many similar assertion methods. Here is a partial list of the supported methods:

  • assertEquals(expected, actual) — asserts that actual is equal to expected
  • assertNotEquals(unexpected, actual) — asserts that actual is not equal to unexpected
  • assertTrue(condition) — asserts that condition is true
  • assertFalse(condition) — asserts that condition is false
  • assertNull(actual) — asserts that actual is null
  • assertNotNull(actual) — asserts that actual is not null
  • assertThrows(expectedType, executable) — asserts that executable throws an exception of class expectedType; see Warmup 4 for more details.
  • fail(message) — fails the test with the given message

Check out the JavaDoc for a list of all of them.

Run the tests again. You should still see all green check marks indicating that all your tests have passed. www Go ahead and add a few more elements to the data set and test the size by adding appropriate assertEquals() statements.

So far, everything is looking good; however, it’s a good idea to make sure that your tests are actually being run. The way to do that is to change your test to be deliberately wrong. When you run the tests, it had better fail! Go ahead and do so now. When you run the tests you should see a red x next to the method. When you click it, it should tell you what the expected and actual results were, and the line of code where the assert failed.

Okay, fix your test and now write a test for max(). Make sure you add some positive and negative numbers to your DataSet. Run your tests.

Create a test for min(). It should be pretty similar to your test for max.

If all the tests you have written up to this point pass, then I have some bad news: your testing was insufficient. One of these methods definitely has a bug. Go back to your tests for max and min. Create multiple DataSets and assert the values of max() and min(). Try creating one that only has positive numbers; one that only has negative numbers; one that only has the same number. Try to think of any other edge cases and test those.

Which values inserted into your DataSet caused the method to fail? Write your answer in a comment at the bottom of the DataSet.java file.