Skip to content

Instantly share code, notes, and snippets.

@alwarren
Last active July 21, 2019 17:46
Show Gist options
  • Save alwarren/7cbadb6ec9d2a39fda63f43f428f9381 to your computer and use it in GitHub Desktop.
Save alwarren/7cbadb6ec9d2a39fda63f43f428f9381 to your computer and use it in GitHub Desktop.
Coursera Algorithms II WordNet Junit5 Test Suite

Coursera Algorithms II WordNet Junit5 Test Suite

Note

  1. This test suite is not exaustive.
  2. It requires removing the org.* restriction from auto import rules if you are using the IntelliJ project included in the course zip file. This is because the Junit5 development team used the based package org.junit.* instead of junit.* in many of the new libraries.
  3. It requires adding Junit5 dependencies.
  4. The test assumes console output for the test is logged (see the IntelliJ Log Options documentation). This is the primary motivation for the WordNetValues class.
  5. The Spy class used to verify API method names can be found at https://git.io/fj2vM
WordNet Test Suite 2019-06-12 11:11 AM
API Tests
Expected methods => PASSED
Corner Case Tests
Null constructor argument throws required exception => PASSED
Digraph is not rooted DAG throws expected exception => PASSED
Null isNoun() argument throws required exeception => PASSED
Null distance() argument throws required exeception => PASSED
A distance() argument that is not a word throws required exeception => PASSED
Null sap() argument throws required exeception => PASSED
An sap() argument that is not a word throws required exeception => PASSED
Functional Tests
WordNet nouns are correct => PASSED
WordNet isNoun() for existing word is true => PASSED
WordNet isNount() for missing word is false => PASSED
WordNet distance() is correct => PASSED
WordNet sap() is correct => PASSED
/**
* 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<String> 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<String> expected = expectedNouns();
List<String> 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<String> expected = expectedMethods();
List<String> actual = actualMethods();
assertEquals(expected, actual);
StdOut.println(WordNetValues.PASSED);
}
private List<String> expectedMethods() {
List<String> expected = Arrays.asList("length", "ancestor", "length", "ancestor");
Collections.sort(expected);
return expected;
}
private List<String> actualMethods() {
return Spy.publicMethodNames(SAP.class)
.stream()
.filter(s -> !s.equals("main"))
.sorted()
.collect(Collectors.toList());
}
}
private List<String> expectedNouns() {
return Arrays.asList("h", "d", "i", "e", "a", "j", "f", "b", "k", "g", "c");
}
private List<String> actualNouns() {
WordNet wordNet = new WordNet("synsets11.txt", "hypernyms11ManyPathsOneAncestor.txt");
List<String> list = new ArrayList<>();
for (String noun : wordNet.nouns())
list.add(noun);
return list;
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Name:
* Date:
* Description: Static values and helper methods for JUnit5 unit tests.
*/
public class WordNetValues {
public static final String PASSED = "PASSED";
public static final String SUITE_TITLE_FORMAT = "\n%s Test Suite " + dateTime() + "\n";
public static final String TEST_CLASS_FORMAT = " %s";
public static final String TEST_FORMAT = " %s => ";
public static final String VERIFY_NULL_CONSTRUCTOR_ARGUMENT_THROWS_EXCEPTION = "Null constructor argument throws required exception";
public static final String VERIFY_API_METHODS = "Expected methods";
public static final String TITLE_API = "API Tests";
public static final String TITLE_CORNER_CASES = "Corner Case Tests";
public static final String TITLE_FUNCTIONAL = "Functional Tests";
public static final String SUITE_TITLE_WORDNET = "WordNet";
public static final String SUITE_TITLE_SAP = "SAP";
public static final String SUITE_TITLE_OUTCAST = "Outcast";
public static final String WORDNET_IS_NOUN_NULL_ARGUMENT_EXCEPTION = "Null isNoun() argument throws required exeception";
public static final String WORDNET_DISTANCE_NULL_ARGUMENT_EXCEPTION = "Null distance() argument throws required exeception";
public static final String WORDNET_SAP_NULL_ARGUMENT_EXCEPTION = "Null sap() argument throws required exeception";
public static final String WORDNET_SAP_ARGUMENT_NOT_A_WORD_EXCEPTION = "An sap() argument that is not a word throws required exeception";
public static final String WORDNET_DISTANCE_ARGUMENT_NOT_A_WORD_EXCEPTION = "A distance() argument that is not a word throws required exeception";
public static final String WORDNET_DIGRAPH_IS_NOT_DAG = "Digraph is not rooted DAG throws expected exception";
public static final String WORDNET_VERIFY_NOUNS = "WordNet nouns are correct";
public static final String WORDNET_VERIFY_NOUNS_CONTAINS_WORD_TRUE = "WordNet isNoun() for existing word is true";
public static final String WORDNET_VERIFY_NOUNS_CONTAINS_WORD_FALSE = "WordNet isNount() for missing word is false";
public static final String WORDNET_VERIFY_DISTANCE = "WordNet distance() is correct";
public static final String WORDNET_VERIFY_SAP = "WordNet sap() is correct";
public static final String SAP_LENGTH_ARGUMENT_EXCEPTION = "Null length() argument throws required exeception";
public static final String SAP_LENGTH_ITERABLE_FIRST_ARGUMENT_HAS_NULL = "Null values in length() first iterable argument throws required exeception";
public static final String SAP_LENGTH_ITERABLE_SECOND_ARGUMENT_HAS_NULL = "Null values in length() second iterable argument throws required exeception";
public static final String SAP_LENGTH_ITERABLE_FIRST_ARGUMENT_VERTEX_ERROR = "Invalid vertex in length() first argument throws required exeception";
public static final String SAP_LENGTH_ITERABLE_SECOND_ARGUMENT_VERTEX_ERROR = "Invalid vertex in length() second argument throws required exeception";
public static final String SAP_ANCESTOR_ARGUMENT_EXCEPTION = "Null ancestor() argument throws required exeception";
public static final String SAP_ANCESTOR_ITERABLE_FIRST_ARGUMENT_EXCEPTION = "Null values in ancestor() first iterable argument throws required exeception";
public static final String SAP_ANCESTOR_ITERABLE_SECOND_ARGUMENT_EXCEPTION = "Null values in ancestor() second iterable argument throws required exeception";
public static final String SAP_ANCESTOR_ITERABLE_FIRST_ARGUMENT_VERTEX_ERROR = "Invalid vertex in ancestor() first argument throws required exeception";
public static final String SAP_ANCESTOR_ITERABLE_SECOND_ARGUMENT_VERTEX_ERROR = "Invalid vertex in ancestor() second argument throws required exeception";
public static final String OUTCAST_NULL_OUTCAST_ARGUMENT = "Null outcast() argument throws required exception";
public static String dateTime() {
String pattern = "yyyy-MM-dd h:mm a";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
return simpleDateFormat.format(new Date());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment