top of page

FLOW MODEL PATTERN

Table of contents

Introduction

So why publish this only 9 years later?

So what exactly is the Flow Model Pattern?

How do you normally design your test cases?

The Flow Model design

The structure of the Software Under Test

The house diagram - facade over a facade

Soda machine - state machine diagram

The Flow Model design explained with a state machine diagram

Flow Model represented in a Tri-Layer Testing Architecture

Login Flow with diagram and coding examples

References

Introduction

In 2013 I joined an iOS development team of EPAM that was working for Adidas. We worked on all sorts of different fitness applications that were amongst the most advanced and popular fitness apps in the World at the time. Needless to say, I as a sportsman was very happy to be part of such an energetic, young team, making me a proud Hungarian to deliver something meaningful, something that I truly believed in.


The best thing was that doing sports was part of our job. No kidding! One of my colleagues was riding his bike to the office and back, creating test data everyday as part of our smoke tests and sometimes the regression tests as well. We had half yearly airsoft challenges with EPAM, so of course we made most of the people wear all the different gadgets to measure heart rates, strides and whatnot. I became widely known in the company, when I had to provide repeated sudden moves with an at least 30 minutes duration workout. I had my karate suite (gi and belt) with me, so of course I went out to the yard of the office to provide the test data. You can imagine how everyone was surprised to see someone doing karate during working hours. It was fun for sure to see their faces and to have random conversations with them in the upcoming weeks.

So after picking up the domain knowledge and manual testing experience on the project, I became 100% assigned to automation. We already had a working test automation framework, but as I was using it more and more, I became less and less satisfied with some of its features.

I determined the below challenges that I was facing:

  • Speed

  • Reliability

  • Scalabilty

  • Reusability

 

This was the time when Page Object Modeling (nowadays more known as Page Object Pattern) was the big thing. And of course I was using it as well. But it just did not feel right on this project. There was something that made me feel: I need to step away from the POM and go with something that makes more sense on iOS and something that makes more sense as a tester. This is again a long story, so I will detail it out in another article. But what matters now for this article: that was the time when I invented the Flow Model Pattern, sometime around May or June in 2013.

So why publish this only 9 years later?

As I have already presented this at several conferences and meetups, I never really had the urge to write this article. Well, I’m an automation engineer, therefore I’m lazy.

I have improved this design pattern since my first implementation, and I just wanted to experience a little bit more, before I really went widely public with it ultimately on the STAREAST in 2021.

So what exactly is the Flow Model Pattern?

Before going into deep waters with the Flow Model, I encourage you to read on the Page Object Pattern and the State Machine Diagram. The former is the first test automation specific design pattern in our history and the latter is a UML diagram which I came to realize to be a useful one to describe how the Flow Models actually look like.

The Flow Model Pattern is an enhancement of the Page Object Pattern and addresses the following two issues I identified in 2013:

 

The major difference between the two concepts is bringing another facade over the page models called as flow models. The structure of the application is described by the page models, but now none of the actions remain there, instead they are moved to the newly defined flow models, which also store the more complex  and repeated user flows. This way the single responsibility issue is fixed as these separate models have very distinct responsibilities. The reason for change in the page models come from the developers (code change in the application), whilst any change in the flow models come from the testers who define the test cases.

How do you normally design your test cases?

Before moving forward with the main topic, I'd like to describe my process of designing test steps. This will be important in understanding how to design the actual flow models. As I stated before, this concept was invented with a tester's mindset.

For me the most logical way is to slice each step into 3 particles:

  • Precondition

  • Action

  • Assertion

 

Does this sound familiar? Ohh yes, it does! Behaviour-Driven Development uses the Gherkin language, and this is how it looks like:

  • GIVEN: Precondition

  • WHEN: Action

  • THEN: Assertion

 

For single atomic test cases, this is a perfectly good structure. Now what about user flows, end-to-end scenarios? I am lazy as I already mentioned above, and I like to save money for the companies that I work for and even more so: save time for myself in the process. So I do the below trick:

  • Step 1

    • Precondition

    • Action

    • Assertion

  • Step 2

    • Action

    • Assertion

  • Step N

    • Action

    • Assertion

 

