Skip to content

Commit 7095c2d

Browse files
Migrate test suite from JUnit 4 to JUnit 5 (#195)
* Migrate test suite from JUnit 4 to JUnit Jupiter 6.1.0 - Replace junit:junit:4.13.2 dependency with org.junit.jupiter:junit-jupiter:6.1.0 - Remove <junit.version> property - Convert all test imports: org.junit.* → org.junit.jupiter.api.* - Rename @Before/@after → @BeforeEach/@AfterEach, @BeforeClass/@afterclass → @BeforeAll/@afterall - Replace @ignore@disabled (including with message arguments) - Swap assertion argument order from message-first (JUnit 4) to message-last (JUnit Jupiter) - Convert Assume.* → Assumptions.* with argument order fix - Convert @test(expected=X.class) patterns to assertThrows() - Replace @rule TemporaryFolder with @tempdir Path - Convert JUnit 4 @RunWith(Parameterized.class) tests to @ParameterizedTest @MethodSource - Rewrite StopReasonTest to use @ParameterizedTest @EnumSource - Convert ModelFlagTest to @ParameterizedTest @MethodSource https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL * Fix JUnit Jupiter migration: compilation errors from CI - Fix @test(timeout=N) → @timeout + @test in SessionConcurrencyTest and MultimodalIntegrationTest - Fix @test(expected=X.class) → assertThrows() in ErrorHandlingTest, InferenceParametersTest, ParameterJsonSerializerTest - Fix @BeforeClass/@afterclass → @BeforeAll/@afterall across all affected test files - Fix broken imports: org.junit.assertNotEquals → org.junit.jupiter.api.Assertions.assertNotEquals - Fix org.junit.assertNull and org.junit.fail → static-imported equivalents - Add missing assertThrows imports in ContentPartTest, MultimodalMessagesTest, NativeLibraryPermissionSetterTest - Fix assertEquals argument order for float delta: message-first → message-last (RerankingModelTest) - Fix Assume.assumeNotNull → Assumptions.assumeTrue (LlamaEmbeddingsTest) https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL * Add JUnit 4 to JUnit Jupiter migration script https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL * Fix remaining JUnit Jupiter compilation errors: missing imports and assertNotEquals argument order - ChatResponseTest: add missing assertNull static import - LlamaPublisherTest: add missing fail static import - LoadProgressCallbackTest: swap assertNotEquals args to message-last order https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL * Fix @Before/@after → @BeforeEach/@AfterEach in LlamaEmbeddingsTest, LlamaLoaderTest, OSInfoTest https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL * Remove migrate_junit.py helper script (no longer needed) https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL * Fix assertEquals argument order: restore (expected, actual, delta) in all float comparisons The migration script incorrectly rotated 3-arg assertEquals(expected, actual, delta) calls to assertEquals(actual, delta, expected), treating numeric first args as messages. This caused 9 test failures (negative delta, or delta=0 where expected≠actual). Fixed all affected assertions across 8 test files. https://claude.ai/code/session_01Wz6qiYa6SGNirh9tVs4jUL --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 41ce68a commit 7095c2d

55 files changed

Lines changed: 847 additions & 1094 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

pom.xml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,15 @@ SPDX-License-Identifier: MIT
5050

5151
<properties>
5252
<jna.version>5.18.1</jna.version>
53-
<junit.version>4.13.2</junit.version>
5453
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5554
<project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp>
5655
</properties>
5756

5857
<dependencies>
5958
<dependency>
60-
<groupId>junit</groupId>
61-
<artifactId>junit</artifactId>
62-
<version>${junit.version}</version>
59+
<groupId>org.junit.jupiter</groupId>
60+
<artifactId>junit-jupiter</artifactId>
61+
<version>6.1.0</version>
6362
<scope>test</scope>
6463
</dependency>
6564
<dependency>

src/test/java/examples/ChatExample.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
import java.util.ArrayList;
1818
import java.util.List;
1919

20-
import org.junit.Ignore;
20+
import org.junit.jupiter.api.Disabled;
2121

2222
// Model file (models/codellama-7b.Q2_K.gguf) is not available in the models directory
23-
@Ignore
23+
@Disabled
2424
public class ChatExample {
2525

2626
public static void main(String... args) throws Exception {

src/test/java/net/ladenthin/llama/CancellationTokenTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
package net.ladenthin.llama;
66

7-
import org.junit.Test;
7+
import org.junit.jupiter.api.Test;
88

9-
import static org.junit.Assert.assertFalse;
10-
import static org.junit.Assert.assertTrue;
9+
import static org.junit.jupiter.api.Assertions.assertFalse;
10+
import static org.junit.jupiter.api.Assertions.assertTrue;
1111

1212
@ClaudeGenerated(
1313
purpose = "Verify CancellationToken state transitions (initial, cancel, reset) "

src/test/java/net/ladenthin/llama/ChatAdvancedTest.java

Lines changed: 37 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
import net.ladenthin.llama.args.MiroStat;
1515
import net.ladenthin.llama.args.Sampler;
1616
import net.ladenthin.llama.json.CompletionResponseParser;
17-
import org.junit.AfterClass;
18-
import org.junit.Assert;
19-
import org.junit.Assume;
20-
import org.junit.BeforeClass;
21-
import org.junit.Test;
17+
import org.junit.jupiter.api.AfterAll;
18+
import static org.junit.jupiter.api.Assertions.*;
19+
import org.junit.jupiter.api.Assumptions;
20+
import org.junit.jupiter.api.BeforeAll;
21+
import org.junit.jupiter.api.Test;
2222

2323
/**
2424
* Advanced inference parameter scenarios covering code paths untested by
@@ -53,10 +53,9 @@ public class ChatAdvancedTest {
5353

5454
private static LlamaModel model;
5555

56-
@BeforeClass
56+
@BeforeAll
5757
public static void setup() {
58-
Assume.assumeTrue("Model file not found, skipping ChatAdvancedTest",
59-
new File(TestConstants.MODEL_PATH).exists());
58+
Assumptions.assumeTrue(new File(TestConstants.MODEL_PATH).exists(), "Model file not found, skipping ChatAdvancedTest");
6059
int gpuLayers = Integer.getInteger(TestConstants.PROP_TEST_NGL, TestConstants.DEFAULT_TEST_NGL);
6160
model = new LlamaModel(
6261
new ModelParameters()
@@ -67,7 +66,7 @@ public static void setup() {
6766
);
6867
}
6968

70-
@AfterClass
69+
@AfterAll
7170
public static void tearDown() {
7271
if (model != null) {
7372
model.close();
@@ -94,9 +93,8 @@ public void testCachePromptConsistentOutput() {
9493
String first = model.complete(params);
9594
String second = model.complete(params);
9695

97-
Assert.assertFalse("First cached call must produce output", first.isEmpty());
98-
Assert.assertEquals("Same prompt with cache_prompt must produce identical output",
99-
first, second);
96+
assertFalse(first.isEmpty(), "First cached call must produce output");
97+
assertEquals(first, second, "Same prompt with cache_prompt must produce identical output");
10098
}
10199

102100
// ------------------------------------------------------------------
@@ -119,10 +117,9 @@ public void testUnboundedGenerationTerminatesAtStopString() {
119117

120118
String output = model.complete(params);
121119

122-
Assert.assertNotNull("Unbounded+stop output must not be null", output);
120+
assertNotNull(output, "Unbounded+stop output must not be null");
123121
// The stop string itself must not appear in the completion
124-
Assert.assertFalse("Output must not contain the stop string 'E'",
125-
output.contains("E"));
122+
assertFalse(output.contains("E"), "Output must not contain the stop string 'E'");
126123
}
127124

128125
// ------------------------------------------------------------------
@@ -150,7 +147,7 @@ public void testSetNProbsStreamingJsonHasProbabilities() {
150147
boolean done = false;
151148
while (!done) {
152149
String json = model.receiveCompletionJson(taskId);
153-
Assert.assertNotNull("receiveCompletionJson must not be null", json);
150+
assertNotNull(json, "receiveCompletionJson must not be null");
154151
LlamaOutput output = completionParser.parse(json);
155152
if (json.contains("\"completion_probabilities\"")) {
156153
foundProbabilities = true;
@@ -166,10 +163,7 @@ public void testSetNProbsStreamingJsonHasProbabilities() {
166163
}
167164
}
168165

169-
Assert.assertTrue(
170-
"At least one streaming JSON chunk must contain 'completion_probabilities' when nProbs>0",
171-
foundProbabilities
172-
);
166+
assertTrue(foundProbabilities, "At least one streaming JSON chunk must contain 'completion_probabilities' when nProbs>0");
173167
}
174168

175169
// ------------------------------------------------------------------
@@ -211,13 +205,9 @@ public void testCustomChatTemplateAcceptedWithoutError() {
211205
// Must not throw; parameter is accepted and forwarded to native layer
212206
String result = model.applyTemplate(params);
213207

214-
Assert.assertNotNull("applyTemplate with setChatTemplate must return non-null", result);
215-
Assert.assertFalse("applyTemplate with setChatTemplate must return non-empty result",
216-
result.isEmpty());
217-
Assert.assertTrue(
218-
"Result must contain the message content 'hello world' regardless of template used",
219-
result.contains("hello world")
220-
);
208+
assertNotNull(result, "applyTemplate with setChatTemplate must return non-null");
209+
assertFalse(result.isEmpty(), "applyTemplate with setChatTemplate must return non-empty result");
210+
assertTrue(result.contains("hello world"), "Result must contain the message content 'hello world' regardless of template used");
221211
}
222212

223213
// ------------------------------------------------------------------
@@ -247,8 +237,7 @@ public void testUseChatTemplateInGenerate() {
247237
output.append(token.text);
248238
}
249239

250-
Assert.assertFalse("generate() with use_chat_template must produce output",
251-
output.toString().isEmpty());
240+
assertFalse(output.toString().isEmpty(), "generate() with use_chat_template must produce output");
252241
}
253242

254243
// ------------------------------------------------------------------
@@ -272,7 +261,7 @@ public void testRepeatAndFrequencyAndPresencePenalty() {
272261
.setRepeatLastN(32);
273262

274263
String output = model.complete(params);
275-
Assert.assertFalse("Penalty params must not produce empty output", output.isEmpty());
264+
assertFalse(output.isEmpty(), "Penalty params must not produce empty output");
276265
}
277266

278267
// ------------------------------------------------------------------
@@ -295,7 +284,7 @@ public void testCustomSamplerChain() {
295284
.setSamplers(Sampler.TOP_K, Sampler.TOP_P, Sampler.TEMPERATURE);
296285

297286
String output = model.complete(params);
298-
Assert.assertFalse("Custom sampler chain must produce non-empty output", output.isEmpty());
287+
assertFalse(output.isEmpty(), "Custom sampler chain must produce non-empty output");
299288
}
300289

301290
// ------------------------------------------------------------------
@@ -317,7 +306,7 @@ public void testMiroStatV2Sampling() {
317306
.setMiroStatEta(0.1f);
318307

319308
String output = model.complete(params);
320-
Assert.assertFalse("MiroStat V2 must produce non-empty output", output.isEmpty());
309+
assertFalse(output.isEmpty(), "MiroStat V2 must produce non-empty output");
321310
}
322311

323312
// ------------------------------------------------------------------
@@ -344,7 +333,7 @@ public void testRequestCompletionDirectStreaming() {
344333
boolean stopped = false;
345334
while (!stopped) {
346335
String json = model.receiveCompletionJson(taskId);
347-
Assert.assertNotNull("receiveCompletionJson must not return null", json);
336+
assertNotNull(json, "receiveCompletionJson must not return null");
348337
LlamaOutput output = completionParser.parse(json);
349338
sb.append(output.text);
350339
tokens++;
@@ -354,13 +343,12 @@ public void testRequestCompletionDirectStreaming() {
354343
}
355344
if (tokens > N_PREDICT + 2) {
356345
model.releaseTask(taskId);
357-
Assert.fail("Direct streaming did not stop within nPredict tokens");
346+
fail("Direct streaming did not stop within nPredict tokens");
358347
}
359348
}
360349

361-
Assert.assertTrue("Direct non-chat streaming must emit at least one token", tokens > 0);
362-
Assert.assertFalse("Direct non-chat streaming must produce non-empty content",
363-
sb.toString().isEmpty());
350+
assertTrue(tokens > 0, "Direct non-chat streaming must emit at least one token");
351+
assertFalse(sb.toString().isEmpty(), "Direct non-chat streaming must produce non-empty content");
364352
}
365353

366354
// ------------------------------------------------------------------
@@ -397,7 +385,7 @@ public void testDisableTokenIdsAccepted() {
397385
.disableTokenIds(Collections.singletonList(disabledId));
398386

399387
String output = model.complete(params);
400-
Assert.assertFalse("disableTokenIds must not produce empty output", output.isEmpty());
388+
assertFalse(output.isEmpty(), "disableTokenIds must not produce empty output");
401389
}
402390

403391
// ------------------------------------------------------------------
@@ -418,14 +406,13 @@ public void testPenaltyPromptStringAccepted() {
418406
.setPenaltyPrompt("def ")
419407
.setRepeatPenalty(1.2f);
420408

421-
Assert.assertFalse("setPenaltyPrompt(String) must produce output",
422-
model.complete(params).isEmpty());
409+
assertFalse(model.complete(params).isEmpty(), "setPenaltyPrompt(String) must produce output");
423410
}
424411

425412
@Test
426413
public void testPenaltyPromptTokenArrayAccepted() {
427414
int[] penaltyTokens = model.encode("def ");
428-
Assume.assumeTrue("Need at least one penalty token", penaltyTokens.length > 0);
415+
Assumptions.assumeTrue(penaltyTokens.length > 0, "Need at least one penalty token");
429416

430417
InferenceParameters params = new InferenceParameters(SIMPLE_PROMPT)
431418
.setNPredict(N_PREDICT)
@@ -434,8 +421,7 @@ public void testPenaltyPromptTokenArrayAccepted() {
434421
.setPenaltyPrompt(penaltyTokens)
435422
.setRepeatPenalty(1.2f);
436423

437-
Assert.assertFalse("setPenaltyPrompt(int[]) must produce output",
438-
model.complete(params).isEmpty());
424+
assertFalse(model.complete(params).isEmpty(), "setPenaltyPrompt(int[]) must produce output");
439425
}
440426

441427
// ------------------------------------------------------------------
@@ -457,13 +443,10 @@ public void testMultipleStopStringsFirstMatchTerminates() {
457443

458444
String output = model.complete(params);
459445

460-
Assert.assertNotNull(output);
446+
assertNotNull(output);
461447
// None of the stop strings should appear in the output
462448
for (String stop : new String[]{"4", "5", "6"}) {
463-
Assert.assertFalse(
464-
"Output must not contain stop string '" + stop + "', got: " + output,
465-
output.contains(stop)
466-
);
449+
assertFalse(output.contains(stop), "Output must not contain stop string '" + stop + "', got: " + output);
467450
}
468451
}
469452

@@ -484,7 +467,7 @@ public void testMinPSamplerAccepted() {
484467
.setTemperature(0.7f)
485468
.setMinP(0.05f);
486469

487-
Assert.assertFalse("setMinP must produce output", model.complete(params).isEmpty());
470+
assertFalse(model.complete(params).isEmpty(), "setMinP must produce output");
488471
}
489472

490473
@Test
@@ -495,7 +478,7 @@ public void testTfsZSamplerAccepted() {
495478
.setTemperature(0.7f)
496479
.setTfsZ(0.95f);
497480

498-
Assert.assertFalse("setTfsZ must produce output", model.complete(params).isEmpty());
481+
assertFalse(model.complete(params).isEmpty(), "setTfsZ must produce output");
499482
}
500483

501484
@Test
@@ -506,7 +489,7 @@ public void testTypicalPSamplerAccepted() {
506489
.setTemperature(0.7f)
507490
.setTypicalP(0.9f);
508491

509-
Assert.assertFalse("setTypicalP must produce output", model.complete(params).isEmpty());
492+
assertFalse(model.complete(params).isEmpty(), "setTypicalP must produce output");
510493
}
511494

512495
// ------------------------------------------------------------------
@@ -526,7 +509,7 @@ public void testNKeepAllTokensAccepted() {
526509
.setTemperature(0.0f)
527510
.setNKeep(-1);
528511

529-
Assert.assertFalse("setNKeep(-1) must produce output", model.complete(params).isEmpty());
512+
assertFalse(model.complete(params).isEmpty(), "setNKeep(-1) must produce output");
530513
}
531514

532515
// ------------------------------------------------------------------
@@ -547,8 +530,7 @@ public void testDisableTokensStringFormAccepted() {
547530
.setTemperature(0.0f)
548531
.disableTokens(Arrays.asList("!!!"));
549532

550-
Assert.assertFalse("disableTokens must not produce empty output",
551-
model.complete(params).isEmpty());
533+
assertFalse(model.complete(params).isEmpty(), "disableTokens must not produce empty output");
552534
}
553535

554536
// ------------------------------------------------------------------
@@ -568,7 +550,6 @@ public void testMiroStatV1Sampling() {
568550
.setMiroStatTau(5.0f)
569551
.setMiroStatEta(0.1f);
570552

571-
Assert.assertFalse("MiroStat V1 must produce non-empty output",
572-
model.complete(params).isEmpty());
553+
assertFalse(model.complete(params).isEmpty(), "MiroStat V1 must produce non-empty output");
573554
}
574555
}

src/test/java/net/ladenthin/llama/ChatMessageTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
package net.ladenthin.llama;
66

7-
import org.junit.Test;
7+
import org.junit.jupiter.api.Test;
88

9-
import static org.junit.Assert.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertEquals;
1010

1111
@ClaudeGenerated(
1212
purpose = "Verify ChatMessage value class accessors and toString format used by Session.getMessages()."

src/test/java/net/ladenthin/llama/ChatResponseTest.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
package net.ladenthin.llama;
66

77
import net.ladenthin.llama.json.ChatResponseParser;
8-
import org.junit.Test;
8+
import org.junit.jupiter.api.Test;
99

1010
import java.util.List;
1111

12-
import static org.junit.Assert.assertEquals;
13-
import static org.junit.Assert.assertTrue;
12+
import static org.junit.jupiter.api.Assertions.assertNull;
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.junit.jupiter.api.Assertions.assertTrue;
1415

1516
@ClaudeGenerated(
1617
purpose = "Verify ChatResponseParser.parseResponse maps the OAI-compatible chat completion JSON "
@@ -83,7 +84,7 @@ public void parsesObjectShapedArguments() {
8384
ChatResponse r = parser.parseResponse(json);
8485
String args = r.getFirstMessage().getToolCalls().get(0).getArgumentsJson();
8586
// exact text isn't guaranteed, but must contain both fields
86-
assertTrue("expected serialized object, got: " + args, args.contains("\"a\":1"));
87+
assertTrue(args.contains("\"a\":1"), "expected serialized object, got: " + args);
8788
assertTrue(args.contains("\"b\":2"));
8889
}
8990

@@ -105,15 +106,15 @@ public void buildMessagesJsonRoundTripsToolTurns() {
105106
.addMessage(ChatMessage.toolResult("c1", "4"));
106107

107108
String msgs = req.buildMessagesJson();
108-
assertTrue(msgs, msgs.contains("\"tool_calls\""));
109-
assertTrue(msgs, msgs.contains("\"tool_call_id\":\"c1\""));
110-
assertTrue(msgs, msgs.contains("\"name\":\"add\""));
109+
assertTrue(msgs.contains("\"tool_calls\""), msgs);
110+
assertTrue(msgs.contains("\"tool_call_id\":\"c1\""), msgs);
111+
assertTrue(msgs.contains("\"name\":\"add\""), msgs);
111112
}
112113

113114
@Test
114115
public void buildToolsJsonEmptyWhenNoTools() {
115116
ChatRequest req = new ChatRequest().addMessage("user", "hi");
116-
org.junit.Assert.assertNull(req.buildToolsJson());
117+
assertNull(req.buildToolsJson());
117118
}
118119

119120
@Test
@@ -122,8 +123,8 @@ public void buildToolsJsonInlinesParameterSchema() {
122123
"echo", "Echo a string",
123124
"{\"type\":\"object\",\"properties\":{\"s\":{\"type\":\"string\"}}}"));
124125
String tools = req.buildToolsJson();
125-
assertTrue(tools, tools.contains("\"type\":\"function\""));
126-
assertTrue(tools, tools.contains("\"name\":\"echo\""));
127-
assertTrue(tools, tools.contains("\"properties\""));
126+
assertTrue(tools.contains("\"type\":\"function\""), tools);
127+
assertTrue(tools.contains("\"name\":\"echo\""), tools);
128+
assertTrue(tools.contains("\"properties\""), tools);
128129
}
129130
}

0 commit comments

Comments
 (0)