1 package de.juplo.kafka.wordcount.top10;
3 import org.junit.jupiter.api.DisplayName;
4 import org.junit.jupiter.api.Test;
5 import org.junit.jupiter.params.ParameterizedTest;
6 import org.junit.jupiter.params.provider.MethodSource;
7 import org.junit.jupiter.params.provider.ValueSource;
9 import java.util.LinkedList;
10 import java.util.List;
11 import java.util.stream.Stream;
13 import static org.assertj.core.api.Assertions.assertThat;
14 import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
17 public class RankingTest
19 @DisplayName("A newly created instance is empty")
21 public void testNewRankingIsEmpty()
23 Ranking ranking = new Ranking();
24 assertThat(ranking.getEntries()).isEmpty();
27 @DisplayName("An instance that was build from an empty ranking is empty")
29 public void testRankingOfYieldsExpectedResultForEmptyList()
31 Ranking ranking = new Ranking();
32 assertThat(ranking.getEntries()).isEmpty();
35 @DisplayName("An instance that was build from a valid ranking contains the expected entries")
37 @MethodSource("validRankingsProvider")
38 public void testRankingOfYieldsExpectedResultsForValidRankings(List<Entry> entryList)
40 Ranking ranking = Ranking.of(toArray(entryList));
41 assertThat(ranking.getEntries()).containsExactlyElementsOf(entryList);
44 @DisplayName("The builder fails for invalid rankings")
46 @MethodSource("invalidRankingsProvider")
47 public void testRankingOfThrowsExceptionForInvalidRankings(List<Entry> entryList)
49 assertThatExceptionOfType(IllegalArgumentException.class)
50 .isThrownBy(() -> Ranking.of(toArray(entryList)));
53 @DisplayName("Adding a new word with highest ranking, pushes all other words down")
55 @MethodSource("validRankingsProvider")
56 public void testAddingNewWordWithHighestRanking(List<Entry> entryList)
58 Ranking ranking = Ranking.of(toArray(entryList));
59 Entry newEntry = Entry.of("NEW!", rankingForPosition(-1));
60 ranking.add(newEntry);
61 assertThat(ranking.getEntries()[0]).isEqualTo(newEntry);
62 for (int i = 0; i < entryList.size() && i < Ranking.MAX_ENTRIES - 1; i++)
64 assertThat(ranking.getEntries()[i + 1]).isEqualTo(entryList.get(i));
68 @DisplayName("Adding a new word with an existent ranking, pushes all words with lower ranking down")
70 @MethodSource("validRankingsProvider")
71 public void testAddingNewWordWithExistingRanking(List<Entry> entryList)
73 for (int position = 0; position < entryList.size(); position++ )
75 Ranking ranking = Ranking.of(toArray(entryList));
76 Entry newEntry = Entry.of("NEW!", rankingForPosition(position));
77 ranking.add(newEntry);
78 for (int i = 0; i < entryList.size() && i < Ranking.MAX_ENTRIES - 1; i++)
82 assertThat(ranking.getEntries()[i]).isEqualTo(entryList.get(i));
86 assertThat(ranking.getEntries()[i]).isEqualTo(entryList.get(i));
87 assertThat(ranking.getEntries()[i + 1]).isEqualTo(newEntry);
91 assertThat(ranking.getEntries()[i + 1]).isEqualTo(entryList.get(i));
97 @DisplayName("Adding a highest ranking for an existing word shifts it to the first place")
99 @ValueSource(ints = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })
100 public void testAddingExistingWordWithHighestRanking(int position)
102 Ranking ranking = Ranking.of(toArray(VALID_RANKINGS[0]));
103 String word = wordForPosition(position);
104 Entry highestEntry = Entry.of(word, 100l);
105 ranking.add(highestEntry);
106 List<Entry> expectedEntries = Stream
108 Stream.of(highestEntry),
111 .filter(entry -> !entry.getWord().equals(word)))
113 assertThat(ranking.getEntries()).containsExactlyElementsOf(expectedEntries);
116 @DisplayName("Adding an existing word with unchanged ranking changes nothing")
118 @ValueSource(ints = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })
119 public void testAddingExistingWordWithUnchangedRanking(int position)
121 Ranking ranking = Ranking.of(toArray(VALID_RANKINGS[0]));
122 Entry unchangedEntry = Entry.of(
123 wordForPosition(position),
124 rankingForPosition(position));
125 ranking.add(unchangedEntry);
126 assertThat(ranking.getEntries()).containsExactlyElementsOf(VALID_RANKINGS[0]);
129 @DisplayName("Adding an existing word with a lower ranking fails")
131 @MethodSource("validRankingsProvider")
132 public void testAddingExistingWordWithLowerRankingFails(List<Entry> entryList)
134 Ranking ranking = Ranking.of(toArray(entryList));
135 entryList.forEach(entry ->
136 assertThatExceptionOfType(IllegalArgumentException.class)
137 .isThrownBy(() -> ranking.add(Entry.of(entry.getWord(), entry.getCounter() - 1))));
140 @DisplayName("Identical rankings are considered equal")
142 @MethodSource("validRankingsProvider")
143 public void testIdenticalRankingsAreConsideredEaqual(List<Entry> entryList)
145 assertThat(Ranking.of(toArray(entryList))).isEqualTo(Ranking.of(toArray(entryList)));
148 @DisplayName("Two empty rankings are considered equal")
150 public void testTwoEmptyRankingsAreConsideredEaqual()
152 assertThat(Ranking.of()).isEqualTo(Ranking.of());
155 @DisplayName("A changed ranking is not considered equal to its unchanged counter-part")
157 @MethodSource("validRankingsProvider")
158 public void testChangedRankingsDoNotEaqualUnchangedOne(List<Entry> entryList)
160 Ranking changed = Ranking.of(toArray(entryList));
161 changed.add(Entry.of("devilish", 666l));
162 assertThat(changed).isNotEqualTo(Ranking.of(toArray(entryList)));
165 @DisplayName("Rankigs are considered equal, if only the order of words with the same count differ")
167 public void testRankingWithDifferentOrderForSameCountAreEqual()
177 .isEqualTo(Ranking.of(
183 Entry.of("c1", 8l)));
187 Entry[] toArray(List<Entry> entryList)
189 return entryList.toArray(size -> new Entry[size]);
192 static String wordForPosition(int position)
194 return Integer.toString(position+1);
197 static long rankingForPosition(int position)
199 return (long)Ranking.MAX_ENTRIES * 2 - position;
202 static Stream<List<Entry>> validRankingsProvider()
204 return Stream.of(VALID_RANKINGS);
207 static Stream<List<Entry>> invalidRankingsProvider()
209 return Stream.of(INVALID_RANKINGS);
212 static String[] WORDS = new String[Ranking.MAX_ENTRIES];
213 static List<Entry>[] VALID_RANKINGS = new List[Ranking.MAX_ENTRIES];
217 for (int i = 0; i < Ranking.MAX_ENTRIES; i++)
219 List<Entry> ranking = new LinkedList<>();
221 for (int position = 0; position <= i; position++)
223 word = wordForPosition(position);
224 Entry entry = Entry.of(word, rankingForPosition(position));
228 VALID_RANKINGS[Ranking.MAX_ENTRIES - (i + 1)] = ranking;
232 static List<Entry>[] INVALID_RANKINGS = new List[] {
234 Entry.of("Platz eins", 1l),
235 Entry.of("Platz zwei", 2l)),
237 Entry.of("Platz eins", 1111111111l),
238 Entry.of("Platz zwei", 222222222l),
239 Entry.of("Platz eins", 1l)),
241 Entry.of("Platz eins", 11l),
242 Entry.of("Platz eins", 1l)),
244 Entry.of("Platz eins", 1111111111l),
245 Entry.of("Platz zwei", 222222222l),
246 Entry.of("Platz eins", 11111111l),
247 Entry.of("Platz zwei", 2222222l),
248 Entry.of("Platz fünf", 555555l)),
250 Entry.of("Platz eins", 1111111111l),
251 Entry.of("Platz zwei", 222222222l),
252 Entry.of("Platz drei", 33333333l),
253 Entry.of("Platz vier", 4444444l),
254 Entry.of("Platz eins", 111111l),
255 Entry.of("Platz sechs", 66666l)),
257 Entry.of("Platz eins", 1111111111l),
258 Entry.of("Platz zwei", 222222222l),
259 Entry.of("Platz drei", 33333333l),
260 Entry.of("Platz vier", 4444444l),
261 Entry.of("Platz fünf", 555555l),
262 Entry.of("Platz sechs", 66666l),
263 Entry.of("Platz eins", 1l)),
265 Entry.of("Platz eins", 1111111111l),
266 Entry.of("Platz zwei", 222222222l),
267 Entry.of("Platz drei", 33333333l),
268 Entry.of("Platz vier", 4444444l),
269 Entry.of("Platz fünf", 555555l),
270 Entry.of("Platz sechs", 66666l),
271 Entry.of("Platz sieben", 7777l),
272 Entry.of("Platz acht", 888l),
273 Entry.of("Platz neun", 99l),
274 Entry.of("Platz 10", 6l),
275 Entry.of("Platz 11", 3l))};