EECE332 – Assignment 2 Due Friday Sept 30, 2022 at 1:45 PM Topics: Unit Testing Collaboration Policy: In all assignments (in-lab exercises and take-home assignments), you are allowed to collaborate or use any references that might be useful (books, Internet, previouses, etc.) as long as you adhere to the basic integrity rules: put sufficient effort and time to solve the problems independently before seeking help, indicate the references and sources of help that you used, understand and write the solutions yourself (do not copy-paste nor type answers that you do not understand). Statement Submit a statement which confirms that you adhered to the integrity rules and which indicates whether you used references or help to complete this assignment (in that case includes the references). Examples: - Statement example 1: The solutions are completely my work: I did not use the help of others and did not use references other than the class lectures - Statement example 2: • • • • I have put sufficient time and effort to solve the problems on my own, before seeking help. My friend ‘X’ (or my tutor/instructor… ) helped me with Problem 1. I found the solution for problem 2 in the previouses (or in this youtube link, etc.) The final submitted work was completed by me (I understood the solutions and wrote them on my own without copying) I. Background Unit testing is a software testing approach where individual components of a software (such as methods) are tested. It is widely used in industry where numerous supporting tools exist. In this regard, JUnit was developed as a unit testing framework for Java. It is an instance of the xUnit architecture for unit testing frameworks (NUnit for .NET, CppUnit for C++, and PyUnit for Python). JUnit allows users to write testing code which checks condition (assertion) and reports whether the test failed or succeeded. Such tests make use of a range of methods defined in the junit.framework.assert class (see Appendix). Code coverage analysis is another quality assurance task which aims at evaluating the testing process itself. In particular, code coverage tools highlight the sections of the code that get executed during testing. This allows developers to identify untested sections and perform further testing accordingly. The package Eclipse IDE for Java Developers has built-in support for JUnit and code coverage. The example below shows how to write unit tests and generate code coverage information using Eclipse. II. Example 1) Create a new project by selecting “File -> New -> Java Project” 2) Enter “Example” in the project name field 3) Leave the other options on their default values and press “Finish” 4) Create a new class by right-clicking on the “src” folder and selecting “New -> Class” 5) Enter “Fraction” in the name field and press “Finish” 6) Use the following implementation for this class: public class Fraction { private int num = 0; private int den = 1; public Fraction(int num, int den) { this.num = num; this.den = den; } public Fraction add(Fraction other) { return new Fraction(num*other.den + other.num*den, den*other.den); } public Fraction multiply(Fraction other) { return new Fraction(num*other.den, den*other.den); } } public boolean equals(Object obj) { Fraction other = (Fraction) obj; if(num*other.den == other.num*den) return true; return false; } 7) To create a JUnit test case for our class: a. Select the “Fraction” class in the the project explorer b. Select “File -> New -> JUnit Test Case” c. The name of the test class will be automatically generated. Keep all the default options and press “Finish” d. You might be prompted to add JUnit 5 to the build path as in the following screenshot e. Press OK to continue f. This should create a class called “FractionTest” with a method that is annotated with “@Test”. g. Implement the following test methods which validate the methods “equals” and “Add” in class “Fraction”: import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; class FractionTest { @Test void testEquals() { Fraction f1 = new Fraction(2,3); Fraction f2 = new Fraction(4,6); assertEquals(f1,f2); } @Test void testAdd() { Fraction f1 = new Fraction(1,2); Fraction f2 = new Fraction(1,4); Fraction f3 = new Fraction(3,4); assertEquals(f1.add(f2), f3); } } h. Run the tests with the coverage results by right-clicking FractionTest.java in the project explorer and selecting “Coverage As -> JUnit test”. Note that both tests succeed. The code coverage information would be shown as in the figure below. The lines highlighted in green are those that were covered when running the tests and those highlighted in red are the ones that did not get executed. i. Add a test method to validate method multiply. What do you notice? III. Assignment Description You are required to write JUnit tests for classes Point and Triangle provided with the assignment material. Make sure to address the following: 1. You should test each method in both classes. Make sure each method is tested in a separate test method (as in the examples above). 2. Your tests should achieve 100% coverage 3. You should provide one failing test for method Triangle.determineType Appendix When writing JUnit tests, the following conventions are followed: • A test case class is usually called “{ClassName}Test” where ClassName is the name of the class under test. It can contain multiple methods. • A test case method is used to test one or more of the methods of the class under test. • A test suite is an empty class that only specifies a list of test classes to run. Its name usually ends with “TestSuite”. The basic building blocks of the Unit tests are the annotations and the assertions. a) The “@Test” annotation is used for every test case method, and it can accept arguments such as the “expected” parameter that specifies that an exception of a given type is expected to be thrown by the annotated test case. b) There are many assertions that are provided by JUnit out of the box. In addition, there are more advanced assertions that are found in the “org.hamcrest” package. The most common assertions can be used by adding an import statement “import static org.junit.Assert.*;”. The description of some of those follows: • assertEquals(expected, actual): Assert that the expected value is equal to the actual value. The values can be of any type (int, double, byte, String, char, Object). Note that it is preferable to use assertEquals(expected, actual, epsilon) when dealing with values of type double to handle properly the comparison. • assertArrayEquals(expected, actual): Assert that two arrays are equal. Similar to the assertEquals method. • assertTrue(condition): Assert that a Boolean condition is true. • assertFalse(condition): Assert that a Boolean condition is false. • assertNull(object): Assert that an Object is null. • assertNotNull(object): Assert that an Object isn’t null. • assertSame(expected, actual): Assert that two objects refer to the same object. • assertNotSame(expected, actual): Assert that two objects do not refer to the same object. All assertX() methods accept an additional first argument “String message” which is the message to display when the assertion does not hold. In addition, the fail(String message) method can be used to always fail a test. It can be useful in conjunction with try/catch blocks or to simplify a complex assertion condition.