Model-based testing with GraphWalker and Selenium – part 1

In this post I’d like to make a start exploring the possibilities and drawbacks that model-based testing (MBT) can offer to test automation in general and Selenium WebDriver in particular. I’ll be using GraphWalker as my MBT tool of choice, mostly because it’s open source, doesn’t have a steep learning curve and it’s available as a Java library, which makes integration with any Selenium project as simple as downloading the necessary .jar files and adding them to your test project.

I’ll use the login procedure for the Parabank demo application I’ve used so often before as an example. First, we need to model the login procedure using standard edges and nodes (which are called vertexes in Graphwalker):
A model of the Parabank login procedure
I’ve used yEd to draw this model, mostly because this tool offers the option to export the model in .graphml format, which will come in very handy at a later stage. I’ll go into that in another post.

After the browser has been started and the Parabank homepage is displayed, we can perform either a successful or an unsuccessful login. Unsuccessful logins take us to an error page, which offers us the possibility to try again, again with both positive and negative results as a possibility. A successful login takes us to the Accounts Overview page, from where we can log out. The application offers us many more options once we have performed a successful login, but for now I’ll leave these out of scope.

Next, we are going to ‘draw’, i.e. implement this model in GraphWalker. This is pretty straightforward:

private Model createModel() {

	// Create a new, empty model
	Model model = new Model();

	// Create vertexes (nodes)
	Vertex v_Start = new Vertex().setName("v_Start");
	Vertex v_HomePage = new Vertex().setName("v_HomePage");
	Vertex v_ErrorPage = new Vertex().setName("v_ErrorPage");
	Vertex v_AccountsOverviewPage = new Vertex().setName("v_AccountsOverviewPage");

	// Create edges
	Edge e_StartBrowser = new Edge()
	Edge e_LoginFailed = new Edge()
	Edge e_LoginFailedAgain = new Edge()
	Edge e_LoginSucceeded = new Edge()
	Edge e_LoginSucceededAfterFailure = new Edge()
	Edge e_Logout = new Edge()

	// Add vertexes to the model

	// Add edges to the model

	return model;

Easy, right? The only downside is that this is quite a lot of work, especially when your models get pretty large. It also leaves (a lot of) room for improvement when it comes to maintainability. We’ll get to that in a later post as well.

Theoretically, we could have GraphWalker go through this model and explore all vertexes and edges, but in order to do meaningful work we need to link them to concrete action steps performed on Parabank. A good and clean way to do this is to consider the following:

  • Edges are like state transitions in your model, so this is where the action (typing in text boxes, clicking on links, etc.) ends up.
  • Vertexes represent states in your model, so this is where the verifications (checks) need to be performed.

For example, this is the implementation of the e_StartBrowser edge:

WebDriver driver = null;

public void e_StartBrowser() {

	driver = new FirefoxDriver();
	driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);


By giving the method the same name as the actual edge, GraphWalker knows that it needs to execute this code snippet every time the e_StartBrowser node is encountered when running through the model. We can do the same for the vertexes, for example for the v_HomePage vertex representing the page we land on when we perform a successful login:

public void v_HomePage() {

	Assert.assertEquals(driver.getTitle(),"ParaBank | Welcome | Online Banking");

For simplicity, we’ll just do a check on the page title, but you’re free to add any type of check you wish, of course.

Finally, we need to tell GraphWalker to load and run the model. I prefer using TestNG for this:

public void fullCoverageTest() {

	// Create an instance of our model
	Model model = createModel();
	// Build the model (make it immutable) and give it to the execution context
	// Tell GraphWalker to run the model in a random fashion,
	// until every vertex is visited at least once.
	// This is called the stop condition.
	this.setPathGenerator(new RandomPath(new VertexCoverage(100)));
	// Get the starting vertex (v_Start)
	//Create the machine that will control the execution
	Machine machine = new SimpleMachine(this);
	// As long as the stop condition of the path generator is not fulfilled, hasNext will return true.
	while (machine.hasNextStep()) {
		//Execute the next step of the model.

The most important part in this test is the stop condition, which basically tells GraphWalker how to run the test and when to stop. In this example, I want to run the model and its corresponding Selenium actions randomly (within the restrictions implied by the model, of course) until every vertex has been hit at least once (100% vertex coverage). GraphWalker offers a lot of other stop conditions, such as running the model until:

  • Every edge has been hit at least once
  • A predefined vertex is hit
  • A predefined time period has passed (this is great for reliability tests)

A complete list of options for stop conditions can be found here in the GraphWalker documentation.

When we run this test, we can see in the console output that GraphWalker walks through our model randomly until the stop condition has been satisfied:
GraphWalker console outputAs usual when using TestNG, a nice little report has been created that tells us everything ran fine:
GraphWalker TestNG report - passNote that unlike what I did in the example above, it’s probably a good idea to use soft asserts when you’re using TestNG together with GraphWalker. Otherwise, TestNG and therefore GraphWalker will stop executing at the first check that fails. Unless that’s exactly what you want, of course.

In this post we’ve seen a very basic introduction into the possibilities of MBT using GraphWalker and how it can be applied to Selenium tests. In upcoming tests I’ll dive deeper into the possibilities GraphWalker provides, how it can be used to generate executable models from .graphml models, and how to make the most of the tool while keeping your tests clean and maintainable.

The Eclipse project containing the code I’ve used in this post can be downloaded here.

39 thoughts on “Model-based testing with GraphWalker and Selenium – part 1

  1. Pingback: Testing Bits – 10/18/15 – 10/24/15 | Testing Curator Blog

  2. Just one note… to get green test result you should have “Error”, istead of “Fault”… ;o)

    public void v_ErrorPage() {

    Assert.assertEquals(driver.getTitle(), “ParaBank | Error”);

    • Hi Roman,

      you’re absolutely correct! In my defense, I changed that on purpose to see how GraphWalker reacted to a failed assertion, but I forgot to change it back to the correct value before uploading the code.

      I’ll fix that ASAP. Thanks for mentioning it!

      EDIT: Done!

    • Hey Patrick,

      I am planning to cover that in a follow up post, unfortunately I haven’t had the time yet to prepare and write one. In the meantime Google might be your best friend..

      I agree that the ability to parse graphml files rather than rewriting them in code would be a massive improvement. I know GraphWalker supports it, I just haven’t had the opportunity to look into it yet..

      • Hi Bas,

        Really a good post. I was wondering if its possible to use above technique for API testing. If it is possible, could you please give some details on how to achieve MBT on API testing.


        • Hi Kumar, if you can model the behavior of your API / your application as a sequence of API calls then surely it’s possible. I like the idea so I’m going to use in a future post. Might take a couple of weeks though..

          • Come to think of it, I’m not sure whether this would make a good example. Most web services are stateless and using MBT or GraphWalker in particular is especially useful for stateful applications. It can be done, but I don’t think it demonstrates the full power of MBT / GraphWalker. My next post will therefore probably be web application-oriented, just as this one.

            If you want to apply GraphWalker on web services / APIs, just replace the Selenium code by code you use to call your API (vertexes) and assert the responses (nodes), for example using REST Assured.

          • Thanks for reply Bas.


            get(“/lotto”).then().assertThat().body(“lotto.lottoId”, equalTo(5));

            For the above Rest Assured code, could you please give the content of Edge and Vertex.

          • That’s what I tried to explain: such an API call doesn’t directly translate to an edge and a vertex in GraphWalker. A transition between vertexes by means of an edge implies a state transition. An API call is simply a query for data (in this case). There’s no change in state.

        • Hey Sagar,

          that’s still somewhere on the backlog, but I’m not sure if I’ll get to that soon. Thanks for reminding me there is a demand for this subject, though.

    • Hi Patric,

      try this:

      public final static Path MODEL_PATH = Paths.get(“my-Graph.graphml”);

      public void runFunctionalTestAllEdges() {
      new TestBuilder().addModel(MODEL_PATH, new WizardLoginTest().setPathGenerator(new RandomPath(new EdgeCoverage(100)))).execute();

      public void runFunctionalTestAllVertexes() {
      new TestBuilder().addModel(MODEL_PATH, new WizardLoginTest().setPathGenerator(new RandomPath(new VertexCoverage(100)))).execute();

      public void runFunctionalTestAll60Seconds() {
      new TestBuilder().addModel(MODEL_PATH, new WizardLoginTest().setPathGenerator(new RandomPath(new TimeDuration(60, TimeUnit.SECONDS)))).execute();

      • Hi Roman,
        thanks for your reply.
        But it doesn`t work.
        Could you please share an example for the “WizardLoginTest”-Class?



        • I don´t know if his still useful but the class “wizardLoginTest” could be something like this”:
          @GraphWalker(value = “random(vertex_coverage(100))”, start = “e_Init”)
          public class LoginSomeTest extends ExecutionContext implements Login {

          public void e_Logout() {


          public void v_LoginPrompted() {


          public void e_Init() {


          public void e_Exit() {


          public void e_InvalidCredentials() {


          public void v_GmailPageOpened() {


          public void e_CleanCache() {


          public void e_SearchGmailPage() {


          public void v_BrowserNotStarted() {


          public void v_SearchResult() {


          public void e_ValidCredentials() {


          public void v_BrowserOpened() {


          public void v_GmailSearchResult() {


          public void e_OpenBrowser() {


          public void v_EmailOpened() {


          public void e_searchEmail() {


          public void e_CloseBrowser() {


          public void v_LoginMade() {


          public void e_ClickOpenGmail() {


          public void v_CacheCleaned() {


          public void e_ClickToOpen() {


          public void e_ClickSignIn() {


          And then in a another/new class this execution that @Roman Hesteric mentioned.

          Like this:

          public class TestExecution {
          public final static Path MODEL_PATH = Paths.get(“src/main/resources/com/company/Login.graphml”);

          public void runFunctionalTestAllEdges() {
          new TestBuilder()
          .addModel(MODEL_PATH, new LoginSomeTest()
          .setPathGenerator(new RandomPath(new EdgeCoverage(100)))).execute();
          By the way thank you @Roman Hesteric for the example.
          Hope this help

  3. Hi Bas,

    On January 21, 2016 at 7:10 pm you wrote ‘There’s no change in state’. Recently I studied your open source training ‘API mocking with WireMock’ (which is excellent btw). In this training states are introduced for handling API calls in specific sequences. It is true that API calls are stateless, but the functionality behind it often depends on such sequences. The light bulb test example in the training can be perfectly rewritten in GraphWalker. Imho this would be a very good test.


    • Hey Ed,

      fully agreed! That might actually be a very good trigger for me to start fiddling around with GraphWalker again.. Thanks for suggesting!

  4. Hey Bas, Nice Tutorial!
    I am new to the MBT, and I am unable to run your eclipse project. It says no tests found with test runner. Can you help?


    • Hey Abbas,

      first of all, sorry for the delay in answering you. Second, thanks for the kind words!

      What test runner are you using? I’ve used TestNG. The project is a mess, by the way, it’s from before the time I learned how to use Maven to create a proper project. Will update it some time (hopefully next week), putting it on the to do list.

      • Not a problem Bas. Thanks for the reply. I am using the Junit 4 test runner (it may sound weird, I am new). I will try it on TestNG.


  5. Hi Bas,

    Thanks for putting together this wonderful tutorial. I am a student currently doing an 8 month internship and I plan to introduce graphwalker while I work here. I am working on a proof of concept and I was wondering if you are planning to come up with a part 2 soon.

    • It’s on the list, that’s all I can promise at the moment.. I’d love to further explore GraphWalker but I can’t seem to find the time at the moment!

  6. Hej Bas!

    Greatly inspiring tutorial.
    I have one Q, how do I integrate test data set in the model using GraphWalker? (Data-driven)


    • Hey AD, it’s been a while since I’ve done anything with GraphWalker so I’m afraid I can’t help you out there..

    • This is the one million dollar question. Tackle this and you have a much more controlled way for testing data oriented / administrative systems.


      • Hi Ed,

        I have implemented the following steps to supply the data sets into a test.

        1. read data from a source, in my case it’s a simple json file.
        “organisationsnummer”: “846000####”,
        “diarienummer”: “Af-2019/0000 ####”
        “organisationsnummer”: “937000####”,
        “diarienummer”: “Af-2018/0000 ####”

        2. using @DataProvider to iterate through each set

        3. inject data into model using setAttribute (leave the attributes undefined in the model like this)

        may be the following code can give you better understanding 🙂

        @DataProvider(name = “input_BAR_2293”)
        public Iterator input_BAR_2293(ITestContext context) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String fileName = context.getCurrentXmlTest().getParameter(“data_2293”);
        List item = objectMapper.readValue(new File(fileName), new TypeReference<List>() {});
        return item.iterator();

        @Test(dataProvider = “input_BAR_2293”)
        public void test_BAR_2293(Dictionary item, ITestContext context, Method method) {
        logger = extent.createTest(““+method.getName().toUpperCase()+”“+item.toString());
        logger.log(Status.INFO, “Inserting test data from json file to the model …”);
        arbetsgivarkontroll.setAttribute(“Organisationsnummer”, item.getOrganisationsnummer());
        arbetsgivarkontroll.setAttribute(“Diarienummer”, item.getDiarienummer());

        logger.log(Status.INFO, “Starting test execution …”);
        new TestBuilder()
        .addContext(initModel, initModel.getMODEL_PATH(), new AStarPath(new ReachedVertex(“Arbetsgivarkontroll”)))
        .addContext(arbetsgivarkontroll, arbetsgivarkontroll.getMODEL_PATH(), new AStarPath(new ReachedVertex(“BAR_2293”)))

  7. when i m pasting my graphml file inside resources it is showing like “No service provider ‘test.graphml’ found”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.