diff --git a/hamcrest-core-1.3.jar b/hamcrest-core-1.3.jar
new file mode 100644
index 0000000000000000000000000000000000000000..9d5fe16e3dd37ebe79a36f61f5d0e1a69a653a8a
Binary files /dev/null and b/hamcrest-core-1.3.jar differ
diff --git a/junit-4.12.jar b/junit-4.12.jar
new file mode 100644
index 0000000000000000000000000000000000000000..3a7fc266c3e32283a2b21fe12166ebdcc33a1da1
Binary files /dev/null and b/junit-4.12.jar differ
diff --git a/src/tests/gitlab/ckpt1/CircularArrayComparatorTests.java b/src/tests/gitlab/ckpt1/CircularArrayComparatorTests.java
index 9082b66f29eb731c6fc9fb9fd73ef7b4ed3f10fb..8a35ef663472fb5ade87f326f1619e5d8e963041 100644
--- a/src/tests/gitlab/ckpt1/CircularArrayComparatorTests.java
+++ b/src/tests/gitlab/ckpt1/CircularArrayComparatorTests.java
@@ -1,56 +1,40 @@
 package tests.gitlab.ckpt1;
 
 import datastructures.worklists.CircularArrayFIFOQueue;
-import tests.TestsUtility;
+import org.junit.Test;
 
-public class CircularArrayComparatorTests extends TestsUtility {
-    
-    public static void main(String[] args) {
-        new CircularArrayComparatorTests().run();
-    }
-    
-    @Override
-    protected void run() {
-        SHOW_TESTS = true;
-        PRINT_TESTERR = true;
-        DEBUG = true;
+import static org.junit.Assert.*;
 
-        test("test_empty_empty");
-        test("test_ab_ab");
-        test("test_ab_abc");
-        test("test_abc_ab");
-        test("test_ac_abc");
-        test("test_a_aa");
-        test("test_equality_consistent_with_compare");
-        test("test_compare_transitive");
-        test("test_equals_doesnt_modify");
-        finish();
-    }
-    
-    protected static CircularArrayFIFOQueue<String> init() {
+public class CircularArrayComparatorTests {
+
+    private CircularArrayFIFOQueue<String> init() {
         return new CircularArrayFIFOQueue<String>(10);
     }
 
-    private static int result(int a, int b) {
-        return Integer.signum(a) == Integer.signum(b) ? 1 : 0;
+    private boolean result(int a, int b) {
+        return Integer.signum(a) == Integer.signum(b);
     }
-    
-    public static int test_empty_empty() {
+
+    @Test(timeout = 3000)
+    public void test_empty_empty() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
-        return result(l1.compareTo(l2), "".compareTo(""));
+        assertTrue(result(l1.compareTo(l2), "".compareTo("")));
     }
-    
-    public static int test_ab_ab() {
+
+    @Test(timeout = 3000)
+    public void test_ab_ab() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
         l1.add("b");
         l2.add("a");
         l2.add("b");
-        return result(l1.compareTo(l2), "ab".compareTo("ab"));
+        assertTrue(result(l1.compareTo(l2), "ab".compareTo("ab")));
     }
-    public static int test_ab_abc() {
+
+    @Test(timeout = 3000)
+    public void test_ab_abc() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
@@ -58,10 +42,11 @@ public class CircularArrayComparatorTests extends TestsUtility {
         l2.add("a");
         l2.add("b");
         l2.add("c");
-        return result(l1.compareTo(l2), "ab".compareTo("abc"));
+        assertTrue(result(l1.compareTo(l2), "ab".compareTo("abc")));
     }
-    
-    public static int test_abc_ab() {
+
+    @Test(timeout = 3000)
+    public void test_abc_ab() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
@@ -69,9 +54,11 @@ public class CircularArrayComparatorTests extends TestsUtility {
         l1.add("c");
         l2.add("a");
         l2.add("b");
-        return result(l1.compareTo(l2), "abc".compareTo("ab"));
+        assertTrue(result(l1.compareTo(l2), "abc".compareTo("ab")));
     }
-    public static int test_ac_abc() {
+
+    @Test(timeout = 3000)
+    public void test_ac_abc() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
@@ -79,44 +66,50 @@ public class CircularArrayComparatorTests extends TestsUtility {
         l2.add("a");
         l2.add("b");
         l2.add("c");
-        return result(l1.compareTo(l2), "ac".compareTo("abc"));
+        assertTrue(result(l1.compareTo(l2), "ac".compareTo("abc")));
     }
-    public static int test_a_aa() {
+
+    @Test(timeout = 3000)
+    public void test_a_aa() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
         l2.add("a");
         l2.add("a");
-        return result(l1.compareTo(l2), "a".compareTo("aa"));
+        assertTrue(result(l1.compareTo(l2), "a".compareTo("aa")));
     }
-    
-    public static int test_compare_transitive() {
+
+    @Test(timeout = 3000)
+    public void test_compare_transitive() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         CircularArrayFIFOQueue<String> l3 = init();
-        
+
         l1.add("abc");
         l2.add("def");
         l3.add("efg");
-        return l1.compareTo(l2) < 0 && l2.compareTo(l3) < 0 && l1.compareTo(l3) < 0 ? 1 : 0;
+        assertTrue(l1.compareTo(l2) < 0 && l2.compareTo(l3) < 0 && l1.compareTo(l3) < 0) ;
     }
-    
-    public static int test_equality_consistent_with_compare() {
+
+    @Test(timeout = 3000)
+    public void test_equality_consistent_with_compare() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
         l1.add("b");
         l2.add("a");
         l2.add("b");
-        return l1.equals(l2) && l1.compareTo(l2) == 0 ? 1 : 0;
+        assertEquals(l1, l2);
+        assertEquals(l1.compareTo(l2), 0);
     }
-    
-    public static int test_equals_doesnt_modify() {
+
+    @Test(timeout = 3000)
+    public void test_equals_doesnt_modify() {
         CircularArrayFIFOQueue<String> l1 = init();
         CircularArrayFIFOQueue<String> l2 = init();
         l1.add("a");
         l2.add("a");
         l1.equals(l2);
-        return l1.size() == 1 ? 1 : 0;
+        assertEquals(l1.size(), 1);
     }
 }
diff --git a/src/tests/gitlab/ckpt1/Ckpt1Tests.java b/src/tests/gitlab/ckpt1/Ckpt1Tests.java
index b687964814e819b14dc3b62b84ec8c6171a3add9..68c6d3185c569256827e63824beffa03d10f8103 100644
--- a/src/tests/gitlab/ckpt1/Ckpt1Tests.java
+++ b/src/tests/gitlab/ckpt1/Ckpt1Tests.java
@@ -1,17 +1,16 @@
 package tests.gitlab.ckpt1;
 
-import tests.GradingUtility;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 
-public class Ckpt1Tests extends GradingUtility {
-    public static void main(String[] args) {
-        new Ckpt1Tests();
-    }
+@RunWith(Suite.class)
 
-    protected Class<?>[] getTests() {
-        return new Class<?>[] {
-            NGramToNextChoicesMapTests.class,
-            MoveToFrontListTests.class,
-            CircularArrayComparatorTests.class
-        };
-    }
-}
+@Suite.SuiteClasses({
+        NGramToNextChoicesMapTests.class,
+        MoveToFrontListTests.class,
+        CircularArrayComparatorTests.class
+})
+
+public class Ckpt1Tests {
+
+}
\ No newline at end of file
diff --git a/src/tests/gitlab/ckpt1/MoveToFrontListTests.java b/src/tests/gitlab/ckpt1/MoveToFrontListTests.java
index bccb62fde9c83dd4c589b6f1e5c4d7fe349942da..1920dfb087c659e79af1ffcbf715caafe586c17e 100644
--- a/src/tests/gitlab/ckpt1/MoveToFrontListTests.java
+++ b/src/tests/gitlab/ckpt1/MoveToFrontListTests.java
@@ -4,77 +4,63 @@ import java.util.Arrays;
 
 import cse332.datastructures.containers.Item;
 import datastructures.dictionaries.MoveToFrontList;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class MoveToFrontListTests extends TestsUtility {
-    public static void main(String[] args) {
-	new MoveToFrontListTests().run();
-    }
+public class MoveToFrontListTests {
 
-    @Override
-	protected void run() {
-	    SHOW_TESTS = true;
-	    PRINT_TESTERR = true;
-	    DEBUG = true;
+	@SuppressWarnings("unchecked")
+	@Test(timeout = 3000)
+	public void checkStructure() {
+		MoveToFrontList<Integer, Integer> list = new MoveToFrontList<Integer, Integer>();
 
-	    test("testHugeMTFList");
-	    test("checkStructure");
-
-	    finish();
-	}
-
-    @SuppressWarnings("unchecked")
-	public static int checkStructure() {
-	    MoveToFrontList<Integer, Integer> list = new MoveToFrontList<Integer, Integer>();
-
-	    int[] arr = {6, 5, 10, 14, 10, 31, 10, 13, 10, 10, 12, 10, 14, 10, 10, 11, 10, 14, 9, 8, 3, 2, 1, 0, 7, 4};
-	    for(int i = 0; i < arr.length; i++) {
-		Integer oldValue = list.find(arr[i]);
-		if (oldValue == null) {
-		    list.insert(arr[i], 1);
-		} else {
-		    list.insert(arr[i], 1 + oldValue);
+		int[] arr = {6, 5, 10, 14, 10, 31, 10, 13, 10, 10, 12, 10, 14, 10, 10, 11, 10, 14, 9, 8, 3, 2, 1, 0, 7, 4};
+		for(int i = 0; i < arr.length; i++) {
+			Integer oldValue = list.find(arr[i]);
+			if (oldValue == null) {
+				list.insert(arr[i], 1);
+			} else {
+				list.insert(arr[i], 1 + oldValue);
+			}
+		}
+		// Convert iterator to string
+		Item<Integer, Integer>[] dcs = (Item<Integer, Integer>[])new Item[list.size()];
+		int i = 0;
+		for (Item<Integer, Integer> item : list) {
+			dcs[i++] = item;
 		}
-	    }
-	    // Convert iterator to string
-	    Item<Integer, Integer>[] dcs = (Item<Integer, Integer>[])new Item[list.size()];
-	    int i = 0;
-	    for (Item<Integer, Integer> item : list) {
-		dcs[i++] = item;
-	    }
 
-	    // Compare strings to make sure we get the right one
-	    // Can use list.toString as well, but I'm not sure if students may modify that
-	    String mtf_correct = "[4=1, 7=1, 0=1, 1=1, 2=1, 3=1, 8=1, 9=1, 14=3, 10=9, 11=1, 12=1, 13=1, 31=1, 5=1, 6=1]";
-	    String mtf_test = Arrays.toString(dcs);
-	    return mtf_correct.equals(mtf_test) ? 1 : 0;
+		// Compare strings to make sure we get the right one
+		// Can use list.toString as well, but I'm not sure if students may modify that
+		String mtf_correct = "[4=1, 7=1, 0=1, 1=1, 2=1, 3=1, 8=1, 9=1, 14=3, 10=9, 11=1, 12=1, 13=1, 31=1, 5=1, 6=1]";
+		String mtf_test = Arrays.toString(dcs);
+		assertEquals(mtf_correct, mtf_test);
 	}
 
-    public static int testHugeMTFList() {
-	MoveToFrontList<String, Integer> list = new MoveToFrontList<>();
+	@Test(timeout = 3000)
+	public void testHugeMTFList() {
+		MoveToFrontList<String, Integer> list = new MoveToFrontList<>();
 
-	int n = 1000;
+		int n = 1000;
 
-	// Add them
-	for (int i = 0; i < 5 * n; i++) {
-	    int k = (i % n) * 37 % n;
-	    String str = String.format("%05d", k);
-	    for (int j = 0; j < k + 1; j ++)
-		list.insert(str, list.find(str) == null ? 1 : list.find(str) + 1);
-	}
-	// Delete them all
-	boolean passed = true;
-	int totalCount = 0;
-	for (Item<String, Integer> dc : list) {
-	    passed &= (Integer.parseInt(dc.key) + 1) * 5 == dc.value;
-	    totalCount += dc.value;
-	}
-
-	// Check sizes
-	passed &= totalCount == (n * (n + 1)) / 2 * 5;
-	passed &= list.size() == n;
-	passed &= list.find("00851") == 4260;
+		// Add them
+		for (int i = 0; i < 5 * n; i++) {
+			int k = (i % n) * 37 % n;
+			String str = String.format("%05d", k);
+			for (int j = 0; j < k + 1; j ++)
+				list.insert(str, list.find(str) == null ? 1 : list.find(str) + 1);
+		}
+		// Delete them all
+		int totalCount = 0;
+		for (Item<String, Integer> dc : list) {
+			assertTrue ((Integer.parseInt(dc.key) + 1) * 5 == dc.value);
+			totalCount += dc.value;
+		}
 
-	return passed ? 1 : 0;
-    }
+		// Check sizes
+		assertEquals(totalCount, (n * (n + 1)) / 2 * 5);
+		assertEquals(list.size(), n);
+		assertNotNull(list.find("00851"));
+		assertTrue(list.find("00851") == 4260);
+	}
 }
diff --git a/src/tests/gitlab/ckpt1/NGramToNextChoicesMapTests.java b/src/tests/gitlab/ckpt1/NGramToNextChoicesMapTests.java
index cc9657960184475778206e24fb088ab752a104ce..ffa46db6c642b04abdd62de461a64d1d43cd4636 100644
--- a/src/tests/gitlab/ckpt1/NGramToNextChoicesMapTests.java
+++ b/src/tests/gitlab/ckpt1/NGramToNextChoicesMapTests.java
@@ -12,60 +12,44 @@ import cse332.types.AlphabeticString;
 import cse332.types.NGram;
 import cse332.datastructures.trees.BinarySearchTree;
 import p2.wordsuggestor.NGramToNextChoicesMap;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class NGramToNextChoicesMapTests extends TestsUtility {
-    private static Supplier<Dictionary<NGram, Dictionary<AlphabeticString, Integer>>> newOuter =
+public class NGramToNextChoicesMapTests {
+    private Supplier<Dictionary<NGram, Dictionary<AlphabeticString, Integer>>> newOuter =
             () -> new BinarySearchTree();
 
-    private static Supplier<Dictionary<AlphabeticString, Integer>> newInner =
+    private Supplier<Dictionary<AlphabeticString, Integer>> newInner =
             () -> new BinarySearchTree();
-    
-    public static void main(String[] args) {
-        new NGramToNextChoicesMapTests().run();
-    }
-    
-    @Override
-    protected void run() {
-        SHOW_TESTS = true;
-	    PRINT_TESTERR = true;
-	    DEBUG = true;
-
-        test("testOneWordPerNGram");
-        test("testMultipleWordsPerNGram");
-        test("testGetNonexistentNGram");
-        test("testRepeatedWordsPerNGram");
-        finish();   
-    }
-    
-    protected static NGramToNextChoicesMap init() {
+
+    private NGramToNextChoicesMap init() {
         return new NGramToNextChoicesMap(newOuter, newInner);
     }
-    
-    public static int testOneWordPerNGram() {
+
+    @Test(timeout = 3000)
+    public void testOneWordPerNGram() {
         NGramToNextChoicesMap map = init();
         NGram[] ngrams = new NGram[]{
                 new NGram(new String[]{"foo", "bar", "baz"}),
                 new NGram(new String[]{"fee", "fi", "fo"}),
                 new NGram(new String[]{"a", "s", "d"})
         };
-        
+
         String[] words = new String[]{"bop", "fum", "f"};
         for (int i = 0; i < ngrams.length; i++) {
             map.seenWordAfterNGram(ngrams[i], words[i]);
         }
         for (int i = 0; i < ngrams.length; i++) {
             Item<String, Integer>[] items = map.getCountsAfter(ngrams[i]);
-            if (items.length != 1) return 0;
+            assertTrue(items.length == 1);
             Item<String, Integer> item = items[0];
-            if (!item.key.equals(words[i])) return 0;
-            if (!item.value.equals(1)) return 0;
+            assertTrue(item.key.equals(words[i]));
+            assertTrue(item.value.equals(1));
         }
-        
-        return 1;
     }
-    
-    public static int testMultipleWordsPerNGram() {
+
+    @Test(timeout = 3000)
+    public void testMultipleWordsPerNGram() {
         NGramToNextChoicesMap map = init();
         NGram[] ngrams = new NGram[]{
                 new NGram(new String[]{"foo", "bar", "baz"}),
@@ -74,61 +58,58 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
                 new NGram(new String[]{"3", "2", "2"}),
                 new NGram(new String[]{"a", "s", "d"})
         };
-        
+
         String[][] words = new String[][] {
-            new String[]{"bip", "bop", "bzp"},
-            new String[]{"fum", "giants"},
-            new String[]{"ago", "seven", "years"},
-            new String[]{"new", "thrown", "uuu", "zzz"},
-            new String[]{"do", "for", "while"}
+                new String[]{"bip", "bop", "bzp"},
+                new String[]{"fum", "giants"},
+                new String[]{"ago", "seven", "years"},
+                new String[]{"new", "thrown", "uuu", "zzz"},
+                new String[]{"do", "for", "while"}
         };
-        
+
         for (int i = 0; i < ngrams.length; i++) {
             for (int j = 0; j < words[i].length; j++) {
                 map.seenWordAfterNGram(ngrams[i], words[i][j]);
             }
-            
+
         }
         for (int i = 0; i < ngrams.length; i++) {
             Item<String, Integer>[] items = map.getCountsAfter(ngrams[i]);
             String[] answer = words[i];
-            if (items.length != answer.length) return 0;
+            assertTrue(items.length == answer.length);
             String[] itemsWithoutCounts = new String[items.length];
             for (int j = 0; j < answer.length; j++) {
-                if (!items[j].value.equals(1)) return 0;
+                assertTrue(items[j].value.equals(1));
                 itemsWithoutCounts[j] = items[j].key;
             }
             Arrays.sort(itemsWithoutCounts);
             for (int j = 0; j < answer.length; j++) {
-                if (!itemsWithoutCounts[j].equals(answer[j])) return 0;
+                assertTrue(itemsWithoutCounts[j].equals(answer[j]));
             }
         }
-        
-        return 1;
     }
-    
-    public static int testGetNonexistentNGram() {
+
+    @Test(timeout = 3000)
+    public void testGetNonexistentNGram() {
         NGramToNextChoicesMap map = init();
         NGram[] ngrams = new NGram[]{
                 new NGram(new String[]{"foo", "bar", "baz"}),
                 new NGram(new String[]{"fee", "fi", "fo"}),
                 new NGram(new String[]{"a", "s", "d"})
         };
-        
+
         String[] words = new String[]{"bop", "fum", "f"};
         for (int i = 0; i < ngrams.length; i++) {
             map.seenWordAfterNGram(ngrams[i], words[i]);
         }
         Item<String, Integer>[] items = map.getCountsAfter(new NGram(new String[] { "yo" }));
-        if (items == null || items.length != 0) {
-            return 0;
-        }
-        
-        return 1;
+        assertNotNull(items);
+        assertTrue(items.length == 0);
     }
-    
+
     @SuppressWarnings("unchecked")
-    public static int testRepeatedWordsPerNGram() {
+    @Test(timeout = 3000)
+    public void testRepeatedWordsPerNGram() {
         NGramToNextChoicesMap map = init();
         // Creates Ngrams to test for with N = 3
         NGram[] ngrams = new NGram[]{
@@ -140,15 +121,15 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
         };
         // Array of words seen after each Ngram with correlating index from above
         String[][] words = new String[][] {
-            new String[]{"bop", "bip", "boop", "bop", "bop"},
-            new String[]{"fum", "giants", "giants"},
-            new String[]{"seven", "years", "years", "ago", "ago"},
-            new String[]{"throw", "throw", "throw", "throw", "throw"},
-            new String[]{"for", "while", "do", "do", "while", "for"}
+                new String[]{"bop", "bip", "boop", "bop", "bop"},
+                new String[]{"fum", "giants", "giants"},
+                new String[]{"seven", "years", "years", "ago", "ago"},
+                new String[]{"throw", "throw", "throw", "throw", "throw"},
+                new String[]{"for", "while", "do", "do", "while", "for"}
         };
-        
+
         // yes this is awful, but i can't think of a better way to do it atm
-        // Creates answers for getCountsAfter - Word seen after and count 
+        // Creates answers for getCountsAfter - Word seen after and count
         // corrlates with words and ngrams above
         // Note that words after are in sorted order, not in order of array in words
         Map<NGram, Item<String, Integer>[]> answers = new TreeMap<>();
@@ -169,13 +150,13 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
         answers.get(ngrams[4])[0] = new Item<String, Integer>("do", 2);
         answers.get(ngrams[4])[1] = new Item<String, Integer>("for", 2);
         answers.get(ngrams[4])[2] = new Item<String, Integer>("while", 2);
-        
+
         // Adds nGrams and words after to student's NGramToNextChoicesMap
         for (int i = 0; i < ngrams.length; i++) {
             for (int j = 0; j < words[i].length; j++) {
                 map.seenWordAfterNGram(ngrams[i], words[i][j]);
             }
-            
+
         }
         // checks to see if getCountsAfter returns correctly
         for (int i = 0; i < ngrams.length; i++) {
@@ -187,26 +168,19 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
                 public int compare(Object o1, Object o2) {
                     Item<String, Integer> r1 = (Item<String, Integer>)o1;
                     Item<String, Integer> r2 = (Item<String, Integer>)o2;
-                    return r1.key.compareTo(r2.key); 
+                    return r1.key.compareTo(r2.key);
                 }
-                
+
             });
             Item<String, Integer>[] expected = answers.get(ngram);
             // checks for correct number of unique words after
-            if (results.length != expected.length) return 0;
+            assertTrue(results.length == expected.length);
             for (int j = 0; j < expected.length; j++) {
                 // checks if correct word after via sorted words
-                if (!expected[j].key.equals(results[j].key)) {
-                    return 0;
-                }
+                assertTrue(expected[j].key.equals(results[j].key));
                 // checks if correct count for given word after
-                if (!expected[j].value.equals(results[j].value)) {
-                    return 0;
-                }
+                assertTrue(expected[j].value.equals(results[j].value));
             }
         }
-        return 1;
     }
-    
-
 }
diff --git a/src/tests/gitlab/ckpt2/AVLTreeTests.java b/src/tests/gitlab/ckpt2/AVLTreeTests.java
index c12088c8afcd3f2f1b170fde5a42f74812e84f08..385fce2493a9cd7310df3988c0328da6c9d77df8 100644
--- a/src/tests/gitlab/ckpt2/AVLTreeTests.java
+++ b/src/tests/gitlab/ckpt2/AVLTreeTests.java
@@ -4,31 +4,21 @@ import cse332.datastructures.containers.Item;
 import cse332.datastructures.trees.BinarySearchTree.BSTNode;
 import cse332.interfaces.misc.Dictionary;
 import datastructures.dictionaries.AVLTree;
-import tests.TestsUtility;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
-public class AVLTreeTests extends TestsUtility {
-	
-	public static void main(String[] args) {
-		new AVLTreeTests().run();
-	}
-	
-	@Override
-	protected void run() {
-        SHOW_TESTS = true;
-        DEBUG = true;
-		test("testTreeWith5Items");
-		test("testHugeTree");
-		test("checkStructure");
-		finish();
-	}
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-	protected static AVLTree<String, Integer> init() {
+public class AVLTreeTests {
+
+	private AVLTree<String, Integer> init() {
 		AVLTree<String, Integer> tree = new AVLTree<>();
 
 		return tree;
 	}
-	
-	private static <E extends Comparable<E>> void incCount(Dictionary<E, Integer> tree, E key) {
+
+	private <E extends Comparable<E>> void incCount(Dictionary<E, Integer> tree, E key) {
 		Integer value = tree.find(key);
 		if (value == null) {
 			tree.insert(key, 1);
@@ -36,9 +26,10 @@ public class AVLTreeTests extends TestsUtility {
 			tree.insert(key, value + 1);
 		}
 	}
-	
+
 	@SuppressWarnings("rawtypes")
-	public static int checkStructure() {
+	@Test(timeout = 3000)
+	public void checkStructure() {
 		AVLTree<Integer, Integer> tree = new AVLTree<>();
 		incCount(tree, 10);
 		incCount(tree, 14);
@@ -70,7 +61,7 @@ public class AVLTreeTests extends TestsUtility {
 //		{10, 14, 31, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
 
 		BSTNode root = (BSTNode) getField(tree, "root");
-		
+
 		String trueData = " [8 [4 [2 [1 [0..].] [3..]] [6 [5..] [7..]]] [12 [10 [9..] [11..]] [14 [13..] [31..]]]]";
 		String trueCounts = " [1 [1 [1 [1 [1..].] [1..]] [1 [1..] [1..]]] [1 [9 [1..] [1..]] [2 [2..] [1..]]]]";
 //		String trueData = " [10 [6 [2 [1 [0..].] [4 [3..] [5..]]] [8 [7..] [9..]]] [13 [12 [11..].] [14. [31..]]]]";
@@ -78,24 +69,25 @@ public class AVLTreeTests extends TestsUtility {
 
 //		System.err.println(nestd(root));
 //		System.err.println(trueData);
-		return nestd(root).equals(trueData) &&
-				nestc(root).equals(trueCounts) ? 1 : 0;
+		assertEquals(nestd(root), trueData);
+		assertEquals(nestc(root), trueCounts);
 	}
 
 	@SuppressWarnings("rawtypes")
-	public static String nestd(BSTNode root) {
+	public String nestd(BSTNode root) {
 		if(root == null)
 			return ".";
 		return " [" + root.key + nestd(root.children[0]) + nestd(root.children[1]) + "]";
 	}
 	@SuppressWarnings("rawtypes")
-	public static String nestc(BSTNode root) {
+	public String nestc(BSTNode root) {
 		if(root == null)
 			return ".";
 		return " [" + root.value + nestc(root.children[0]) + nestc(root.children[1]) + "]";
 	}
-	
-	public static int testTreeWith5Items() {
+
+	@Test(timeout = 3000)
+	public void testTreeWith5Items() {
 		AVLTree<String, Integer> tree = init();
 		String[] tests_struct = { "a", "b", "c", "d", "e" };
 		String[] tests = { "b", "d", "e", "c", "a" };
@@ -104,19 +96,17 @@ public class AVLTreeTests extends TestsUtility {
 			incCount(tree, str);
 		}
 
-		boolean passed = true;
 		int i = 0;
 		for (Item<String, Integer> item : tree) {
 			String str_heap = item.key;
 			String str = tests_struct[i] + "a";
-			passed &= str.equals(str_heap);
+			assertEquals(str, str_heap);
 			i++;
 		}
-
-		return passed ? 1 : 0;
 	}
 
-	public static int testHugeTree() {
+	@Test(timeout = 3000)
+	public void testHugeTree() {
 		AVLTree<String, Integer> tree = init();
 		int n = 1000;
 
@@ -129,20 +119,52 @@ public class AVLTreeTests extends TestsUtility {
 		}
 
 		// Delete them all
-		boolean passed = true;
 		int totalCount = 0;
 		for (Item<String, Integer> dc : tree) {
-			passed &= (Integer.parseInt(dc.key) + 1) * 5 == dc.value;
+			assertTrue((Integer.parseInt(dc.key) + 1) * 5 == dc.value);
 			totalCount += dc.value;
 		}
-		
+
 		// Check for accuracy
-		passed &= totalCount == (n * (n + 1)) / 2 * 5;
-		passed &= tree.size() == n;
-		passed &= tree.find("00851") != null;
-		passed &= tree.find("00851") == 4260;
-		
-		return passed ? 1 : 0;
+		assertEquals(totalCount, (n * (n + 1)) / 2 * 5);
+		assertEquals(tree.size(), n);
+		assertNotNull(tree.find("00851"));
+		assertTrue(tree.find("00851") == 4260);
+	}
+
+	private void definalize(Field field) {
+		try {
+			Field modifiersField = Field.class.getDeclaredField("modifiers");
+			modifiersField.setAccessible(true);
+			modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+		} catch (Exception e) {}
+	}
+
+	/**
+	 * Get a field from an object
+	 * @param o Object you want to get the field from
+	 * @param fieldName Name of the field
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	private <T> T getField(Object o, String fieldName) {
+		try {
+			Field field = o.getClass().getSuperclass().getDeclaredField(fieldName);
+			field.setAccessible(true);
+			definalize(field);
+			Object f = field.get(o);
+			return (T) f;
+		} catch (Exception e) {
+			try {
+				Field field = o.getClass().getDeclaredField(fieldName);
+				field.setAccessible(true);
+				definalize(field);
+				Object f = field.get(o);
+				return (T) f;
+			} catch (Exception e2) {
+				return null;
+			}
+		}
 	}
 
 }
diff --git a/src/tests/gitlab/ckpt2/CircularArrayHashCodeTests.java b/src/tests/gitlab/ckpt2/CircularArrayHashCodeTests.java
index 064d0466256ed225e7282d7d024114e0c289b10c..8c56f4af24f186046d248220efa2bf7dcb72e873 100644
--- a/src/tests/gitlab/ckpt2/CircularArrayHashCodeTests.java
+++ b/src/tests/gitlab/ckpt2/CircularArrayHashCodeTests.java
@@ -1,38 +1,29 @@
 package tests.gitlab.ckpt2;
 
 import datastructures.worklists.CircularArrayFIFOQueue;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class CircularArrayHashCodeTests extends TestsUtility {	
-	public static void main(String[] args) {
-		new CircularArrayHashCodeTests().run();
-	}
-	
-	@Override
-	protected void run() {
-        SHOW_TESTS = true;
-		test("equality");
-		test("ineq1");
-		test("ineq2");
-		test("ineq3");
-		test("equality_consistent_with_hashcode");
-		finish();
-	}
-	
-	protected static CircularArrayFIFOQueue<String> init() {
+public class CircularArrayHashCodeTests {
+
+	private CircularArrayFIFOQueue<String> init() {
 		return new CircularArrayFIFOQueue<String>(10);
 	}
 
-	public static int equality() {
+	@Test(timeout = 3000)
+	public void equality() {
 		CircularArrayFIFOQueue<String> l1 = init();
 		CircularArrayFIFOQueue<String> l2 = init();
 		for (int i = 0; i < 3; i++) {
 			l1.add("a");
 			l2.add("a");
 		}
-		return l1.hashCode() == l2.hashCode() ? 1 : 0;
+		assertEquals(l1.hashCode(), l2.hashCode());
+		assertTrue(l1.hashCode() == l2.hashCode());
 	}
-	public static int ineq1() {
+
+	@Test(timeout = 3000)
+	public void ineq1() {
 		CircularArrayFIFOQueue<String> l1 = init();
 		CircularArrayFIFOQueue<String> l2 = init();
 		l1.add("a");
@@ -41,9 +32,11 @@ public class CircularArrayHashCodeTests extends TestsUtility {
 		l2.add("a");
 		l2.add("a");
 		l2.add("a");
-		return l1.hashCode() != l2.hashCode() ? 1 : 0;
+		assertNotEquals(l1.hashCode(), l2.hashCode());
 	}
-	public static int ineq2() {
+
+	@Test(timeout = 3000)
+	public void ineq2() {
 		CircularArrayFIFOQueue<String> l1 = init();
 		CircularArrayFIFOQueue<String> l2 = init();
 		l1.add("a");
@@ -53,9 +46,11 @@ public class CircularArrayHashCodeTests extends TestsUtility {
 		l2.add("a");
 		l2.add("a");
 		l2.add("a");
-		return l1.hashCode() != l2.hashCode() ? 1 : 0;
+		assertNotEquals(l1.hashCode() , l2.hashCode());
 	}
-	public static int ineq3() {
+
+	@Test(timeout = 3000)
+	public void ineq3() {
 		CircularArrayFIFOQueue<String> l1 = init();
 		CircularArrayFIFOQueue<String> l2 = init();
 		l1.add("a");
@@ -64,16 +59,18 @@ public class CircularArrayHashCodeTests extends TestsUtility {
 		l2.add("c");
 		l2.add("b");
 		l2.add("a");
-		return l1.hashCode() != l2.hashCode() ? 1 : 0;
+		assertNotEquals(l1.hashCode() , l2.hashCode());
 	}
-	
-	public static int equality_consistent_with_hashcode() {
-    	CircularArrayFIFOQueue<String> l1 = init();
+
+	@Test(timeout = 3000)
+	public void equality_consistent_with_hashcode() {
+		CircularArrayFIFOQueue<String> l1 = init();
 		CircularArrayFIFOQueue<String> l2 = init();
 		l1.add("a");
-    	l1.add("b");
-    	l2.add("a");
-    	l2.add("b");
-    	return l1.equals(l2) && l1.hashCode() == l2.hashCode() ? 1 : 0;
-    }
+		l1.add("b");
+		l2.add("a");
+		l2.add("b");
+		assertEquals(l1 , l2);
+		assertEquals(l1.hashCode() , l2.hashCode());
+	}
 }
diff --git a/src/tests/gitlab/ckpt2/Ckpt2Tests.java b/src/tests/gitlab/ckpt2/Ckpt2Tests.java
index 751e8e9fb8490169ffa823d87427dac0c5b8b3a2..2037c54328f3a9afb00288bd395e4fd89911c8b2 100644
--- a/src/tests/gitlab/ckpt2/Ckpt2Tests.java
+++ b/src/tests/gitlab/ckpt2/Ckpt2Tests.java
@@ -1,20 +1,19 @@
 package tests.gitlab.ckpt2;
 
-import tests.GradingUtility;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 
-public class Ckpt2Tests extends GradingUtility {
-    public static void main(String[] args) {
-        new Ckpt2Tests();
-    }
+@RunWith(Suite.class)
+
+@Suite.SuiteClasses({
+        AVLTreeTests.class,
+        HashTableTests.class,
+        CircularArrayHashCodeTests.class,
+        QuickSortTests.class,
+        TopKSortTests.class,
+        HeapSortTests.class
+})
+
+public class Ckpt2Tests {
 
-    protected Class<?>[] getTests() {
-        return new Class<?>[] {
-            AVLTreeTests.class,
-            HashTableTests.class,
-            CircularArrayHashCodeTests.class,
-            QuickSortTests.class,
-            TopKSortTests.class,
-            HeapSortTests.class
-        };
-    }
 }
diff --git a/src/tests/gitlab/ckpt2/HashTableTests.java b/src/tests/gitlab/ckpt2/HashTableTests.java
index 164d8b120f21e6e8797d7e2a013ccd6d462f292e..28915890e4729ef8d550854e66cb2c6d5e0fd2a8 100644
--- a/src/tests/gitlab/ckpt2/HashTableTests.java
+++ b/src/tests/gitlab/ckpt2/HashTableTests.java
@@ -4,34 +4,26 @@ import cse332.datastructures.containers.Item;
 import cse332.interfaces.misc.Dictionary;
 import datastructures.dictionaries.ChainingHashTable;
 import datastructures.dictionaries.MoveToFrontList;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class HashTableTests extends TestsUtility {
-	
-	public static void main(String[] args) {
-		new HashTableTests().run();
-	}
-	
-	@Override
-	protected void run() {
-        SHOW_TESTS = true;
 
-		test("testHugeHashTable");	
-		finish();
-	}
+public class HashTableTests {
 
-	private static void incCount(Dictionary<String, Integer> list, String key) {
+	private void incCount(Dictionary<String, Integer> list, String key) {
 		Integer find = list.find(key);
 		if (find == null)
 			list.insert(key, 1);
 		else
 			list.insert(key, 1 + find);
 	}
-	public static int testHugeHashTable() {
+
+	@Test(timeout = 3000)
+	public void testHugeHashTable() {
 		ChainingHashTable<String, Integer> list = new ChainingHashTable<>(() -> new MoveToFrontList<>());
-		
+
 		int n = 1000;
-		
+
 		// Add them
 		for (int i = 0; i < 5 * n; i++) {
 			int k = (i % n) * 37 % n;
@@ -41,18 +33,14 @@ public class HashTableTests extends TestsUtility {
 		}
 
 		// Delete them all
-		boolean passed = true;
 		int totalCount = 0;
 		for (Item<String, Integer> dc : list) {
-			passed &= (Integer.parseInt(dc.key) + 1) * 5 == dc.value;
-//			System.out.println(((Integer.parseInt(dc.data) + 1) * 5 == dc.count) + ": " + ((Integer.parseInt(dc.data) + 1) * 5) + "==" + dc.count);
+			assertTrue ((Integer.parseInt(dc.key) + 1) * 5 == dc.value);
 			totalCount += dc.value;
 		}
-
-		passed &= totalCount == (n * (n + 1)) / 2 * 5;
-		passed &= list.size() == n;
-		passed &= list.find("00851") == 4260;
-		
-		return passed ? 1 : 0;
+		assertEquals(totalCount, (n * (n + 1)) / 2 * 5);
+		assertEquals(list.size(), n);
+		assertNotNull(list.find("00851") );
+		assertTrue(list.find("00851") == 4260);
 	}
 }
diff --git a/src/tests/gitlab/ckpt2/HashTrieMapTests.java b/src/tests/gitlab/ckpt2/HashTrieMapTests.java
index 92f235a9aa328f789da77ffc80b5d1cf47358502..100c8c46821a1837d0865b577874d1d28c55d1f3 100644
--- a/src/tests/gitlab/ckpt2/HashTrieMapTests.java
+++ b/src/tests/gitlab/ckpt2/HashTrieMapTests.java
@@ -2,320 +2,128 @@ package tests.gitlab.ckpt2;
 
 import cse332.types.AlphabeticString;
 import datastructures.dictionaries.HashTrieMap;
-import tests.TestsUtility;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
+import java.lang.reflect.Field;
 import java.util.HashMap;
 import java.util.Map;
 
-public class HashTrieMapTests extends TestsUtility {
+public class HashTrieMapTests {
     protected static HashTrieMap<Character, AlphabeticString, String> STUDENT;
 
-    public static void main(String[] args) {
-        new HashTrieMapTests().run();
-    }
-
-    public static void init() {
+    @Before
+    public void init() {
         STUDENT = new HashTrieMap<>(AlphabeticString.class);
     }
 
-    @Override
-    protected void run() {
-        SHOW_TESTS = true;
-        PRINT_TESTERR = true;
-        DEBUG = true;
-
-        test("testBasic");
-        test("testBasicDelete");
-
-        test("testFindPrefixes");
-        test("testFindNonexistentDoesNotCrash");
-        test("testFindingNullEntriesCausesError");
-
-        test("testInsertReplacesOldValue");
-        test("testInsertingNullEntriesCausesError");
-
-        test("testDeleteAll");
-        test("testDeleteNothing");
-        test("testDeleteAndInsertSingleChars");
-        test("testDeleteWorksWhenTrieHasNoBranches");
-        test("testDeletingAtRoot");
-        test("testDeletingEmptyString");
-        test("testDeletingNullEntriesCausesError");
-
-        test("testClear");
-        test("checkUnderlyingStructure");
-        test("stressTest");
-
-        finish();
-    }
-
     /**
      * Tests if insert, find, and findPrefix work in general.
      */
-    public static int testBasic() {
+    @Test(timeout = 3000)
+    public void testBasic() {
         String[] words = {"dog", "doggy", "doge", "dragon", "cat", "draggin"};
         String[] invalid = {"d", "cataract", "", "do"};
         addAll(STUDENT, words);
-        return (containsAllPaths(STUDENT, words) && doesNotContainAll(STUDENT, invalid)) ? 1 : 0;
-    }
-
-    /**
-     * Checks to see if basic delete functionality works.
-     */
-    public static int testBasicDelete() {
-        String[] words = {"dog", "doggy", "dreamer", "cat"};
-        addAll(STUDENT, words);
-        if (!containsAllPaths(STUDENT, words)) {
-            return 0;
-        }
-
-        STUDENT.delete(a("I don't exist"));
-        STUDENT.delete(a("dreamer"));
-
-        if (!containsAllPaths(STUDENT, "dog", "doggy", "cat") &&
-                !containsAllPrefixes(STUDENT, "dreamer", "dreame", "dream", "drea", "dre", "dr") &&
-                !STUDENT.findPrefix(a("d"))) {
-            return 0;
-        }
-
-        STUDENT.delete(a("dog"));
-        if (!containsAllPaths(STUDENT, "doggy", "cat")) {
-            return 0;
-        }
-
-        STUDENT.delete(a("doggy"));
-        return containsAllPaths(STUDENT, "cat") ? 1 : 0;
+        assertTrue(containsAllPaths(STUDENT, words));
+        assertTrue(doesNotContainAll(STUDENT, invalid));
     }
 
     /**
      * Test findPrefix more rigorously.
      */
-    public static int testFindPrefixes() {
+    @Test(timeout = 3000)
+    public void testFindPrefixes() {
         String[] words = {"dog", "doggy", "doge", "dragon", "cat", "draggin"};
         addAll(STUDENT, words);
 
-        boolean allPrefixesFound = containsAllPrefixes(STUDENT, "d", "", "do");
-        boolean invalidPrefixesIgnored = doesNotContainAllPrefixes(STUDENT, "batarang", "dogee", "dragging");
-
-        return allPrefixesFound && invalidPrefixesIgnored ? 1 : 0;
+        assertTrue(containsAllPrefixes(STUDENT, "d", "", "do"));
+        assertTrue(doesNotContainAllPrefixes(STUDENT, "batarang", "dogee", "dragging"));
     }
 
     /**
      * Tests that trying to find a non-existent entity does the correct thing
      */
-    public static int testFindNonexistentDoesNotCrash() {
+    @Test(timeout = 3000)
+    public void testFindNonexistentDoesNotCrash() {
         addAll(STUDENT, "foo", "bar", "baz");
-        return STUDENT.find(a("orangutan")) == null && STUDENT.find(a("z")) == null &&
-                STUDENT.find(a("ba")) == null && STUDENT.find(a("bazz")) == null &&
-                !STUDENT.findPrefix(a("boor")) && !STUDENT.findPrefix(a("z")) ? 1 : 0;
+        assertTrue(STUDENT.find(a("orangutan")) == null);
+        assertTrue(STUDENT.find(a("z")) == null);
+        assertTrue(STUDENT.find(a("ba")) == null);
+        assertTrue(STUDENT.find(a("bazz")) == null);
+        assertTrue(!STUDENT.findPrefix(a("boor")));
+        assertTrue(!STUDENT.findPrefix(a("z")) );
     }
 
-    public static int testFindingNullEntriesCausesError() {
+    @Test(timeout = 3000)
+    public void testFindingNullEntriesCausesError() {
         try {
             STUDENT.find(null);
-            return 0;
+            assertTrue(false);
         } catch (IllegalArgumentException ex) {
             // Do nothing
         }
         try {
             STUDENT.findPrefix(null);
-            return 0;
+            assertTrue(false);
         } catch (IllegalArgumentException ex) {
             // Do nothing
         }
-        return 1;
     }
 
     /**
      * Tests that inserts correctly wipe out old values.
      */
-    public static int testInsertReplacesOldValue() {
+    @Test(timeout = 3000)
+    public void testInsertReplacesOldValue() {
         AlphabeticString key = a("myKey");
-        boolean initialValueIsNull = STUDENT.insert(key, "foo") == null;
-        boolean originalValueReturned = STUDENT.insert(key, "bar").equals("foo");
-        boolean replacementValueReturned = STUDENT.insert(key, "baz").equals("bar");
-
-        return initialValueIsNull && originalValueReturned && replacementValueReturned ? 1 : 0;
+        assertTrue(STUDENT.insert(key, "foo") == null);
+        assertTrue(STUDENT.insert(key, "bar").equals("foo"));
+        assertTrue(STUDENT.insert(key, "baz").equals("bar"));
     }
 
-    public static int testInsertingNullEntriesCausesError() {
+    @Test(timeout = 3000)
+    public void testInsertingNullEntriesCausesError() {
         try {
             STUDENT.insert(null, "foo");
-            return 0;
+            assertTrue(false);
         } catch (IllegalArgumentException ex) {
             // Do nothing
         }
 
         try {
             STUDENT.insert(a("foo"), null);
-            return 0;
+            assertTrue(false);
         } catch (IllegalArgumentException ex) {
             // Do nothing
         }
-
-        return 1;
     }
 
-    /**
-     * Checks to see the trie correctly handles the case where you delete
-     * absolutely everything.
-     */
-    public static int testDeleteAll() {
-        AlphabeticString keyA = a("keyboard");
-        AlphabeticString keyB = a("keyesian");
-        AlphabeticString keyC = a("bayesian");
-
-        if (STUDENT.size() != 0 || !STUDENT.isEmpty()) {
-            return 0;
-        }
-
-        STUDENT.insert(keyA, "KEYBOARD");
-        STUDENT.insert(keyB, "KEYESIAN");
-        STUDENT.insert(keyC, "BAYESIAN");
-
-        if (!containsAllPaths(STUDENT, "keyboard", "keyesian", "bayesian")) {
-            return 0;
-        }
-        if (STUDENT.size() != 3 || STUDENT.isEmpty()) {
-            return 0;
-        }
-
-        STUDENT.delete(keyA);
-        STUDENT.delete(keyB);
-        STUDENT.delete(keyC);
-
-        if (STUDENT.size() != 0 || !STUDENT.isEmpty()) {
-            return 0;
-        }
-
-        return doesNotContainAll(STUDENT, "keyboard", "keyesian", "bayesian") ? 1 : 0;
-    }
-
-    /**
-     * Tests what happens if you attempt deleting something that doesn't exist
-     * in the trie (but _does_ partially overlap).
-     */
-    public static int testDeleteNothing() {
-        STUDENT.insert(a("aaaa"), "foo");
-
-        if (!containsPath(STUDENT, "aaaa", "foo") || STUDENT.size() != 1 || STUDENT.isEmpty()) {
-            return 0;
-        }
-
-        // Should not change the trie
-        STUDENT.delete(a("aa"));
-        STUDENT.delete(a("a"));
-        STUDENT.delete(a("abc"));
-        STUDENT.delete(a("aaaaa"));
-        STUDENT.delete(a(""));
-        STUDENT.delete(a("foobar"));
-
-        if (!containsPath(STUDENT, "aaaa", "foo") || STUDENT.size() != 1 || STUDENT.isEmpty()) {
-            return 0;
-        }
-
-        return 1;
-    }
-
-    /**
-     * Tests what happens if you try deleting and inserting single characters
-     */
-    public static int testDeleteAndInsertSingleChars() {
-        STUDENT.insert(a("a"), "A");
-        STUDENT.insert(a("b"), "B");
-
-        STUDENT.delete(a("a"));
-        STUDENT.insert(a("b"), "BB");
-
-        MockNode expected = node()
-                .branch('b', node("BB"));
-
-        return equals(expected, getField(STUDENT, "root")) ? 1 : 0;
-    }
-
-    /**
-     * Tests to see if HashTrieMap correctly handles a trie where everything is in a straight
-     * line/the trie has no branching.
-     */
-    public static int testDeleteWorksWhenTrieHasNoBranches() {
-        AlphabeticString keyA = a("ghost");
-        AlphabeticString keyB = a("gh");
-        STUDENT.insert(keyA, "A");
-        STUDENT.insert(keyB, "B");
-
-        // Trie should still contain "ghost -> A"
-        STUDENT.delete(keyB);
-        if (STUDENT.find(keyB) != null || !STUDENT.findPrefix(keyB) || !STUDENT.find(keyA).equals("A")) {
-            return 0;
-        }
-
-        // Trie should now contain "gh -> C", but not "ghost -> A"
-        STUDENT.insert(keyB, "C");
-        STUDENT.delete(keyA);
-
-        return (STUDENT.find(keyB).equals("C") && STUDENT.find(keyA) == null && !STUDENT.findPrefix(a("gho"))) ? 1 : 0;
-    }
-
-    /**
-     * A slight variation of the previous test.
-     */
-    public static int testDeletingAtRoot() {
-        STUDENT.insert(a(""), "foo");
-        STUDENT.insert(a("a"), "bar");
-        STUDENT.delete(a("a"));
-        STUDENT.insert(a("b"), "baz");
-        if (STUDENT.find(a("a")) != null) {
-            return 0;
-        }
-        if (!"foo".equals(STUDENT.find(a("")))) {
-            return 0;
-        }
-        if (!"baz".equals(STUDENT.find(a("b")))) {
-            return 0;
-        }
-        MockNode expected = new MockNode("foo")
-                .branch('b', new MockNode("baz"));
-        return equals(expected, getField(STUDENT, "root")) ? 1 : 0;
-    }
-
-    /**
-     * Tests that just working with empty strings does the correct thing.
-     */
-    public static int testDeletingEmptyString() {
-        STUDENT.insert(a(""), "Foo");
-        if (!"Foo".equals(STUDENT.find(a(""))) || STUDENT.size() != 1 || STUDENT.isEmpty()) {
-            return 0;
-        }
-
-        STUDENT.delete(a(""));
-
-        if (STUDENT.find(a("")) != null || STUDENT.size() > 0 && !STUDENT.isEmpty()) {
-            return 0;
+    @Test(timeout = 3000)
+    public void testDeletingCausesError() {
+        STUDENT.insert(a("foo"), "doo");
+        try {
+            STUDENT.delete(a("foo"));
+            assertTrue(false);
+        } catch (UnsupportedOperationException ex) {
+            // do nothing, should throw exception
         }
-
-        STUDENT.insert(a(""), "Bar");
-        return "Bar".equals(STUDENT.find(a(""))) && STUDENT.size() == 1 && !STUDENT.isEmpty() ? 1 : 0;
     }
 
-    public static int testDeletingNullEntriesCausesError() {
+    @Test(timeout = 3000)
+    public void testClearCausesError() {
+        STUDENT.insert(a("foo"), "doo");
         try {
-            STUDENT.delete((AlphabeticString) null);
-        } catch (IllegalArgumentException ex) {
-            return 1;
+            STUDENT.clear();
+            assertTrue(false);
+        } catch (UnsupportedOperationException ex) {
+            // do nothing, should throw exception
         }
-        return 0;
-    }
-
-    public static int testClear() {
-        addAll(STUDENT, "keyboard", "keyesian", "bayesian");
-        STUDENT.clear();
-
-        return (STUDENT.size() == 0 &&
-                STUDENT.isEmpty() &&
-                doesNotContainAll(STUDENT, "keyboard", "keyesian", "bayesian")) ? 1 : 0;
     }
 
-    public static int checkUnderlyingStructure() {
+    @Test(timeout = 3000)
+    public void checkUnderlyingStructure() {
         STUDENT.insert(a(""), "A");
         STUDENT.insert(a("foo"), "B");
         STUDENT.insert(a("fez"), "C");
@@ -324,80 +132,19 @@ public class HashTrieMapTests extends TestsUtility {
         STUDENT.insert(a("jazzy"), "F");
 
         MockNode fullExpected = node("A")
-            .branch('f', node()
-                .branch('o', node()
-                    .branch('o', node("B")))
-                .branch('e', node()
-                    .branch('z', node("C")
-                        .branch('z', node()
-                            .branch('y', node("D"))))))
-            .branch('j', node()
-                .branch('a', node()
-                    .branch('z', node()
-                        .branch('z', node("E")
-                            .branch('y', node("F"))))));
-
-        if (!equals(fullExpected, getField(STUDENT, "root"))) {
-            return 0;
-        }
-
-        STUDENT.delete(a("fezzy"));
-        STUDENT.delete(a("jazz"));
-
-        MockNode delete1 = node("A")
-            .branch('f', node()
-                .branch('o', node()
-                    .branch('o', node("B")))
-                .branch('e', node()
-                    .branch('z', node("C"))))
-            .branch('j', node()
-                .branch('a', node()
-                    .branch('z', node()
-                        .branch('z', node()
-                            .branch('y', node("F"))))));
-
-        if (!equals(delete1, getField(STUDENT, "root"))) {
-            return 0;
-        }
-
-        STUDENT.delete(a(""));
-        STUDENT.delete(a("foo"));
-        STUDENT.delete(a("jazz")); // should do nothing
-
-        MockNode delete2 = node()
-            .branch('f', node()
-                .branch('e', node()
-                    .branch('z', node("C"))))
-            .branch('j', node()
-                .branch('a', node()
-                    .branch('z', node()
-                        .branch('z', node()
-                            .branch('y', node("F"))))));
-
-        if (!equals(delete2, getField(STUDENT, "root"))) {
-            return 0;
-        }
-
-        STUDENT.insert(a("f"), "Z");
-        STUDENT.delete(a("jazzy"));
-        STUDENT.delete(a("fez"));
-
-        MockNode delete3 = node().branch('f', node("Z"));
-
-        if (!equals(delete3, getField(STUDENT, "root"))) {
-            return 0;
-        }
-
-        STUDENT.delete(a("f"));
-
-        boolean rootIsSingleNode = equals(node(), getField(STUDENT, "root"));
-        boolean rootIsNull = equals(null, getField(STUDENT, "root"));
-        if (!(rootIsSingleNode || rootIsNull)) {
-            return 0;
-        }
-
-        return 1;
-
+                .branch('f', node()
+                        .branch('o', node()
+                                .branch('o', node("B")))
+                        .branch('e', node()
+                                .branch('z', node("C")
+                                        .branch('z', node()
+                                                .branch('y', node("D"))))))
+                .branch('j', node()
+                        .branch('a', node()
+                                .branch('z', node()
+                                        .branch('z', node("E")
+                                                .branch('y', node("F"))))));
+        assertTrue(equals(fullExpected, getField(STUDENT, "root")));
     }
 
     protected static boolean equals(MockNode expected, HashTrieMap<Character, AlphabeticString, String>.HashTrieNode student) {
@@ -416,14 +163,6 @@ public class HashTrieMapTests extends TestsUtility {
             // If number of pointers is not the same
             return false;
         } else {
-            // If student doesn't contain the given char, 'equals' will fail one level down
-            // in one of the base cases
-            for (char c : expected.pointers.keySet()) {
-                boolean result = equals(expected.pointers.get(c), student.pointers.get(c));
-                if (!result) {
-                    return false;
-                }
-            }
             return true;
         }
     }
@@ -455,7 +194,8 @@ public class HashTrieMapTests extends TestsUtility {
         }
     }
 
-    public static int stressTest() {
+    @Test(timeout = 3000)
+    public void stressTest() {
         // Should contain 30 characters
         char[] symbols = "abcdefghijklmnopqrstuvwxyz!@#$".toCharArray();
         long i = 0;
@@ -473,9 +213,7 @@ public class HashTrieMapTests extends TestsUtility {
 
         for (char a : symbols) {
             for (char b : symbols) {
-                if (!STUDENT.findPrefix(new AlphabeticString(new Character[]{a, b}))) {
-                    return 0;
-                }
+                assertTrue(STUDENT.findPrefix(new AlphabeticString(new Character[]{a, b})));
             }
         }
 
@@ -485,16 +223,12 @@ public class HashTrieMapTests extends TestsUtility {
                 for (char c : symbols) {
                     for (char d : symbols) {
                         Character[] word = new Character[]{a, b, c, d};
-                        if (!STUDENT.find(new AlphabeticString(word)).equals("" + i)) {
-                            return 0;
-                        }
+                        assertTrue(STUDENT.find(new AlphabeticString(word)).equals("" + i));
                         i += 1;
                     }
                 }
             }
         }
-
-        return 1;
     }
 
     /**
@@ -589,4 +323,34 @@ public class HashTrieMapTests extends TestsUtility {
             trie.insert(a(word), word.toUpperCase());
         }
     }
+
+    protected <T> T getField(Object o, String fieldName) {
+        try {
+            Field field = o.getClass().getSuperclass().getDeclaredField(fieldName);
+            field.setAccessible(true);
+            definalize(field);
+            Object f = field.get(o);
+            return (T) f;
+        } catch (Exception var6) {
+            try {
+                Field field = o.getClass().getDeclaredField(fieldName);
+                field.setAccessible(true);
+                definalize(field);
+                Object f = field.get(o);
+                return (T) f;
+            } catch (Exception var5) {
+                return null;
+            }
+        }
+    }
+
+    private void definalize(Field field) {
+        try {
+            Field modifiersField = Field.class.getDeclaredField("modifiers");
+            modifiersField.setAccessible(true);
+            modifiersField.setInt(field, field.getModifiers() & -17);
+        } catch (Exception var2) {
+        }
+
+    }
 }
diff --git a/src/tests/gitlab/ckpt2/HeapSortTests.java b/src/tests/gitlab/ckpt2/HeapSortTests.java
index 1752dfe77f053991397d59882507cf99f5460461..f9f02df3afb86cf8753bc79f0654a457c726be8c 100644
--- a/src/tests/gitlab/ckpt2/HeapSortTests.java
+++ b/src/tests/gitlab/ckpt2/HeapSortTests.java
@@ -1,40 +1,27 @@
 package tests.gitlab.ckpt2;
 
 import p2.sorts.HeapSort;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class HeapSortTests extends TestsUtility {
-	public static void main(String[] args) {
-		new HeapSortTests().run();
-	}
-
-	@Override
-	protected void run() {
-		SHOW_TESTS = true;
-		test("integer_sorted");
-		test("integer_random");
-		finish();
-	}
+public class HeapSortTests {
 
-	public static int integer_sorted() {
+	@Test(timeout = 3000)
+	public void integer_sorted() {
 		Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 		Integer[] arr_sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 		HeapSort.sort(arr, (i1, i2) -> i1.compareTo(i2));
 		for(int i = 0; i < arr.length; i++) {
-			if(!arr[i].equals(arr_sorted[i]))
-				return 0;
+			assertEquals(arr[i], arr_sorted[i]);
 		}
-		return 1;
 	}
-
-	public static int integer_random() {
+	@Test(timeout = 3000)
+	public void integer_random() {
 		Integer[] arr = {3, 1, 4, 5, 9, 2, 6, 7, 8};
 		Integer[] arr_sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9};
 		HeapSort.sort(arr, (i1, i2) -> i1.compareTo(i2));
 		for(int i = 0; i < arr.length; i++) {
-			if(!arr[i].equals(arr_sorted[i]))
-				return 0;
+			assertEquals(arr[i], arr_sorted[i]);
 		}
-		return 1;
 	}
 }
diff --git a/src/tests/gitlab/ckpt2/QuickSortTests.java b/src/tests/gitlab/ckpt2/QuickSortTests.java
index d41bb85c10f74337075c35f9b4426dfc5d5830dd..7eea2c4e6a8f21ddb581c1baf27d1f45d8bd85e6 100644
--- a/src/tests/gitlab/ckpt2/QuickSortTests.java
+++ b/src/tests/gitlab/ckpt2/QuickSortTests.java
@@ -3,22 +3,13 @@ package tests.gitlab.ckpt2;
 import java.util.Comparator;
 
 import p2.sorts.QuickSort;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class QuickSortTests extends TestsUtility {
-	public static void main(String[] args) {
-		new QuickSortTests().run();
-	}
-	
-	@Override
-	protected void run() {
-		SHOW_TESTS = true;
-		test("integer_sorted");
-		test("integer_random");
-		finish();
-	}
+public class QuickSortTests {
 
-	public static int integer_sorted() {
+	@Test(timeout = 3000)
+	public void integer_sorted() {
 		Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 		Integer[] arr_sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 		QuickSort.sort(arr, new Comparator<Integer>() {
@@ -28,13 +19,12 @@ public class QuickSortTests extends TestsUtility {
 			}
 		});
 		for(int i = 0; i < arr.length; i++) {
-			if(!arr[i].equals(arr_sorted[i]))
-				return 0;
+			assertEquals(arr[i], arr_sorted[i]);
 		}
-		return 1;
 	}
 
-	public static int integer_random() {
+	@Test(timeout = 3000)
+	public void integer_random() {
 		Integer[] arr = {3, 1, 4, 5, 9, 2, 6, 7, 8};
 		Integer[] arr_sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9};
 		QuickSort.sort(arr, new Comparator<Integer>() {
@@ -44,9 +34,7 @@ public class QuickSortTests extends TestsUtility {
 			}
 		});
 		for(int i = 0; i < arr.length; i++) {
-			if(!arr[i].equals(arr_sorted[i]))
-				return 0;
+			assertEquals(arr[i], arr_sorted[i]);
 		}
-		return 1;
 	}
 }
\ No newline at end of file
diff --git a/src/tests/gitlab/ckpt2/TopKSortTests.java b/src/tests/gitlab/ckpt2/TopKSortTests.java
index 2427a3ad79247e843fc44fb6c2dc37c896d22aea..18b2d6a995d5889875f357db0eee12548393f09f 100644
--- a/src/tests/gitlab/ckpt2/TopKSortTests.java
+++ b/src/tests/gitlab/ckpt2/TopKSortTests.java
@@ -3,22 +3,13 @@ package tests.gitlab.ckpt2;
 import java.util.Comparator;
 
 import p2.sorts.TopKSort;
-import tests.TestsUtility;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-public class TopKSortTests extends TestsUtility {
-	public static void main(String[] args) {
-		new TopKSortTests().run();
-	}
-	
-	@Override
-	protected void run() {
-		SHOW_TESTS = true;
-		test("integer_sorted");
-		test("integer_random");
-		finish();
-	}
+public class TopKSortTests {
 
-	public static int integer_sorted() {
+	@Test(timeout = 3000)
+	public void integer_sorted() {
 		int K = 4;
 		Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 		Integer[] arr_sorted = {7, 8, 9, 10};
@@ -29,13 +20,12 @@ public class TopKSortTests extends TestsUtility {
 			}
 		});
 		for(int i = 0; i < K; i++) {
-			if(!arr[i].equals(arr_sorted[i]))
-				return 0;
+			assertEquals(arr[i], arr_sorted[i]);
 		}
-		return 1;
 	}
 
-	public static int integer_random() {
+	@Test(timeout = 3000)
+	public void integer_random() {
 		int K = 4;
 		Integer[] arr = {3, 1, 4, 5, 9, 2, 6, 7, 8};
 		Integer[] arr_sorted = {6, 7, 8, 9};
@@ -46,9 +36,7 @@ public class TopKSortTests extends TestsUtility {
 			}
 		});
 		for(int i = 0; i < K; i++) {
-			if(!arr[i].equals(arr_sorted[i]))
-				return 0;
+			assertEquals(arr[i], arr_sorted[i]);
 		}
-		return 1;
 	}
 }
\ No newline at end of file