Backend test automation, the middle layer of the Testing Pyramid, is an area that no efficient test automation strategy should overlook. It's quick, it's stable and luckily with the use of specific Java libraries, it's also easy to implement.
This article will present a Backend test automation framework built with JUnit 5, REST Assured and a specific library for GraphQL file manipulation.
Project structure and setup
As it is a Maven project, all the needed libraries can be easily imported through the POM file.
Two helper classes are also needed:
- one for preparing the GraphQL payload, that can be checked here and is shown below:
public static String prepareGraphqlPayload(Map<String, String> variables, String queryFileLocation) {
File file = new File(queryFileLocation);
ObjectNode objectNode = new ObjectMapper().createObjectNode();
for (Map.Entry<String, String> entry : variables.entrySet()) {
objectNode.put(entry.getKey(), entry.getValue());
}
String graphqlPayload = null;
try {
graphqlPayload = GraphqlTemplate.parseGraphql(file, objectNode);
} catch (IOException e) {
e.printStackTrace();
}
return graphqlPayload;
}
- one for preparing the JSON object that can be checked here and is shown below:
public static JSONObject buildJsonObject(String location) {
JSONParser parser = new JSONParser();
JSONObject jsonObject = null;
try {
jsonObject = (JSONObject) parser.parse(new FileReader(location));
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
return jsonObject;
}
Specifying the APIs and test data
The APIs under test will be:
As test data, we need:
- the Pokemon GraphQL query file
- the list of Pokemon and their attributes as a .csv file
Writing the test scenarios
- The GraphQL test class can be checked here and the main test is detailed below:
@ParameterizedTest
@CsvFileSource(resources = "/graphql/pokemons.csv", numLinesToSkip = 1)
void testGraphQL(String id, String pokemonName, String weight, String height) {
RestAssured.baseURI = "https://pokeapi-graphiql.herokuapp.com";
Map<String, String> variables = new HashMap<>();
variables.put("number", id);
String graphqlPayload = GraphqlUtil.prepareGraphqlPayload(variables, "src/test/resources/graphql/pokemon.graphql");
given().log().body()
.contentType(ContentType.JSON)
.body(graphqlPayload)
.post("/graphql")
.then()
.statusCode(200)
.body("data.pokemon.name", equalTo(pokemonName))
.body("data.pokemon.weight", equalTo(weight))
.body("data.pokemon.height", equalTo(height));
logger.info("GraphQL request successful for " + pokemonName);
}
Although a test scenario for a GraphQL API, the REST Assured library can be easily used and we can take advantage of its straightforward features for making the initial setup, executing the request and verifying the returned data.
- The REST test class can be checked here and the initialisation step and first test case are detailed below:
@BeforeAll
static void initialize() {
RestAssured.baseURI = "https://petstore.swagger.io/v2";
petCreatedJson = buildJsonObject("src/test/resources/rest/pet_created.json");
petUpdatedJson = buildJsonObject("src/test/resources/rest/pet_updated.json");
}
@Test
@Order(1)
void testPetCreation() {
given().log().uri()
.contentType(ContentType.JSON)
.body(petCreatedJson)
.post("/pet")
.then()
.statusCode(200).extract().response()
.then().body("name", equalTo(petCreatedJson.get("name")));
logger.info("Pet entry with id " + petCreatedJson.get("id") + " and name " + petCreatedJson.get("name") + " successfully CREATED");
}
The @BeforeAll step handles the initial setup, setting the baseURI and building the two JSON objects that will be used in testing.
Because this test class was designed to verify the entire flow, with @Order used to guarantee the correct timing of the test scenarios, the execution flow will be the following:
- Create the pet entry
- Verify the entry with correct info was created
- Update the pet entry
- Verify the entry was updated with the correct info
- Delete the pet entry
- Verify the entry was deleted
Thus, this test suite can run independently each time and does not rely on previously available data, nor does it spam the database after each execution.
No comments:
Post a Comment