Notice how I left out the precondition for each of the test steps except for the first one? That’s because the precondition of each follow-up step is the assertion or postcondition of the previous step.

Let’s see it with the following example: you are delivering goods to families. Your starting position is A. To start your journey, you must be at position A, or otherwise you cannot pick up all the goods to deliver. So the first place you go to is at position B. Your action is leaving position A, taking the route between A and B. Once you arrive to B and delivered the goods for that family, your first task is done. You need to assert that you arrived to B and that the goods were delivered to this family. To be able to start your second task, your precondition is being located at position B. See how that was already validated previously? You don’t need to do that twice, that’s frivolous!

The Flow Model design

Now this is exactly what you will describe in your Flow Models. Each test step will have its own method, just as each of the repeated concatenated steps, hence user flows. The ever boring login flow is a great example to this one. If you need to successfully log in 50 out of 100 test cases, then you definitely do not want to repeat all the steps every time in your test script. Instead, you create one method, which you will call from all of your tests where a successful login is a precondition.

The structure of the Software Under Test

In the flow model pattern, the structure models represent how the pages look like, i.e. how you can interact with its elements that you will be testing. Page models represent web pages. Screen models represent mobile screens. Widgets represent repeated, floating or pop-up elements or group of elements.

Many times it is difficult to decide which page includes certain controls and whether those controls should be the part of a specific page. This is when a widget model can be created. Good examples are: toolbars, menus, shopping carts and alerts. The implementation is the same as of the page and screen models, they are just simply called widgets and are referred to on multiple pages and can be exercised by multiple user flows.

The house diagram - facade over a facade

In the Page Object Pattern, each class file stores all the locators, elements, user actions and user flows that represent the structure and the actions of that given page.

In the Flow Model Pattern, the user actions and user flows provide a facade over the locators and elements, hence forming a double facade over the represented page, screen or widget. The user actions and user flows are detached from these pages and are organized according to application features and typical user journeys.

Publishing
Flow Model Pattern description
Test Case Design
Flow Model Design
SUT structure
House diagram
Introduction
house_facades

Login scenario - state machine diagram

The state machine diagram is a behavioural Unified Modeling Language diagram. It shows transitions between objects.

 

State: stores the status of an object at a given time.
Transition: an event that indicates a change of state.

Soda machine
Login_Scenario_UML_State_Machine_Diagram

The Flow Model design explained with a state machine diagram

The Flow Model can be best represented with a basic UML state machine diagram.

States -> Page Models
Transitions -> Flow Models

The page models include the page/screen and widget models.

Page models represent web UI, Screen models represent mobile UI structures.

The flow models include the simple steps and complex user journeys.

As per the below example, the pages represent the states and you can go from one state to the other by a user action. You can go back to previous states and even remain in the same state for example when typing in your credentials into an edit textbox field.

Flow Model state machine
flow_model_design_diagram

 

Flow Model represented in a Tri-Layer Testing Architecture

As all the application dependent logic is to be stored in the business logic layer, both the flow and structure models are found inside that layer.

Tri-Layer Testing Architecture
flow model pattern tri-layer testing architecture

The page models provide a facade for the web elements, which are called inside the flow models that provide a facade for the test steps (user actions and user flows). The actual test scripts make a call to these facades provided by the flow models.

flow_model_facade_over_structure_model_facade

 

Login Flow with diagram and coding examples

Below I am showing you a very typical successful login scenario example. I'll explain the connections between the different classes, provide coding examples from a very stripped down basic script through leveraging the page object pattern to ultimately using flow models.

First let's look at some of the libraries included.

  • LoginTest: includes the runnable test cases

  • LoginFlow: all the test steps and test flows that the LoginTest calls

  • Page & Widget class files: they expose the web elements to the LoginFlow

  • BasePage: page and widget models inherit this base class file

  • UserAction & BaseFlow: the LoginFlow inherits the UserAction class file. If there's a necessity to provide application specific common user actions, they can be defined inside the Business Layer and the LoginFlow would inherit those app specific class files instead.

Diagram and coding examples
tri-layer_example

1. step: Implement the plain test script

Class LoginTest (Linear Script)

..

solo.clickOnActionBarHomeButton();

solo.waitForText("Login");

 

