- This test suite is not exaustive.
- 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.
- It requires adding Junit5 dependencies.
- The test assumes console output for the test is logged (see the IntelliJ Log Options documentation). This is the primary motivation for the Values class.
- The Spy class used to verify API method names can be found at https://git.io/fj2vM
Last active
June 17, 2019 05:08
-
-
Save alwarren/ea8fda971fd82c2a384f6294c44bb2e3 to your computer and use it in GitHub Desktop.
Coursera Algorithms II BaseballElimination Junit5 Test Suite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BaseballElimination Test Suite 2019-06-16 11:42 PM | |
API Tests | |
Expected methods => PASSED | |
Corner Case Tests | |
Invalid wins() argument throws expected exception => PASSED | |
Invalid wins() argument throws expected exception => PASSED | |
Invalid remaining() argument throws expected exception => PASSED | |
Invalid against() first argument throws expected exception => PASSED | |
Invalid against() second argument throws expected exception => PASSED | |
Invalid isEliminated() argument throws expected exception => PASSED | |
Invalid certificateOfElimination() argument throws expected exception => PASSED | |
Functional Tests | |
Class BaseballElimination exists => PASSED | |
Method numberOfTeams() is correct => PASSED | |
Method teams() is correct => PASSED | |
Method isEliminated() is correct for teams not eliminated => PASSED | |
Method isEliminated() is correct for teams eliminated => PASSED | |
Method wins() is correct | |
Atlanta = 83 => PASSED | |
Philadelphia = 80 => PASSED | |
New_York = 78 => PASSED | |
Montreal = 77 => PASSED | |
Method losses() is correct | |
Atlanta = 71 => PASSED | |
Philadelphia = 79 => PASSED | |
New_York = 78 => PASSED | |
Montreal = 82 => PASSED | |
Method remaining() is correct | |
Atlanta = 8 => PASSED | |
Philadelphia = 3 => PASSED | |
New_York = 6 => PASSED | |
Montreal = 3 => PASSED | |
Method against() is correct | |
Atlanta vs Philadelphia = 1 => PASSED | |
Atlanta vs New_York = 6 => PASSED | |
Atlanta vs Montreal = 1 => PASSED | |
Philadelphia vs New_York = 0 => PASSED | |
Philadelphia vs Montreal = 2 => PASSED | |
New_York vs Montreal = 0 => PASSED | |
End of Test Suite | |
Passed 31 of 31 tests |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Name: Al Warren | |
* Date: 6/16/2019 | |
* Description: Test suite for an Immutable object type BaseballElimination. | |
* | |
* API Requirements: | |
* | |
* public BaseballElimination(String filename) // create a baseball division from given filename in format specified below | |
* public int numberOfTeams() // number of teams | |
* public Iterable<String> teams() // all teams | |
* public int wins(String team) // number of wins for given team | |
* public int losses(String team) // number of losses for given team | |
* public int remaining(String team) // number of remaining games for given team | |
* public int against(String team1, String team2) // number of remaining games between team1 and team2 | |
* public boolean isEliminated(String team) // is given team eliminated? | |
* public Iterable<String> certificateOfElimination(String team) // subset R of teams that eliminates given team; null if not eliminated | |
* | |
* Corner Caases: | |
* | |
* - The last six methods should throw a java.lang.IllegalArgumentException if one (or both) | |
* of the input arguments are invalid teams. | |
* | |
*/ | |
@DisplayName(Values.SUITE_TITLE_BASEBALL_ELIMINATION) | |
public class BaseballEliminationTest { | |
private static String filename = "teams4.txt"; | |
private String invalidTeam = "invalid team"; | |
private String validTeam = "Atlanta"; | |
private static BaseballElimination division; | |
private static int counter; | |
private static int passed; | |
@BeforeAll | |
static void setup() { | |
division = new BaseballElimination(filename); | |
StdOut.println(String.format(Values.SUITE_TITLE_FORMAT, Values.SUITE_TITLE_BASEBALL_ELIMINATION)); | |
} | |
@AfterEach | |
void beforeEach() { | |
++counter; | |
} | |
@AfterAll | |
static void afterAll() { | |
StdOut.println("End of Test Suite"); | |
StdOut.printf("\nPassed %s of %s tests\n\n", passed, counter); | |
} | |
@Nested | |
@DisplayName(Values.TITLE_FUNCTIONAL) | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) | |
class Functional { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_CLASS_FORMAT, Values.TITLE_FUNCTIONAL)); | |
} | |
@Order(1) | |
@DisplayName(Values.VERIFY_CLASS_EXISTS) | |
@Test void verify_class_exists() { | |
StdOut.printf(Values.TEST_FORMAT, Values.VERIFY_CLASS_EXISTS); | |
new BaseballElimination(filename); | |
showPassed(); | |
} | |
@Order(2) | |
@DisplayName(Values.VERIFY_NUMBER_OF_TEAMS) | |
@Test void verify_number_of_teams() { | |
StdOut.printf(Values.TEST_FORMAT, Values.VERIFY_NUMBER_OF_TEAMS); | |
int expected = 4; | |
int actual = division.numberOfTeams(); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
@Order(3) | |
@DisplayName(Values.VERIFY_TEAMS) | |
@Test void verify_teams() { | |
StdOut.printf(Values.TEST_FORMAT, Values.VERIFY_TEAMS); | |
List<String> expected = expectedTeamNames(); | |
List<String> actual = actualTeamNames(); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
@Order(4) | |
@DisplayName(Values.VERIFY_NOT_ELIMINATED) | |
@Test void verify_not_eliminated() { | |
StdOut.printf(Values.TEST_FORMAT, Values.VERIFY_NOT_ELIMINATED); | |
List<String> expected = expectedNotEliminated(); | |
List<String> actual = actualNotEliminated(); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
@Order(5) | |
@DisplayName(Values.VERIFY_ELIMINATED) | |
@Test void verify_eliminated() { | |
StdOut.printf(Values.TEST_FORMAT, Values.VERIFY_ELIMINATED); | |
Map<String, List<String>> expected = expectedEliminated(); | |
Map<String, List<String>> actual = actualEliminated(); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
@Nested | |
@DisplayName("Against") | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
class TestAgainst { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_TITLE_FORMAT, Values.VERIFY_AGAINST)); | |
} | |
@DisplayName(Values.VERIFY_AGAINST) | |
@ParameterizedTest(name = "{0} & {1} = {2}") | |
@CsvFileSource(resources = "test-against.csv") | |
void verify_against(String team1, String team2, Integer expected) { | |
int actual = division.against(team1, team2); | |
String names = team1 + " vs " + team2; | |
StdOut.print(String.format(Values.TEST_EQUALS_FORMAT, names, actual)); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
} | |
@Nested | |
@DisplayName(Values.VERIFY_REMAINING) | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
class TestRemaining { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_TITLE_FORMAT, Values.VERIFY_REMAINING)); | |
} | |
@Order(4) | |
@DisplayName("Remaining") | |
@ParameterizedTest(name = "{0} = {1}") | |
@CsvFileSource(resources = "test-remaining.csv") | |
void verify_losses(String team, int expected) { | |
int actual = division.remaining(team); | |
StdOut.print(String.format(Values.TEST_EQUALS_FORMAT, team, actual)); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
} | |
@Nested | |
@DisplayName(Values.VERIFY_LOSSES) | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
class TestLosses { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_TITLE_FORMAT, Values.VERIFY_LOSSES)); | |
} | |
@Order(5) | |
@DisplayName("Losses") | |
@ParameterizedTest(name = "{0} = {1}") | |
@CsvFileSource(resources = "test-losses.csv") | |
void verify_losses(String team, int expected) { | |
int actual = division.losses(team); | |
StdOut.print(String.format(Values.TEST_EQUALS_FORMAT, team, actual)); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
} | |
@Nested | |
@DisplayName(Values.VERIFY_WINS) | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
class TestWins { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_TITLE_FORMAT, Values.VERIFY_WINS)); | |
} | |
@Order(6) | |
@DisplayName("Wins") | |
@ParameterizedTest(name = "{0} = {1}") | |
@CsvFileSource(resources = "test-wins.csv") | |
void verify_losses(String team, int expected) { | |
int actual = division.wins(team); | |
StdOut.print(String.format(Values.TEST_EQUALS_FORMAT, team, actual)); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
} | |
} | |
@Nested | |
@DisplayName(Values.TITLE_CORNER_CASES) | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) | |
class CornerCases { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_CLASS_FORMAT, Values.TITLE_CORNER_CASES)); | |
} | |
@Order(1) | |
@DisplayName(Values.INVALID_WINS_ARGUMENT_THROWS_EXCEPTION) | |
@Test | |
void null_wins_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_WINS_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.wins(invalidTeam) | |
); | |
showPassed(); | |
} | |
@Order(2) | |
@DisplayName(Values.INVALID_LOSSES_ARGUMENT_THROWS_EXCEPTION) | |
@Test void null_losses_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_WINS_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.losses(invalidTeam) | |
); | |
showPassed(); | |
} | |
@Order(3) | |
@DisplayName(Values.INVALID_REMAINING_ARGUMENT_THROWS_EXCEPTION) | |
@Test void null_remaining_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_REMAINING_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.remaining(invalidTeam) | |
); | |
showPassed(); | |
} | |
@Order(4) | |
@DisplayName(Values.INVALID_AGAINST_FIRST_ARGUMENT_THROWS_EXCEPTION) | |
@Test void null_against_first_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_AGAINST_FIRST_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.against(invalidTeam, validTeam) | |
); | |
showPassed(); | |
} | |
@Order(5) | |
@DisplayName(Values.INVALID_AGAINST_SECOND_ARGUMENT_THROWS_EXCEPTION) | |
@Test void null_against_second_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_AGAINST_SECOND_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.against(validTeam, invalidTeam) | |
); | |
showPassed(); | |
} | |
@Order(6) | |
@DisplayName(Values.INVALID_IS_ELIMINATED_ARGUMENT_THROWS_EXCEPTION) | |
@Test void null_is_eliminated_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_IS_ELIMINATED_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.isEliminated(invalidTeam) | |
); | |
showPassed(); | |
} | |
@Order(7) | |
@DisplayName(Values.INVALID_ELIM_CERT_ARGUMENT_THROWS_EXCEPTION) | |
@Test void null_certificate_of_elimination_eliminated_argument_throws_expected_exception() { | |
StdOut.printf(Values.TEST_FORMAT, Values.INVALID_ELIM_CERT_ARGUMENT_THROWS_EXCEPTION); | |
assertThrows(IllegalArgumentException.class, () -> | |
division.certificateOfElimination(invalidTeam) | |
); | |
showPassed(); | |
} | |
} | |
@Nested | |
@DisplayName(Values.TITLE_API) | |
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | |
class Api { | |
@BeforeAll | |
void setup() { | |
StdOut.println(String.format(Values.TEST_CLASS_FORMAT, Values.TITLE_API)); | |
} | |
@DisplayName(Values.VERIFY_API_METHODS) | |
@Test | |
void verify_api_methods() { | |
StdOut.printf(Values.TEST_FORMAT, Values.VERIFY_API_METHODS); | |
List<String> expected = expectedMethods(); | |
List<String> actual = actualMethods(); | |
assertEquals(expected, actual); | |
showPassed(); | |
} | |
} | |
private void showPassed() { | |
passed++; | |
StdOut.println(Values.PASSED); | |
} | |
private List<String> expectedMethods() { | |
List<String> expected = Arrays.asList("numberOfTeams", "teams", "wins", "losses", | |
"remaining", "against", "isEliminated", | |
"certificateOfElimination"); | |
Collections.sort(expected); | |
return expected; | |
} | |
private List<String> actualMethods() { | |
return Spy.publicMethodNames(BaseballElimination.class) | |
.stream() | |
.filter(s -> !s.equals("main")) | |
.sorted() | |
.collect(Collectors.toList()); | |
} | |
private List<String> expectedTeamNames() { | |
List<String> expected = Arrays.asList("Atlanta", "Philadelphia", "New_York", "Montreal"); | |
Collections.sort(expected); | |
return expected; | |
} | |
private List<String> actualTeamNames() { | |
List<String> actual = new ArrayList<>(); | |
for (String team : division.teams()) | |
actual.add(team); | |
return actual.stream() | |
.sorted() | |
.collect(Collectors.toList()); | |
} | |
private List<String> expectedNotEliminated() { | |
return Arrays.asList("Atlanta", "New_York"); | |
} | |
private List<String> actualNotEliminated() { | |
List<String> actual = new ArrayList<>(); | |
for (String team : division.teams()) { | |
if (!division.isEliminated(team)) | |
actual.add(team); | |
} | |
return actual; | |
} | |
private Map<String, List<String>> actualEliminated() { | |
Map<String, List<String>> actual = new HashMap<>(); | |
for (String team : division.teams()) { | |
if (division.isEliminated(team)) { | |
List<String> opponents = new ArrayList<>(); | |
for (String certificate : division.certificateOfElimination(team)) { | |
opponents.add(certificate); | |
} | |
actual.put(team, opponents); | |
} | |
} | |
return actual; | |
} | |
private Map<String, List<String>> expectedEliminated() { | |
Map<String, List<String>> expected = new HashMap<>(); | |
expected.put("Montreal", Collections.singletonList("Atlanta")); | |
expected.put("Philadelphia", Arrays.asList("Atlanta", "New_York")); | |
return expected; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
/** | |
* Name: | |
* Date: | |
* Description: Static values and helper methods for JUnit5 unit tests. | |
*/ | |
public class Values { | |
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_TITLE_FORMAT = " %s\n"; | |
public static final String TEST_EQUALS_FORMAT = " %s = %s => "; | |
public static final String TEST_FORMAT = " %s => "; | |
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_BASEBALL_ELIMINATION = "BaseballElimination"; | |
public static final String INVALID_WINS_ARGUMENT_THROWS_EXCEPTION = "Invalid wins() argument throws expected exception"; | |
public static final String INVALID_LOSSES_ARGUMENT_THROWS_EXCEPTION = "Invalid losses() argument throws expected exception"; | |
public static final String INVALID_REMAINING_ARGUMENT_THROWS_EXCEPTION = "Invalid remaining() argument throws expected exception"; | |
public static final String INVALID_AGAINST_FIRST_ARGUMENT_THROWS_EXCEPTION = "Invalid against() first argument throws expected exception"; | |
public static final String INVALID_AGAINST_SECOND_ARGUMENT_THROWS_EXCEPTION = "Invalid against() second argument throws expected exception"; | |
public static final String INVALID_IS_ELIMINATED_ARGUMENT_THROWS_EXCEPTION = "Invalid isEliminated() argument throws expected exception"; | |
public static final String INVALID_ELIM_CERT_ARGUMENT_THROWS_EXCEPTION = "Invalid certificateOfElimination() argument throws expected exception"; | |
public static final String VERIFY_API_METHODS = "Expected methods"; | |
public static final String VERIFY_CLASS_EXISTS = "Class BaseballElimination exists"; | |
public static final String VERIFY_NUMBER_OF_TEAMS = "Method numberOfTeams() is correct"; | |
public static final String VERIFY_TEAMS = "Method teams() is correct"; | |
public static final String VERIFY_WINS = "Method wins() is correct"; | |
public static final String VERIFY_LOSSES = "Method losses() is correct"; | |
public static final String VERIFY_REMAINING = "Method remaining() is correct"; | |
public static final String VERIFY_AGAINST = "Method against() is correct"; | |
public static final String VERIFY_NOT_ELIMINATED = "Method isEliminated() is correct for teams not eliminated"; | |
public static final String VERIFY_ELIMINATED = "Method isEliminated() is correct for teams eliminated"; | |
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