/** * Name: Al Warren * Date: 6/3/2019 * Description: Test suite for an Immutable object type WordNet. * * API Requirements: * * public class WordNet { * * // constructor takes the name of the two input files * public WordNet(String synsets, String hypernyms) * * // returns all WordNet nouns * public Iterable nouns() * * // is the word a WordNet noun? * public boolean isNoun(String word) * * // distance between nounA and nounB (defined below) * public int distance(String nounA, String nounB) * * // a synset (second field of synsets.txt) that is the common ancestor of nounA and nounB * // in a shortest ancestral path (defined below) * public String sap(String nounA, String nounB) * * // do unit testing of this class * public static void main(String[] args) * } * } * * Corner Caases: * * Throw a java.lang.IllegalArgumentException in the following situations: * - Any argument to the constructor or an instance method is null * - The input to the constructor does not correspond to a rooted DAG. * - Any of the noun arguments in distance() or sap() is not a WordNet noun. * */ @DisplayName(WordNetValues.SUITE_TITLE_WORDNET) public class WordNetTest { private static String synsets = "synsets11.txt"; private static String hypernyms = "hypernyms11ManyPathsOneAncestor.txt"; private static String synsets_not_dag = "synsets6.txt"; private static String hypernyms_not_dag = "hypernyms6InvalidTwoRoots.txt"; private static WordNet wordNet; @BeforeAll static void setup() { wordNet = new WordNet(synsets, hypernyms); StdOut.println(String.format(WordNetValues.SUITE_TITLE_FORMAT, WordNetValues.SUITE_TITLE_WORDNET)); } @Nested @DisplayName(WordNetValues.TITLE_FUNCTIONAL) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class Functional { @BeforeAll void setup() { StdOut.println(String.format(WordNetValues.TEST_CLASS_FORMAT, WordNetValues.TITLE_FUNCTIONAL)); } @Order(1) @DisplayName(WordNetValues.WORDNET_VERIFY_NOUNS) @Test void verify_nouns() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_VERIFY_NOUNS); List expected = expectedNouns(); List actual = actualNouns(); assertEquals(expected, actual); StdOut.println(WordNetValues.PASSED); } @Order(2) @DisplayName(WordNetValues.WORDNET_VERIFY_NOUNS_CONTAINS_WORD_TRUE) @Test void verify_nouns_contains_word_true() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_VERIFY_NOUNS_CONTAINS_WORD_TRUE); String word = expectedNouns().get(0); assertTrue(wordNet.isNoun(word)); StdOut.println(WordNetValues.PASSED); } @Order(3) @DisplayName(WordNetValues.WORDNET_VERIFY_NOUNS_CONTAINS_WORD_FALSE) @Test void verify_nouns_contains_word_false() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_VERIFY_NOUNS_CONTAINS_WORD_FALSE); String word = expectedNouns().get(0) + "missing"; assertFalse(wordNet.isNoun(word)); StdOut.println(WordNetValues.PASSED); } @Order(4) @DisplayName(WordNetValues.WORDNET_VERIFY_DISTANCE) @Test void verify_distance() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_VERIFY_DISTANCE); testDistance(); StdOut.println(WordNetValues.PASSED); } @Order(5) @DisplayName(WordNetValues.WORDNET_VERIFY_SAP) @Test void verify_sap() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_VERIFY_SAP); testSap(); StdOut.println(WordNetValues.PASSED); } private void testSap() { String[] letters = {"a","b","c","d","e","f","g","h","i","j","k"}; String[] expected = {"a","b","c","d","e","f","f","f","f","f","f"}; for (int i = 0; i < letters.length; i++) { assertEquals(expected[i], wordNet.sap("a", letters[i])); } } private void testDistance() { String[] letters = {"a","b","c","d","e","f","g","h","i","j","k"}; int[] expected = {0,1,1,1,1,2,3,3,3,3,4}; for (int i = 0; i < letters.length; i++) { assertEquals(expected[i], wordNet.distance("a", letters[i])); } } } @Nested @DisplayName(WordNetValues.TITLE_CORNER_CASES) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class CornerCases { @BeforeAll void setup() { StdOut.println(String.format(WordNetValues.TEST_CLASS_FORMAT, WordNetValues.TITLE_CORNER_CASES)); } @Order(1) @DisplayName(WordNetValues.VERIFY_NULL_CONSTRUCTOR_ARGUMENT_THROWS_EXCEPTION) @Test void throw_exception_on_null_constructor_argument() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.VERIFY_NULL_CONSTRUCTOR_ARGUMENT_THROWS_EXCEPTION); assertThrows(IllegalArgumentException.class, () -> { new WordNet(null, hypernyms); new WordNet(synsets, null); new WordNet(null, null); }); StdOut.println(WordNetValues.PASSED); } @Order(2) @DisplayName(WordNetValues.WORDNET_DIGRAPH_IS_NOT_DAG) @Test void thow_execption_ondigraph_is_not_dag() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_DIGRAPH_IS_NOT_DAG); assertThrows(IllegalArgumentException.class, () -> new WordNet(synsets_not_dag, hypernyms_not_dag) ); StdOut.println(WordNetValues.PASSED); } @Order(3) @DisplayName(WordNetValues.WORDNET_IS_NOUN_NULL_ARGUMENT_EXCEPTION) @Test void throw_exception_on_is_noun_null_argument() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_IS_NOUN_NULL_ARGUMENT_EXCEPTION); assertThrows(IllegalArgumentException.class, () -> wordNet.isNoun(null) ); StdOut.println(WordNetValues.PASSED); } @Order(4) @DisplayName(WordNetValues.WORDNET_DISTANCE_NULL_ARGUMENT_EXCEPTION) @Test void throw_exception_on_distance_null_argument() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_DISTANCE_NULL_ARGUMENT_EXCEPTION); assertThrows(IllegalArgumentException.class, () -> { wordNet.distance("", null); wordNet.distance(null, ""); wordNet.distance(null, null); }); StdOut.println(WordNetValues.PASSED); } @Order(5) @DisplayName(WordNetValues.WORDNET_DISTANCE_ARGUMENT_NOT_A_WORD_EXCEPTION) @Test void throw_exception_on_distance_argument_not_a_word() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_DISTANCE_ARGUMENT_NOT_A_WORD_EXCEPTION); assertThrows(IllegalArgumentException.class, () -> { String word = expectedNouns().get(0); String missingWord = word + "missing"; wordNet.distance(word, missingWord); wordNet.distance(missingWord, word); }); StdOut.println(WordNetValues.PASSED); } @Order(6) @DisplayName(WordNetValues.WORDNET_SAP_NULL_ARGUMENT_EXCEPTION) @Test void throw_exception_on_sap_null_argument() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_SAP_NULL_ARGUMENT_EXCEPTION); assertThrows(IllegalArgumentException.class, () -> { wordNet.sap("", null); wordNet.sap(null, ""); wordNet.sap(null, null); }); StdOut.println(WordNetValues.PASSED); } @Order(7) @DisplayName(WordNetValues.WORDNET_SAP_ARGUMENT_NOT_A_WORD_EXCEPTION) @Test void throw_exception_on_sap_argument_not_a_word() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.WORDNET_SAP_ARGUMENT_NOT_A_WORD_EXCEPTION); assertThrows(IllegalArgumentException.class, () -> { String word = expectedNouns().get(0); String missingWord = word + "missing"; wordNet.sap(word, missingWord); wordNet.sap(missingWord, word); }); StdOut.println(WordNetValues.PASSED); } } @Nested @DisplayName(WordNetValues.TITLE_API) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class Api { @BeforeAll void setup() { StdOut.println(String.format(WordNetValues.TEST_CLASS_FORMAT, WordNetValues.TITLE_API)); } @DisplayName(WordNetValues.VERIFY_API_METHODS) @Test void verify_api_methods() { StdOut.printf(WordNetValues.TEST_FORMAT, WordNetValues.VERIFY_API_METHODS); List expected = expectedMethods(); List actual = actualMethods(); assertEquals(expected, actual); StdOut.println(WordNetValues.PASSED); } private List expectedMethods() { List expected = Arrays.asList("length", "ancestor", "length", "ancestor"); Collections.sort(expected); return expected; } private List actualMethods() { return Spy.publicMethodNames(SAP.class) .stream() .filter(s -> !s.equals("main")) .sorted() .collect(Collectors.toList()); } } private List expectedNouns() { return Arrays.asList("h", "d", "i", "e", "a", "j", "f", "b", "k", "g", "c"); } private List actualNouns() { WordNet wordNet = new WordNet("synsets11.txt", "hypernyms11ManyPathsOneAncestor.txt"); List list = new ArrayList<>(); for (String noun : wordNet.nouns()) list.add(noun); return list; } }