Lecture 8 Testing With JUnit
Lecture 8 Testing With JUnit
Spring 2024
Course Instructor:
Ms. Seemab Khan- Lecturer (Software Engineering )
Department of Creative Technologies
Air University - Islamabad
[email protected]
Lecture 8
● Software reliability: Probability that a software system will not cause failure under
specified conditions.
● Measured by uptime, MTTF (mean time till failure), crash data.
@Test
public void name() { // a test case method
...
}
}
● The JUnit bar will show green if all tests pass, red if any fail.
@Test
public void test2() {
Date d = new Date(2050, 2, 15);
d.addDays(14);
assertEquals(d.getYear(), 2050);
assertEquals(d.getMonth(), 3);
assertEquals(d.getDay(), 1);
}
}
Well-structured assertions
public class DateTest {
@Test
public void test1() {
Date d = new Date(2050, 2, 15);
d.addDays(4);
assertEquals(2050, d.getYear()); // expected
assertEquals(2, d.getMonth()); // value should
assertEquals(19, d.getDay()); // be at LEFT
}
@Test
public void test2() {
Date d = new Date(2050, 2, 15);
d.addDays(14);
assertEquals("year after +14 days", 2050, d.getYear());
assertEquals("month after +14 days", 3, d.getMonth());
assertEquals("day after +14 days", 1, d.getDay());
} // test cases should usually have messages explaining
} // what is being checked, for better failure output
Expected answer objects
public class DateTest {
@Test
public void test1() {
Date d = new Date(2050, 2, 15);
d.addDays(4);
Date expected = new Date(2050, 2, 19);
assertEquals(expected, d); // use an expected answer
} // object to minimize tests
@Test
public void test_addDays_wrapToNextMonth_2() {
Date actual = new Date(2050, 2, 15);
actual.addDays(14);
Date expected = new Date(2050, 3, 1);
assertEquals("date after +14 days", expected, actual);
}
// give descriptive names to expected/actual values
}
What's wrong with this?
public class DateTest {
@Test
public void test_addDays_addJustOneDay_1() {
Date actual = new Date(2050, 2, 15);
actual.addDays(1);
Date expected = new Date(2050, 2, 16);
assertEquals(
"should have gotten " + expected + "\n" +
" but instead got " + actual\n",
expected, actual);
}
...
}
Good assertion messages
public class DateTest {
@Test
public void test_addDays_addJustOneDay_1() {
Date actual = new Date(2050, 2, 15);
actual.addDays(1);
Date expected = new Date(2050, 2, 16);
assertEquals("adding one day to 2050/2/15",
expected, actual);
}
...
}
@Test(timeout = 5000)
public void name() { ... }
● The above method will be considered a failure if it doesn't finish running within 5000 ms
@Test(timeout = TIMEOUT)
public void name() { ... }
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void testBadIndex() {
ArrayIntList list = new ArrayIntList();
list.get(4); // should fail
}
Setup and teardown
@Before
public void name() { ... }
@After
public void name() { ... }
@BeforeClass
public static void name() { ... }
@AfterClass
public static void name() { ... }
● Many products have a set of mandatory check-in tests that must pass before code can be
added to a source code repository.
Test-driven development
● Imagine that we'd like to add a method subtractWeeks to our Date class, that shifts this Date
backward in time by the given number of weeks.
● Need a quick set, queue, etc.? Many collections can take a list
Set<Integer> list = new HashSet<Integer>(
Arrays.asList(7, 4, -2, 9));
What's wrong with this?
public class DateTest {
// shared Date object to test with (saves memory!!1)
private static Date DATE;
@Test(timeout = DEFAULT_TIMEOUT)
public void addDays_sameMonth() {
DATE = new Date(2050, 2, 15); // first test;
addhelper(DATE, +4, 2050, 2, 19); // DATE = 2/15 here
}
@Test(timeout = DEFAULT_TIMEOUT)
public void addDays_nextMonthWrap() { // second test;
addhelper(DATE, +10, 2050, 3, 1); // DATE = 2/19 here
}
@Test(timeout = DEFAULT_TIMEOUT)
public void addDays_multipleCalls() { // third test;
addDays_sameMonth(); // go back to 2/19;
addhelper(DATE, +1, 2050, 2, 20); // test two calls
addhelper(DATE, +1, 2050, 2, 21);
}
...
}
Test case "smells"
import org.junit.runner.*;
import org.junit.runners.*;
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestCaseName.class,
TestCaseName.class,
...
TestCaseName.class,
})
public class name {}
Test suite example
import org.junit.runner.*;
import org.junit.runners.*;
@RunWith(Suite.class)
@Suite.SuiteClasses({
WeekdayTest.class,
TimeTest.class,
CourseTest.class,
ScheduleTest.class,
CourseComparatorsTest.class
})
public class HW2Tests {}
JUnit summary
● Tests need failure atomicity (ability to know exactly what failed).
● Each test should have a clear, long, descriptive name.
● Assertions should always have clear messages to know what
failed.
● Write many small tests, not one big test.
4 Each test should have roughly just 1 assertion at its end.