A Fixture is something you can
- set up and tear down
- use in a test
- identify by type and name
- give a scoped lifecycle (e.g. test method, class, file, session)
More about fixtures: https://docs.pytest.org/en/6.2.x/fixture.html
<dependency>
<groupId>de.gofabian</groupId>
<artifactId>junit-fixture-extension</artifactId>
<version>0.1.1</version>
<scope>test</scope>
</dependency>
With Fixture Extension | Plain JUnit 5 |
---|---|
@ExtendWith(FixtureExtension.class)
class TestClass {
@Fixture
Database db(FixtureContext c) {
var db = DbUtil.open(...);
c.addTearDown(() -> db.close());
return db;
}
@Test
void test(Database db) {
db.put("key", "value");
assertEquals("value", db.get("key"));
}
} |
|
@ExtendWith(FixtureExtension.class)
class TestClass {
@Fixture(scope = Scope.SESSION)
long fixtureWithFileScope(FixtureContext c) {
println("session-up");
c.addTearDown(() -> println("session-down"));
return 1234567890;
}
@Fixture(scope = Scope.FILE)
double fixtureWithFileScope(FixtureContext c) {
println("file-up");
c.addTearDown(() -> println("file-down"));
return 13.37;
}
@Fixture(scope = Scope.CLASS)
int fixtureWithClassScope(FixtureContext c) {
println("class-up");
c.addTearDown(() -> println("class-down"));
return 42;
}
@Fixture // default scope is "METHOD"
String fixtureWithMethodScope(FixtureContext c) {
println("method-up");
c.addTearDown(() -> println("method-down"));
return "method";
}
@Test
void test1(String m, int c, double f, long s) {
println("test1");
}
@Test
void test2(String m, int c, double f, long s) {
println("test2");
}
} |
|
@ExtendWith(FixtureExtension.class)
class TestClass {
@Fixture
Database db(FixtureContext c) {
var db = DbUtil.open(...);
c.addTearDown(() -> db.close());
return db;
}
@Fixture
Table bookTable(Database db) {
return db.table("book");
}
@Test
void test(Table table) {
table.add("Science Book");
assertEquals(1, table.count());
}
}
@ExtendWith(FixtureExtension.class)
@LoadFixtures(DatabaseFixtures.class)
class TestClass {
@Fixture
Table bookTable(Database db) {
return db.table("book");
}
@Test
void test(Database db) {
db.put("key", "value");
assertEquals("value", db.get("key"));
}
} |
class DatabaseFixtures {
@Fixture
Database db(FixtureContext c) {
var db = DbUtil.open(...);
c.addTearDown(() -> db.close());
return db;
}
} |
@ExtendWith(FixtureExtension.class)
class TestClass {
@Fixture(autoUse = true)
Database db(FixtureContext c) {
var db = DbUtil.start(...);
c.addTearDown(() -> db.stop());
return db;
}
@Test
void test(/* Database db */) {
print("db is set up without explicit parameter");
}
}
@ExtendWith(FixtureExtension.class)
class TestClass {
@Fixture(scope = Scope.FILE)
double fixtureWithFileScope(FixtureContext c) {
println("file-up");
c.addTearDown(() -> println("file-down"));
return 13.37;
}
@Fixture(scope = Scope.CLASS)
int fixtureWithClassScope(FixtureContext c) {
println("class-up");
c.addTearDown(() -> println("class-down"));
return 42;
}
@Nested
class NestedTest1 {
@Test
void test1(String m, int c, double f, long s) {
println("test1");
}
}
@Nested
class NestedTest2 {
@Test
void test2(String m, int c, double f, long s) {
println("test2");
}
}
} |
|
@ExtendWith(FixtureExtension.class)
class TestClass {
@Fixture
String fixture1() {
return "fixture1";
}
@Fixture
String fixture2() {
return "fixture2";
}
@Test
void test(String fixture1, String fixture2, String any) {
assertEquals("fixture1", fixture1);
assertEquals("fixture2", fixture2);
assertTrue(any.equals("fixture1") || any.equals("fixture2"));
}
}
Run tests:
mvn test
Set new version (implicit git tag
and git push
):
./bump_version.sh x.y.z
Create a release in Github and the Github workflow will automatically publish it to Maven Central.
Manual alternative:
mvn clean deploy -P release
- generic dependency types, e.g. List
- @UseFixture
- support parallel execution
- support static fixture class methods
- fixture mark (given argument)
- parameterized fixture (multiple executions)
- more attributes in fixture context
- Programmatic FixtureDefinition