Mam nadzieję, że czytałeś mój poprzedni post. Jeśli nie warto zrobić to wczesniej ponieważ kod, który dzisiaj napiszemy będzie bardziej zrozumiały dla Ciebie.
Artykuł dostępny także w wersji angielskiej.
Testy dla metryki HTM
Zacznijmy więc od metryki HTM, która jest bardzo prostą metryką.
Pierwszy z naszych testów sprawdza czy nazwa metryki jest poprawna:
1 2 3 4 5 6 7 8 9 |
public class HTMMetricGetNameTest { @Test public void testGetName() { HTMMetric htmMetric = new HTMMetric(); assertEquals("HTM", htmMetric.getMetricName()); } } |
Drugi z testów sprawdza czy wartość dla określonych ruchów jest poprawna:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
@RunWith(Parameterized.class) public class HTMMetricGetValueForMoveTest { private final Integer expectedValueForMove; private final Move move; public HTMMetricGetValueForMoveTest(Integer expectedValueForMove, Move move) { this.expectedValueForMove = expectedValueForMove; this.move = move; } /** * Test of getValuesForMoves method, of class qtmmetric. */ @Test public void testGetValuesForMoves() { HTMMetric htmMetric = new HTMMetric(); assertEquals(this.expectedValueForMove, htmMetric.getValueForMove(this.move)); } @Parameterized.Parameters public static Collection moves() { return Arrays.asList(new Object[][]{ { 1, Move.MOVE_R }, { 1, Move.MOVE_R2 }, { 1, Move.MOVE_R3 }, { 1, Move.MOVE_U }, { 1, Move.MOVE_U2 }, { 1, Move.MOVE_U3 } }); } } |
I ostatni z testów, który sprawdza czy scramble zawierający określone ruchy ma poprawną długość:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
@RunWith(Parameterized.class) public class HTMMetricCountTest { private final Integer expectedMovesCounter; private final Move[] moves; public HTMMetricCountTest(Integer expectedMovesCounter, Move[] moves) { this.expectedMovesCounter = expectedMovesCounter; this.moves = moves; } /** * Test of getValuesForMoves method, of class qtmmetric. */ @Test public void testGetValuesForMoves() { Scramble scramble = new Scramble(); for (Move move : this.moves) { scramble.addMove(move); } HTMMetric qtmMetric = new HTMMetric(); assertEquals("HTM(" + this.expectedMovesCounter + ")", qtmMetric.count(scramble)); } @Parameterized.Parameters public static Collection moves() { return Arrays.asList(new Object[][]{ { 0, new Move[]{} }, { 3, new Move[]{ Move.MOVE_R, Move.MOVE_R2, Move.MOVE_R3 } }, { 3, new Move[]{ Move.MOVE_R, Move.MOVE_L, Move.MOVE_D } }, { 3, new Move[]{ Move.MOVE_R2, Move.MOVE_L2, Move.MOVE_D2 } }, { 3, new Move[]{ Move.MOVE_R3, Move.MOVE_L3, Move.MOVE_D3 } }, { 18, new Move[]{ Move.MOVE_R, Move.MOVE_U, Move.MOVE_F, Move.MOVE_L, Move.MOVE_D, Move.MOVE_B, Move.MOVE_R2, Move.MOVE_U2, Move.MOVE_F2, Move.MOVE_L2, Move.MOVE_D2, Move.MOVE_B2, Move.MOVE_R3, Move.MOVE_U3, Move.MOVE_F3, Move.MOVE_L3, Move.MOVE_D3, Move.MOVE_B3, } } }); } } |
Testy dla metryki QTM
Naszym następnym celem jest napisanie testu dla metryki QTM. Pokazuję je poniżej.
Pierwszy z nich sprawdza czy metryka ma poprawną nazwę:
1 2 3 4 5 6 7 8 9 |
public class QTMMetricGetNameTest { @Test public void testGetName() { QTMMetric htmMetric = new QTMMetric(); assertEquals("QTM", htmMetric.getMetricName()); } } |
Drugi test sprawdza czy dla podanych ruchów zwracana jest poprawna wartość:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
@RunWith(Parameterized.class) public class QTMMetricGetValueForMoveTest { private final Integer expectedValueForMove; private final Move move; public QTMMetricGetValueForMoveTest(Integer expectedValueForMove, Move move) { this.expectedValueForMove = expectedValueForMove; this.move = move; } /** * Test of getValuesForMoves method, of class qtmmetric. */ @Test public void testGetValuesForMoves() { QTMMetric qtmMetric = new QTMMetric(); assertEquals(this.expectedValueForMove, qtmMetric.getValueForMove(this.move)); } @Parameterized.Parameters public static Collection moves() { return Arrays.asList(new Object[][]{ { 1, Move.MOVE_R }, { 2, Move.MOVE_R2 }, { 1, Move.MOVE_R3 }, { 1, Move.MOVE_U }, { 2, Move.MOVE_U2 }, { 1, Move.MOVE_U3 } }); } } |
I ostatni który sprawdza czy długość scrambla jest poprawna:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
@RunWith(Parameterized.class) public class QTMMetricCountTest { private final Integer expectedMovesCounter; private final Move[] moves; public QTMMetricCountTest(Integer expectedMovesCounter, Move[] moves) { this.expectedMovesCounter = expectedMovesCounter; this.moves = moves; } /** * Test of getValuesForMoves method, of class qtmmetric. */ @Test public void testGetValuesForMoves() { Scramble scramble = new Scramble(); for (Move move : this.moves) { scramble.addMove(move); } QTMMetric qtmMetric = new QTMMetric(); assertEquals("QTM(" + this.expectedMovesCounter + ")", qtmMetric.count(scramble)); } @Parameterized.Parameters public static Collection moves() { return Arrays.asList(new Object[][]{ { 0, new Move[]{} }, { 4, new Move[]{ Move.MOVE_R, Move.MOVE_R2, Move.MOVE_R3 } }, { 3, new Move[]{ Move.MOVE_R, Move.MOVE_L, Move.MOVE_D } }, { 6, new Move[]{ Move.MOVE_R2, Move.MOVE_L2, Move.MOVE_D2 } }, { 3, new Move[]{ Move.MOVE_R3, Move.MOVE_L3, Move.MOVE_D3 } }, { 24, new Move[]{ Move.MOVE_R, Move.MOVE_U, Move.MOVE_F, Move.MOVE_L, Move.MOVE_D, Move.MOVE_B, Move.MOVE_R2, Move.MOVE_U2, Move.MOVE_F2, Move.MOVE_L2, Move.MOVE_D2, Move.MOVE_B2, Move.MOVE_R3, Move.MOVE_U3, Move.MOVE_F3, Move.MOVE_L3, Move.MOVE_D3, Move.MOVE_B3, } } }); } } |
Implementacja klas metryk
Teraz pozostało tylko napisanie klas odpowiedzialnych za obliczanie długości naszych scrambli:
Oto klasa dla metryki HTM:
1 2 3 4 5 6 7 8 9 10 11 12 |
public class HTMMetric extends AbstractMetric { @Override protected Integer getValueForMove(Move move) { return 1; } @Override protected String getMetricName() { return "HTM"; } } |
Klasa dla metryki QTM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class QTMMetric extends AbstractMetric { @Override protected Integer getValueForMove(Move move) { if (move.getMove().endsWith("2")) { return 2; } return 1; } @Override protected String getMetricName() { return "QTM"; } } |
Dodatkowo, stworzyłem abstrakcyjną klasę, która posiada wydzielony kod, wspólny dla obu klas metryk. Oczywiście moje testy pomogły mi wykonać tę refaktoryzację bez zbędnego bólu.
Oto ta klasa:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
abstract public class AbstractMetric { /** * @param move * @return Integer */ abstract protected Integer getValueForMove(Move move); /** * @return String */ abstract protected String getMetricName(); /** * @param scramble * @return String */ public String count(Scramble scramble) { Integer counter = 0; for (int i = 0; i < scramble.getLength(); i++) { Move move = scramble.getMove(i); counter += this.getValueForMove(move); } return this.getMetricName() + "(" + counter + ")"; } } |
Teraz jeśli uruchomimy nasze testy, wszystkie z nich powinny przejść.
Moje zmiany możesz podejrzeć tutaj. Możesz oczywiście także ściągnąć cały mój projekt jeśli Ci się on podoba.
Co dalej
W następnym wpisie odnośnie rozwijania mojego projektu zacznę tworzyć klasę odpowiedzialną za kostkę i ruchy na niej.