Showing posts with label Data-Driven. Show all posts
Showing posts with label Data-Driven. Show all posts

Friday, 9 July 2021

Gatling and the test data generator pattern

Background

Recently I’ve done a lot of work on performance and load testing a variety of back-end systems which required huge JSON objects containing lots of different fields. In load testing, its useful to really push a system in terms of memory, cache and its disk space, which requires every bit of data we send to be unique.
Fortunately, the developers had already created a POJO project that documented the JSON schema in code, however, this only provided the skeleton of what the JSON should look like, but didn’t physically generate any data.
Initially I wrote a lot of Scala code in my Gatling project to use the POJO to define test data for my requests, however when we have 200+ different fields this quickly became a nightmare to maintain and confusing for newcomers to understand.
This is where I came up with the idea to create a 3rd project to define test data, splitting it out from my Gatling project so that it was only concerned with code that controlled load tests.

 

Data model

Here I have created an example of what a data-model project could look like:
https://github.com/matthewbretten/example-json-data-model

It is basically a code representation of a JSON schema, where we define what a particular object looks like, so in this case I’ve gone with an example of a shopping basket where it has particular nested objects such as “customer” and fields like “name” - also defining what type of data these are (such as String or Integer).
In my context, the developers had already created this and used it within their Java applications, so there wasn’t any work for me to do originally and it was extra useful to share the same effective “contract” in a sense - if the model changed it was only changed in one place and it was simply a case of increasing version numbers.

Test data generator

Here I have created an example of what a test-data-generator project could look like:
https://github.com/matthewbretten/example-json-test-data-generator

This pulls in the above data-model as a dependency and then goes a step further and provides functions that return full JSON strings. It has definitions of what various fields should look like and controls how random this content is.
So for example, in the JSON schema we define objects such as a Name:
“Name”:”String”
Whereas in this project we are now defining and controlling what content we get in the String - we could make it totally random strings “Acse1234fggDG” or we could attempt to make it realistic “Billy Boat”. In this case I’ve provided some examples where we randomly select from lists of reasonably realistic data - this is limiting the “randomness” of the data but keeping it more useful. Depending on what you’re trying to test, you may want to change it so its more random.
The key point here is that we have a neat Java project to easily define and control this behaviour.

Gatling

Here I have created an example Gatling project that uses both of the above projects as dependencies:
https://github.com/matthewbretten/gatling-example-datamodel-pattern

This defines our load tests, controls how many requests per second and where we send the data. However, the data is now fed from the test-data-generator project, the advantage being that all of that code is now kept separate and keeping the amount of Scala code to a minimum. The latter was relevant for me because many of the developers and testers were not familiar with Scala - so keeping the load test code simple and understandable was valuable.

Benefits

  • Each project only has 1 job - particularly the Gatling project is kept strictly to load test design and avoids bloat from having to define every field in a large JSON payload.
  • The test-data-generator can be re-used for other purposes, it can be used in unit tests or pulled in by other tools. 
  • Easily extendable to make data more or less random or more or less realistic.
  • Java is more widely understood and used than Scala, particularly when we include the Gatling DSL.
  • A neat way to also document what “realistic” test data looks like.

Downsides

  • More complicated in terms of more than 1 code project to maintain, may be harder to follow. This is not worthwhile in simpler examples where the JSON schema is very small or where we simply can hard-code many of the fields.
  • Load test design is now spread across multiple projects which makes it more work to understand. I found it was important to then make sure the relationship between the Scenario and Request names in Gatling was tied to the different kinds of test data so make it easier to quickly understand in the Gatling HTML reports.
  • There is also a separation of concern regarding the performance of Gatling itself - we now have to be careful how we design the test data code because itself can be slow to physically generate and return the JSON strings. On this note, I was originally using the java-faker library but found its use of string replacement to be very slow, which slowed down how fast Gatling could generate requests. With separate projects, such a concern may not be as apparent.






Sunday, 16 October 2016

Neat ideas from some recent meetups

Introduction

The last few weeks I’ve been to quite a few testing meetups and there were some notable ideas that I really loved. Plus, I like promoting that these events exist and if you haven’t been to one, find one near you and go! (or if there isn’t one, start one!).

Challenges of testability

I had no idea about this one until I saw a tweet about free tickets from Ash Winter. It was a free 1-day, 2-track conference held in Leeds on the 20th September. I thoroughly enjoyed one of the workshops by Clem Pickering and Mike Grimwood. Their workshop was on testability and it involved designing a toaster (which reminded very much of this TED talk).

What I loved about this workshop was the visual demonstration of how people could take many different interpretations from vague requirements, the assumptions we make and how asking questions on testability helps drive out these assumptions. They used James Bach’s testability heuristics as a tool to help people explore different kinds of testability and generate some great discussion and ideas in the workshop. I loved this workshop so much in its simplicity and visual impact that I’d like to have a go running it at work when I can find a good time.

Using data to drive testing

The following week was the Liverpool Tester Gathering which featured my old manager from Sony, Gaz Tynan, talking about the visual methods they use to plan and review test coverage. This was another highlight for me as again I love the visual impact. Gaz talked through how they collect data from both exploratory tests and automation checks and map it onto a game map (similar to Google Maps). As you can imagine, many games at Sony have a 3D virtual world to explore and test, so they can represent their test data as a physical map too. He then demonstrated how they can then see where they test coverage is lacking or where they may want to explore more through examples like heat maps of framerate drop or where bugs were collecting together.
Seeing this visual representation of test coverage really got me thinking about how I could achieve similar results back at work. It was really inspiring and yet more evidence for me that visual representations of ideas, problems or reporting on data are so appealing and compelling.