JUnit
JUnit is a well-known testing library in Java.
- β οΈ JUnit4 (download, hamcrest library)
- πΉ JUnit5 (a.k.a. Jupiter, download)
JUnit5 is a bit less straightforward to use, and unlike JUnit4 where there is only one file, the code is now divided into modules, so you need to find and download the ones you need.
You will usually put every required .jar
in a folder "libs
". To find the JUnit5 jar
you need, check the path of the import in the code.
JUnit4
$ javac -cp ".:libs/*" XXXTest.java
$ java -cp ".:libs/*" org.junit.runner.JUnitCore XXXTest
JUnit5
$ javac -d out -cp ".:/libs/*" XXXTest.java
$ java -jar junit-platform-console-standalone.jar -cp "out" --scan-classpath
JUnit4
In JUnit4, it was common to have a class to run all tests.
public class RunAllTests {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(XXXTest.class, YYYTest.class);
if (result.wasSuccessful()) {
System.out.println("All tests passed.");
} else {
for (Failure failure : result.getFailures()) {
System.err.println("Failure : " + failure.toString());
}
}
}
}
If your IDE can run them, it's shorter and better to run suites:
@RunWith(Suite.class)
@SuiteClasses({XXXTest.class, YYYTest.class})
public class AllTests {}
To move to/from JUnit5, you will most likely have to only replace the import with JUnit4 imports (if classes/methods still exist):
import org.junit.Assert;
import org.junit.Test;
JUnit5
Since JUnit5, there is no easy way to have a main class run all tests. You can run multiple classes using:
@Suite
@SelectClasses({XXXTest.class, YYYTest.class})
public class AllTests {}
π΅ Required: jupiter-api
, platform-commons
, platform-suite-api
, platform-suite-engine
, platform-suite-commons
.
To move to/from JUnit4, you will most likely have to only replace the import with JUnit5 imports (if classes/methods still exist):
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
β‘οΈ Notice that we use api
, so you need the xxx-api.jar
.
Assertions
JUnit uses assertions in its tests. They are defined in the package Assertions
(JUnit5) or Assert
(JUnit4).
An assertion is a function call that will test something, and raise an exception if the check fails.
// true if equals
Assertions.assertEquals(Object, Objet);
// true if the condition is true
Assertions.assertTrue(condition);
// true if the condition is false
Assertions.assertFalse(condition);
// true if null
Assertions.assertNull(objet);
// true if not null
Assertions.assertNotNull(Objet);
// true if ==
Assertions.assertSame(Object, Object);
// true if !=
Assertions.assertNotSame(Object, Object)
// true if Arrays are equals
Assertions.assertArrayEquals(t1,t2);
// true if exception got thrown,
// method must be a Runnable
assertThrows(SomeException.class, method);
// fail
fail()
Every assert method has an argument usually called message
to send, along with the exception, a more pertinent error message.
Test suites
Test suite are java classes with tests. Most test methods are named starting with test[...]
. They are annotated with @Test
.
public class XXXTest {
@Test
public void testAAA() {
Assertions.assertTrue(true);
}
}
According to the JUnit version, you can add some annotations to refine how JUnit handles your test.
-
@DisplayName("XXX")
: name displayed by the runner -
@Test(expected = XXX.class)
: the test must raise an exception -
@Test(timeout = xxx)
: test fails if longer than the timeout -
@Disabled
: don't run this test
Test suites usually group tests, testing the same method or class. We may have to prepare things before running tests:
public class TestSuite {
// before/all ALL tests
@BeforeAll
public static void classInit(){ /* set attributes */ }
@AfterAll
public static void classFree(){ /* unset attributes */ }
// before/all EVERY test
@BeforeEach
public void testInit(){ /* set attributes, ... */ }
@AfterEach
public void testFree(){ /* unset attributes, ... */ }
}
β οΈ Use @BeforeClass
/@AfterClass
, and @Before/@After
with Junit4.
Parametric tests
Parametric tests are tests that have the same code but different parameters. We will write a method with parameters once, and tell JUnit all the parameters that must be tested.
The logic is that we will indicate one or more sources to fill the parameter with our test method. These methods return a Stream
.
public class XXXTest {
@ParameterizedTest
@MethodSource("method_name")
public void myTest(ArgumentType name){
// code
}
private static Stream<ArgumentType> method_name(){
return ...;
}
}
For instance, here, we will call myTest
with 5
, 7
, 3
, and 5
.
@ParameterizedTest
@MethodSource({"test", "test2", "test"})
public void myTest(int p){
// some code here
}
private static Stream<Integer> test() {
ArrayList<Integer> e = new ArrayList<>();
e.add(5);
return e.stream();
}
private static Stream<Integer> test2() {
ArrayList<Integer> e = new ArrayList<>();
e.add(7);
e.add(3);
return e.stream();
}
π» To-do π»
Stuff that I found, but never read/used yet.
- Maven
- Idea note
-junit5 pkg.AClass,aTest
JUnit4
@RunWith(JUnitPlatform.class)
@SelectClasses({anotherClass.class})
// @SelectPackages("tests")
// @SelectPackages({"tests"})
public class MaClasse {
}
@RunWith(Suite.class) ;
@Suite.SuiteClasses({ TestClass.class, ... });
public class MyClass {}