Java PS Utils is a lightweight utility library designed to streamline Competitive Programming (Algorithm) testing using JUnit 5.
It abstracts standard I/O redirection (System.in, System.out) and provides a simple interface for Parameterized Tests and Timeout Assertions, making your solution verification process clean and efficient.
- 🛡 Zero Boilerplate: Use simple
@PSTest,@PSTestCase, and@PSTestCasesannotations. No inheritance, no setup methods. - ⏱ Timeout Assertions: Easily detect infinite loops or inefficient solutions with strict timeouts.
- 📝 I/O Redirection: Automatically handles
System.inand capturesSystem.outfor assertion. - 🧪 Flexible Test Organization: Define each test case as a separate method, or group multiple cases in one method with
@PSTestCases. - 🎯 Better IDE Integration: Each test case appears separately in test runners.
- ☕ Java 8 Compatible: Works with Java 8 and above.
This library is distributed via JitPack.
Step 1. Add the JitPack repository to your root build.gradle file:
repositories {
mavenCentral()
maven { url '[https://jitpack.io](https://jitpack.io)' }
}Step 2. Add the dependency:
dependencies {
implementation 'com.github.dukcode:ps-utils:1.1.0'
}repositories {
mavenCentral()
maven("[https://jitpack.io](https://jitpack.io)")
}
dependencies {
implementation("com.github.dukcode:ps-utils:1.1.0")
}<repositories>
<repository>
<id>jitpack.io</id>
<url>[https://jitpack.io](https://jitpack.io)</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.dukcode</groupId>
<artifactId>ps-utils</artifactId>
<version>1.1.0</version>
</dependency>There are two ways to use this library: Annotation-based (recommended) and Classic.
Use @PSTest and @PSTestCase annotations for minimal boilerplate.
1. Annotate Your Test Class
Use @PSTest to specify the solution class and timeout.
2. Define Test Cases
Use @PSTestCase to define input and expected output for each test case.
Here is a full example of testing a solution named Fence:
import org.dukcode.psutils.PSTest;
import org.dukcode.psutils.PSTestCase;
@PSTest(timeout = 1.0, solution = Fence.class)
class FenceTest {
@PSTestCase(
input = """
3
7
7 1 5 9 6 7 3
""",
output = "20"
)
void testCase1() {}
@PSTestCase(
input = """
7
1 4 4 4 4 1 1
""",
output = "16"
)
void testCase2() {}
}Benefits:
- ✨ No inheritance required
- 🎯 Each test case is a separate method with clear naming
- 📊 Better IDE integration and test reporting
- 🔧 Less boilerplate code
You can also use @PSTestCases to define multiple test cases in a single method:
import org.dukcode.psutils.PSTest;
import org.dukcode.psutils.PSTestCase;
import org.dukcode.psutils.PSTestCases;
@PSTest(timeout = 1.0, solution = Fence.class)
class FenceTest {
@PSTestCases({
@PSTestCase(input = "3\n7\n7 1 5 9 6 7 3", output = "20"),
@PSTestCase(input = "7\n1 4 4 4 4 1 1", output = "16"),
@PSTestCase(input = "4\n1 4 2 3", output = "8")
})
void testAllCases() {}
}Each test case will be executed separately and displayed as:
[1] input: 3\n7\n7 1 5 9 6 7 3[2] input: 7\n1 4 4 4 4 1 1[3] input: 4\n1 4 2 3
For those who prefer the traditional approach, you can extend ProblemSolvingTest.
1. Create a Test Class
Extend ProblemSolvingTest and pass the timeout limit (in seconds) to the super constructor.
2. Implement Abstract Methods
setData(): Provide test cases as a Stream. Each argument contains the Input String and the Expected Output String.runMain(): Call your solution's main method.
import org.dukcode.psutils.ProblemSolvingTest;
import org.junit.jupiter.params.provider.Arguments;
import java.util.stream.Stream;
class FenceTest extends ProblemSolvingTest {
public FenceTest() {
super(1); // 1 second timeout
}
public static Stream<Arguments> setData() {
return Stream.of(
Arguments.of(
"""
3
7
7 1 5 9 6 7 3
""",
"20"
),
Arguments.of(
"""
7
1 4 4 4 4 1 1
""",
"16"
)
);
}
@Override
protected void runMain() throws Exception {
Fence.main(new String[]{});
}
}Console
A wrapper around java.util.Scanner to simplify reading input in your solution code. It manages the Scanner lifecycle automatically.
import org.dukcode.psutils.Console;
public class MySolution {
public static void main(String[] args) {
String line = Console.readLine();
// ... solve problem
}
}Assertions
Provides strict timeout assertions used internally by the test framework. You generally don't need to use this directly if you use @PSTest annotation or extend ProblemSolvingTest.
This project is licensed under the MIT License - see the LICENSE file for details.