Unit Testing Lab |
CS 159 CS 159 Docs Labs Projects Labs Lab 01 - Eclipse Lab Lab 02 - Memory Lab Lab 03 - Two-Dimensional Arrays Lab Lab 04 - Debugger Lab Lab 05 - Class Design Lab Lab 06 - ArrayList Lab Lab 07 - File I/O Lab Lab 08 - Unit Testing Lab View page source Edit this page Create child page Create documentation issue Print entire section Severe Weather Policy Background Part 1 - 100% Coverage Submission Part 2 - Boundary Cases (Optional) Tag Cloud .equals1 .jar1 .toString1 2D-array2 accessor1 activation record1 arguments1 array3 arraylist1 checkstyle2 class design1 CLI2 command line2 constructor1 coverage1 data modeling1 debugger1 docs1 document2 eclipse3 editor2 enum1 exceptions1 file2 format2 gradescope1 heap1 inheritance1 input1 install1 jacoco1 jdk1 junit4 lab1 load1 memory1 mutator1 OOP1 output1 overload1 override1 polymorphism1 project5 project11 project21 project31 project41 read1 save1 setup1 stack1 stub1 test2 tutor1 unit test2 unit testing1 validate1 visualizer1 write1 Categories Docs2 Lab9 Project5 Labs Lab 08 - Unit Testing Lab Unit Testing Lab Tags: unit testing junit coverage jacoco Categories: Lab 6 minute read Unit Testing and Code Coverage Severe Weather Policy The goal of this lab is to gain experience writing JUnit tests and using code coverage analysis. Background Suppose that JMU had the following severe weather cancellation policy: (here's the real one) JMU (FAKE) SEVERE WEATHER POLICY If any of the following conditions are met, campus will be closed: More than 6.0 inches of rain are predicted within the next 24 hours. Wind speeds greater than 70.0 mph are predicted within the next 24 hours. It is predicted that there will be more than 4.0 inches of rain and wind speeds will be above 45.0 mph. If none of the above conditions are met, the University may still issue a warning and encourage individuals to avoid non-essential outdoor activities. A warning will be issued if any of the following conditions are met: Predicted wind speeds are above 45.0 mph. Predicted precipitation is above 4.0 inches. The following Java class has been developed as part of a JMU Decision Support system: WeatherUtils.java The weatherAdvice method provides an implementation of the cancellation policy above. Your job is to develop a set of JUnit tests to confirm that this method is implemented correctly. Your testing must also confirm that the correct exception is thrown when the method receives invalid input. Part 1 - 100% Coverage Creating a JUnit Test Class Once you have set up an Eclipse project containing WeatherUtils.java, create a stub JUnit test class: Right click the WeatherUtils.java in the Package Explorer and select New -> JUnit Test Case. Make sure New JUnit Jupiter test is selected. Click the Next button, check the box for WeatherUtils, and click Finish (don’t worry if you see a warning against using the default package). This should prompt you to add Junit 5 to the build path and create a new file named WeatherUtilsTest.java. Write Javadoc comments so that Checkstyle is happy. For example: import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
/** * Tests the WeatherUtils class. * * @author * @version */
public class WeatherUtilsTest {
/** * Tests the weatherAdvice method. */
@Test
public void testWeatherAdvice() {
fail("Not yet implemented");
}
}
Replace the fail method call with an assertion, for example: assertEquals("CANCEL", WeatherUtils.weatherAdvice(70.1, 0.0));
Run the JUnit test by clicking the green Run button on the toolbar. If you see a green bar on the left, your test passed; if you see a red bar, your test failed. You can now run coverage analysis against your program by clicking the button to the right of Run (this button should say Coverage in the tooltip when you hover your mouse cursor over it). This should color-code your Java files to indicate which lines are being exercised by your tests. You should also see a new tab labeled Coverage that will display coverage percentages for each file. Note: Consider adjusting your theme away from Dark themes if the highlighting that indicates your test coverage makes the file nearly illegible (for some of the dark themes). You can select which coverage metric to display (Line Counters, Branch Counters, etc.) by clicking on the View Menu (3 vertical dots icon) in the far right of the Coverage window. Writing Additional Tests Complete WeatherUtilsTest.java by writing an appropriate set of test methods. You should be able to check your code coverage from within Eclipse. Keep working until your tests cover 100% of the method. Once you are confident that your unit tests are sufficient, demonstrate them and your coverage to the instructor or TA. Your goal is to achieve 100% method, statement, and branch coverage. Note: In order to cover the public class WeatherUtils line, you will need to construct a (useless) WeatherUtils object. The following example "covers" the default constructor. Notice that there is nothing to assert. /** * Tests the constructor (for 100% coverage). */
@Test
public void testDefaultConstructor() {
new WeatherUtils();
}
Testing for Exceptions There are several ways to test for thrown exceptions in JUnit. The easiest way (see below and also the assertThrows example on the CS wiki ) requires a language feature we haven’t covered yet, so we recommend you use the first example in the CS wiki which involves your junit test catching the expected error, and using junit’s fail method after the line you expected to throw. The “canonical ” way is to use assertThrows: /** * Test invalid wind speed. */
@Test
public void testInvalidWindSpeed() {
assertThrows(IllegalArgumentException.class, () -> {
WeatherUtils.weatherAdvice(-1.0, 0.0);
});
}
The -> operator defines a lambda expression. In programming, a "lambda" is a block of code that can be assigned to a variable. Lambdas allow you to write unnamed methods on the fly and pass them as parameters to other methods. In the above example, we define an unnamed method that takes no paramters () and that invokes weatherAdvice. Make sure you can answer the following questions: Why do you need to define a lambda expression? Why can't you just pass the result of WeatherUtils.weatherAdvice to assertThrows? What does code coverage look like when exceptions are thrown? Is there any way to get 100% coverage for a test class that has exceptions? Submission Note There’s a little incompatibility problem with our Gradescope setup right now. If you make the following tiny changes, you should still be able to run locally with the expected test and coverage analysis results, but also actually get points from Gradescope: Ensure that your test class is public (i.e. public class WeatherUtilsTest…) Ensure that your test methods are public (i.e public void testDefaultConstructor() {...) Change the imports in your test class. Your test class hopefully has only these import statements: import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
but in order to workaround a little Gradescope issue we’re having, please replace these with the following (this should not cause the tests to stop passing or compiling locally [on your machine], and neither should this have an effect on your coverage report): import static org.junit.Assert.*;
import org.junit.Test;
Upload your completed WeatherUtilsTest.java file to Gradescope. To be graded, your code must (1) pass Checkstyle and (2) pass JUnit. If any of your tests fail, you will need to revise and resubmit. Part 2 - Boundary Cases (Optional) 100% coverage doesn’t necessarily mean that your tests are good enough. High-quality tests should be able to uncover errors in the code that is being tested. The next step is to run your tests against an implementation that is known to contain errors. If your tests are effective, they should indicate that there is a problem with this code. For this part of the lab, you will run your tests against a pre-compiled .class file that we have intentionally coded to contain at least one error. Create a new Java Project. Copy your completed WeatherUtilsTest.java file into the new project, and make sure that JUnit is on the classpath (right-click the project, go down to Build Path, and click Add Libraries…JUnit…(ensure JUnit5 is selected)…Finish). Download the file WeatherUtils.class to anywhere but your Eclipse project folder Go to Project / Properties and click on Java Build Path. Click on Libraries -> Classpath -> Add External Class Folder. Navigate to the folder where you downloaded the WeatherUtils.class file. Press “Okay”. You will see a new section in the Package Explorer window called “Referenced Libraries” and you should see your new folder beneath it. Execute the tests to confirm that at least one test fails. Last modified March 9, 2022: added p4 stubs (61e734d) © 2022 The Docsy Authors All Rights Reserved Privacy Policy About Goldydocs