Skip to content

Instantly share code, notes, and snippets.

@alwarren
Last active June 17, 2019 05:08
Show Gist options
  • Save alwarren/ea8fda971fd82c2a384f6294c44bb2e3 to your computer and use it in GitHub Desktop.
Save alwarren/ea8fda971fd82c2a384f6294c44bb2e3 to your computer and use it in GitHub Desktop.
Coursera Algorithms II BaseballElimination Junit5 Test Suite

Coursera Algorithms II BaseballElimination 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 Values class.
  5. The Spy class used to verify API method names can be found at https://git.io/fj2vM
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
/**
* 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;
}
}
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