Exam: Acceptance Test–Driven Development based on Concordion
Illustration from "Growing Object-Oriented Software, Guided by Tests"
Exam is oriented on declarative end-to-end black\graybox application testing in a way a manual tester would do it: send request, verify response\database\message queue etc.
- Declarative glue-code free approach
- Attractive, flexible documentation thanks to Concordion
- Widly used set of testing tools under the hood: dbunit, rest-assured, xml-unit, json-unit
// Typical microservices setup (Web API + DB + MQ) testing:
testImplementation "io.github.adven27:exam-ms:6.0.0-alpha-3"
//same as:
//testImplementation "io.github.adven27:exam-ws:6.0.0-alpha-3"
//testImplementation "io.github.adven27:exam-db:6.0.0-alpha-3"
//testImplementation "io.github.adven27:exam-mq:6.0.0-alpha-3"
// UI testing
testImplementation "io.github.adven27:exam-ui:6.0.0-alpha-3"
For detailed info, see original tutorial
specs.Specs.java
public class Specs extends AbstractSpecs {
private static ConfigurableApplicationContext SUT;
@Override
protected ExamExtension init() {
return new ExamExtension(
new WsPlugin(8080),
new DbPlugin("org.postgresql.Driver", "jdbc:postgresql://localhost:5432/postgres", "postgres", "postgres"),
new MqPlugin(Map.of("kafka", new KafkaTester("PLAINTEXT://localhost:9092", "topic")))
);
}
@Override
protected void startSut() {
SpringApplication app = new SpringApplication(Main.class);
app.setAdditionalProfiles("qa");
SUT = app.run();
}
@Override
protected void stopSut() {
SUT.stop();
}
}
specs\Specs.md
# API
- [User creation]( usercreation/UserCreation.html "c:run")
specs.usercreation.UserCreation.java
public class UserCreation extends Specs {
}
specs\usercreation\UserCreation.html
<html xmlns:e="http://exam.extension.io" xmlns:cc="http://www.concordion.org/2007/concordion">
<body>
<h1>User creation</h1>
<e:example name="My dummy user creation example">
<e:given>
Given users:
<e:db-set table="user" cols="name, age, id=1..10">
<e:row>Andrew, 20</e:row>
<e:row>Bob , 30</e:row>
</e:db-set>
</e:given>
<e:post url="users">
<e:case desc="When name and age was posted user should be created and id should be returned">
<e:body> {"name": "Carl", "age": 40} </e:body>
<e:expected> {"id": "{{number}}"} </e:expected>
<e:check>
<e:db-check table="person" cols="name, age">
<e:row>Andrew, 20</e:row>
<e:row>Bob , 30</e:row>
<e:row>Carl , 40</e:row>
</e:db-check>
</e:check>
</e:case>
<e:case desc="Age is optional">
<e:body> {"name": "Don"} </e:body>
<e:expected> {"id": "{{number}}"} </e:expected>
<e:check>
<e:db-check table="person" cols="name, age" where="name='Don'">
<e:row>Don, {{NULL}}</e:row>
</e:db-check>
</e:check>
</e:case>
</e:post>
</e:example>
</body>
</html>
For more info, see live spec and demo project