Lecture 7: Testing

9/11/2020

A New Way

How Does a Programmer Know That Their Code Works?

Sorting: The McGuffin for Our Testing Adventure

The New Way

Ad Hoc Testing vs. JUnit

Ad Hoc Test

public class TestSort { /** Test the Sort.sort method */ public static void testSort() { String[] input = {"i", "have", "an", "egg"}; String[] expected = {"an", "egg", "have", "i"}; Sort.sort(input); for (int i = 0; i < input.length; i += 1) { if (!input[i].equals(expected[i])) { System.out.println("Mismatch in position " + i); return; } } if (java.utils.Arrays.equals(input, expected)) { System.out.println("Error! There seems to be a problem with Sort.sort."); } } public static void main(String[] args) { testSort(); } }

JUnit: A Library for Making Testing Easier

public class TestSort { /** Test the Sort.sort method */ public static void testSort() { String[] input = {"i", "have", "an", "egg"}; String[] expected = {"an", "egg", "have", "i"}; Sort.sort(input); org.junit.Assert.assertArrayEquals(expected, input); } public static void main(String[] args) { testSort(); } }

Selection Sort

Back to Sorting: Selection Sort

public class Sort { /** Sorts strings recursively */ public static void sort(String[] x) { // Find the smallest item // Move it to the front // Selection sort the rest int smallestIndex = findSmallest(x); swap(x, 0, smallestIndex); } /** Swap item a with b */ public static void swap(String[] x, int a, int b) { String temp = x[a]; x[a] = x[b]; x[b] = temp; } /** Returns the index of the smallest String in x */ public static int findSmallest(String[] x) { int smallestIndex = 0; for (int i = 0; i < x.length; i += 1) { int cmp = x[i].compareTo(x[smallestIndex]); if (cmp < 0) { smallestIndex = i; } return smallestIndex; } } } public class TestSort { /** Test the Sort.sort method */ public static void testSort() { String[] input = {"i", "have", "an", "egg"}; String[] expected = {"an", "egg", "have", "i"}; Sort.sort(input); org.junit.Assert.assertArrayEquals(expected, input); } /** Test the Sort.findSmallest method */ public static void testFindSmallest() { String[] input = {"i", "have", "an", "egg"}; int expected = 2; int actual = Sort.findSmallest(input); org.junit.Assert.assertEquals(expected, actual); String[] input2 = {"there", "are", "many", "pigs"}; int expected2 = 1; int actual = Sort.findSmallest(input2); org.junit.Assert.assertEquals(expected2, actual2); } public static void testSwap() { String[] input = {"i", "have", "an", "egg"}; int a = 0; int b = 2; String[] expected = {"an", "have", "i", "egg"}; Sort.swap(input, input, b); org.junit.Assert.assertArrayEquals(expected, input); } public static void main(String[] args) { testSwap(); testFindSmallest(); testSort(); } }

The Evolution of Our Design

public class Sort { /** Sorts strings recursively */ public static void sort(String[] x) { sort(x, 0); } /** Sorts x starting at position start */ private static void sort(String[] x, int start) { if (start == x.length) { return; } int smallestIndex = findSmallest(x, start); swap(x, start, smallestIndex); sort(x, start + 1); } /** Swap item a with b */ public static void swap(String[] x, int a, int b) { String temp = x[a]; x[a] = x[b]; x[b] = temp; } /** Returns the index of the smallest String in x. Starting at start */ public static int findSmallest(String[] x, int start) { int smallestIndex = start; for (int i = start; i < x.length; i += 1) { int cmp = x[i].compareTo(x[smallestIndex]); if (cmp < 0) { smallestIndex = i; } return smallestIndex; } } } public class TestSort { /** Test the Sort.sort method */ public static void testSort() { String[] input = {"i", "have", "an", "egg"}; String[] expected = {"an", "egg", "have", "i"}; Sort.sort(input); org.junit.Assert.assertArrayEquals(expected, input); } /** Test the Sort.findSmallest method */ public static void testFindSmallest() { String[] input = {"i", "have", "an", "egg"}; int expected = 2; int actual = Sort.findSmallest(input, 0); org.junit.Assert.assertEquals(expected, actual); String[] input2 = {"there", "are", "many", "pigs"}; int expected2 = 2; int actual2 = Sort.findSmallest(input2, 2); org.junit.Assert.assertEquals(expected2, actual2); } /** Test the Sort.swap method */ public static void testSwap() { String[] input = {"i", "have", "an", "egg"}; int a = 0; int b = 2; String[] expected = {"an", "have", "i", "egg"}; Sort.swap(input, input, b); org.junit.Assert.assertArrayEquals(expected, input); } public static void main(String[] args) { testSwap(); testFindSmallest(); testSort(); } }

The Evolution of Our Design

Reflections on the Process

And We're Done!

Simpler JUnit Tests

Simple JUnit

Better JUnit

Even Better JUnit

public class Sort { /** Sorts strings recursively */ public static void sort(String[] x) { sort(x, 0); } /** Sorts x starting at position start */ private static void sort(String[] x, int start) { if (start == x.length) { return; } int smallestIndex = findSmallest(x, start); swap(x, start, smallestIndex); sort(x, start + 1); } /** Swap item a with b */ public static void swap(String[] x, int a, int b) { String temp = x[a]; x[a] = x[b]; x[b] = temp; } /** Returns the index of the smallest String in x. Starting at start */ public static int findSmallest(String[] x, int start) { int smallestIndex = start; for (int i = start; i < x.length; i += 1) { int cmp = x[i].compareTo(x[smallestIndex]); if (cmp < 0) { smallestIndex = i; } return smallestIndex; } } } import org.junit.Test; import static org.junit.Assert.*; public class TestSort { /** Test the Sort.sort method */ @org.junit.Test public void testSort() { String[] input = {"i", "have", "an", "egg"}; String[] expected = {"an", "egg", "have", "i"}; Sort.sort(input); assertArrayEquals(expected, input); } /** Test the Sort.findSmallest method */ @org.junit.Test public void testFindSmallest() { String[] input = {"i", "have", "an", "egg"}; int expected = 2; int actual = Sort.findSmallest(input, 0); assertEquals(expected, actual); String[] input2 = {"there", "are", "many", "pigs"}; int expected2 = 2; int actual2 = Sort.findSmallest(input2, 2); assertEquals(expected2, actual2); } /** Test the Sort.swap method */ @org.junit.Test public void testSwap() { String[] input = {"i", "have", "an", "egg"}; int a = 0; int b = 2; String[] expected = {"an", "have", "i", "egg"}; Sort.swap(input, input, b); assertArrayEquals(expected, input); } }

Testing Philosophy

Correctness Tool #1: Autograder

Autograder Driven Development (ADD)

Correctness Tool #2: Unit Tests

Test-Driven Development (TDD)

A Tale of Two Workflows

Correctness Tool #3: Integration Testing

Parting Thoughts