solo.clickOnButton("Login");

solo.waitForActivity("LoginscreenActivity", 10000);

solo.assertCurrentActivity("Activity did not load in time", LoginscreenActivity.class);

 

solo.clickOnEditText(solo.getView(R.id.username));

solo.typeText(R.id.username, "DarthVader");

 

solo.clickOnEditText(solo.getView(R.id.password));

solo.typeText(solo.getView(R.id.password), "iAMyourF4ther");

 

solo.clickOnView(solo.getView(R.id.loginButton));

solo.waitForActivity("HomescreenActivity", 10000);

solo.assertCurrentActivity("Activity did not load in time", HomescreenActivity.class);

Assert.equals("Welcome, DarthVader!",

((TextView)solo.getView(R.id.welcomeMessage)).getText().toString());

 

solo.clickOnActionBarHomeButton();

solo.waitForText("Logout");

 

solo.clickOnButton("Logout");

2. step: Create the page models

Class LoginPage

..

public View username() { return solo.getView(R.id.username); }

public View loginButton() { return solo.getView(R.id.loginButton); }

public View password() { return solo.getView(R.id.password); }
public View showPassword() { return solo.getView(R.id.showPassword); }

3. step: Refactor test script with the page facades

Class LoginTest (using Page Model)

..

solo.clickOnView(toolbar.layoutDrawer);

solo.clickOnView(menu.loginButton);

solo.clickOnView(loginPage.username);

solo.typeText(loginPage.username, "DarthVader");

solo.clickOnView(loginPage.password);

solo.typeText(loginPage.password, "iAMyourF4ther");

solo.clickOnView(loginPage.loginButton);


solo.waitForActivity("HomescreenActivity", 10000);

solo.assertCurrentActivity("Activity did not load in time", HomescreenActivity.class);

Assert.equals("Welcome, DarthVader", homePage.welcomeMessage);

4. step: Create the flow models

Class LoginFlow

..

public void login.openLoginPage() {

solo.clickOnView(menu.loginButton); }

public void login.typeUsername(String username) {

solo.clickOnEditText(loginPage.username);

solo.typeText(loginPage.username, username); }

public login.typePassword(String password) {

solo.clickOnEditText(loginPage.password);

solo.typeText(loginPage.password, password); }


public login.finishSuccessfulLogin(username) {

solo.clickOnView(loginPage.loginButton);

solo.waitForActivity("HomescreenActivity", 10000);

solo.assertCurrentActivity("Activity did not load in time", HomescreenActivity.class);

Assert.equals("Welcome, "  + username + "!", homePage.welcomeMessage); }

5. step: Refactor test script with the flow facades

Class LoginTest (using Flow Model)

..

login.openSideMenu();
login.openLoginScreen();

login.typeUsername("DarthVader");

login.typePassword("iAMyourF4ther");

login.finishLogin("DarthVader");
login.openSideMenu();

login.tapLogoutButton();

Comparison of the three different approaches

code_comparison

As you can see the Page Model already provides a much more readable format of test case compared to an unstructured script. However, it does not provide the same level of abstractness that Flow Model does, and the script leveraging the LoginFlow facades represents an actual test case with an even better readability.

And that's all she wrote!

 

I do plan to publish more related articles with more examples. I will update this initial article with the links to the new materials as I progress with them.

You can find some example projects on GitHub:

https://github.com/foldhpet/flowmodelpatternjava

https://github.com/foldhpet/playwright_flowmodel

Table of contents

Introduction

So why publish this only 9 years later?

So what exactly is the Flow Model Pattern?

How do you normally design your test cases?

The Flow Model design

The structure of the Software Under Test

The house diagram - facade over a facade

Soda machine - state machine diagram

The Flow Model design explained with a state machine diagram

Flow Model represented in a Tri-Layer Testing Architecture

Login Flow with diagram and coding examples

References

References:

Page object models - Selenium Dev

Page Object - Martin Fowler

UML State Machine Diagrams - UML Diagrams org

UML state machine diagram wiki page

SOLID principles wiki page

Facade Design pattern - blackwasp

Facade pattern wiki page

Originally published on 2022. March 10.

Last updated on 2023. December 10.

References
bottom of page