First8 staat voor vakmanschap. Al onze collega’s zijn een groot aanhanger van Open Source en in het bijzonder het Java-platform. Wij zijn gespecialiseerd in het pragmatisch ontwikkelen van bedrijfskritische Java toepassingen waarbij integratie van systemen, hoge eisen aan beveiliging en veel transacties een belangrijke rol spelen. Op deze pagina vind je onze blogs.

Testing with state using GraphWalker | Part 1 – Persistence

In this first installment of Testing with state using GraphWalker, we’ll look at integration testing the persistence layer of a Spring application. So, our tests will target the database and the data repositories.

People trying to walk a path

Statefulness

The database itself is inherently stateful. As a result, if we connect a data repository to an actual database, it will also show stateful behavior. For example, when we query for a record that is not there, the result will be empty. Then, if we add the record and run the query again, the answer will be different and the record will be returned. Now, the fact that the queries result depended on previous actions, means that we are dealing with state.

In GraphWalker we can model this state in such a way, that it generates test scenarios accordingly.

System under test

Our example application is a tiny blog application. The next few test will target the persistence layer, which stores a blog post with comments.

Our tests will use @DataJpaTest, together with Spring runner, to create test a database and inject a repository.

Trivial example

The model

Our model has two states and three transitions.

In diagram form

 

TransitionFrom stateTo state
addPostnotPresentPresent
removePostPresentnotPresent
updatePostPresentPresent

In table form

The model represented in code

 

Now that we have our model, we need to tell GraphWalker what to do with it. For example, we have to tell it where to start.

Next, we will tell GraphWalker to generate random paths.

GraphWalker can generate random paths indefinitely. So, we have to tell it when to stop. We have. among others,  the following options to do so:

  • EdgeCoverage stop when a certain coverage degree of edges (transitions) is walked
  • VertexCoverage stop when a certain coverage degree of vertices (states) has been visited
  • TimeDuration stop when a certain amount of time has passed

Gluing the model to our code

You have noticed we named all the vertices and edges and you have noted the names look like method names. They are method names. Upon traversing edge, the method it is named after gets executed. Upon entering a vertex, the method it is named after gets executed. These method provide the glue between our model and our code. The code executed at a vertex may contain assertions, do validate some results.

The code executed at the edges applies the state changes implied by the transition.

Full source code

This example is trivial, just to show the basics. However, to test more complex software, using just states and transitions will not be enough.

Actions and guards

Guards further constrain which edges can be traversed. Without guards, any edge starting from a certain state may be chosen when the model is in that state. Guards add the ability to dynamically disable and enable some edges. Actions are executed upon walking an edge.

Both actions and guards, are specified as fragments of javascript. Guards must return a boolean, in contrast actions have no such constraints.

In our next example, we will add and remove comments. To make the test more accurate, we will add multiple comments to a post. We will also remove the comments, but only if there is at least one comment to remove.

The updatePost edge will be replaced by two new edges, addComment and removeComment.

Full source code

As a post is added, var comments = 0 is executed. Then, as comments are added, comments++ is executed. The edge removeComment has both a guard and an action. The guard comments > 0 make sure the path will not be traversed if there are no comments to remove. Finally, the action comments-- updates the number of comments if the edge is traversed.

The addition of the number of comments makes our model an Extended Finite State Machine.

Conclusion

With GraphWalker we can use finite state machines to generate scenario’s, to test software that has state. Furthermore, using Javascript executed by GraphWalker, we can make these scenario’s more complete.