Perhaps the greatest contributor to low-maintenance scripts is using component or modular scripts. This way, if a change needs to be made which influences many scripts, we may only have to make a change in a single location. Also, we may be able to very quickly assemble new journeys by combining previously defined components. Ghost Inspector has always supported this approach, and has made a few recent improvements to further enhance the ease of using modular tests. For this post, we’ll focus on a single example, starting from the initial test design phase through to implementation.
- Worked Example
- Ghost Inspector documentation link – https://ghostinspector.com/docs/modularizing-tests/
Understand the need to modularise
Although we might start with a small suite with short tests, we expect our coverage to grow over time. Dividing our journeys into logical smaller pieces not only helps to avoid step repetition, but can also make our scripts easier to follow and maintain. Using modular scripts also paves the way for rapid creation of new journeys and path variations, as we can piece the core of the journey together with our module scripts. Neglecting to modularise could leave us with very long scripts and the need to make changes in many places after a change in the site under test.
Visualise the paths through the site under test
When designing our tests, it’s critical to have a strong understanding of the different paths a user can take and how likely each of those paths is to occur. With this in mind, we can understand the scope of our journey coverage and the priority with which we should approach them. Try to understand the common parts of every journey and the main decision points that can lead a user down a different path. One approach to aid understanding and structure is to try to model the basics of the user journey, which can be particularly helpful if more than one person is developing tests.
Plan, but don’t over-document
While it’s beneficial to plan your automation approach in advance, you should be careful not to over-document. Prescribing the approach reduces the possibility to deviate, adapt and react to what is discovered in implementation. It’s important to ensure any documentation you have produced is current – the less you have, the more likely it is that you can make sure this is the case.
What this article aims to highlight is that it’s important to be thinking about the efficiency and maintainability of your suite as you develop it. However, as long as you have this intention, you shouldn’t worry about whether your scripts are perfect. Your suite will evolve over time, progressing iteratively. If you realise your original approach is causing unnecessary maintenance, have a look at how you could rework the scripts to avoid the overhead.
Find the right level of granularity
There’s a balance between efficiency of our suite of scripts and the overall usability of them. We must assume that someone else will need to understand our tests. The temptation can be to avoid almost all duplication of test steps, resulting in many modules and multiple tiers of hierarchy of module import in our scripts. We must accept that some duplication will be needed in order to aid the ease of understanding of our suite. Finding the right balance is a necessary skill.
There may be a single step that is used in most scripts, but it makes sense to have it alone rather than as part of a larger component script. There are a few options with handling this. The first is to just put this step into each script. If it’s sensitive to change, we shouldn’t do this, as it will need to be updated in many places. An alternative is to create a component script for this one step. The issue here is that a component script for a single step can often be wasteful, and comes at the expense of a suite which is harder to understand and maintain.
Make your modules flexible
When you’re writing scripts that will be utilised multiple times, usually in different contexts, there’s a greater necessity to make those scripts flexible. We need to build them in a way that they can still be robust when run under different conditions. The best way to accomplish this is through use of variables and conditional steps. Moving the majority of data population and verification steps to use variables allows these values to be set from outside the module. Using conditional steps can allow the component to handle a series of sub-paths based upon the context in which it is run.
Visualising the journeys
While me might feel we have a good understanding of the site under test, with its core journeys and branching paths, it can be useful to visualise this in a diagram. We’ve used the example of wiggle.co.uk below. This is just a simplified example – you should aim to cover all main permutations of customer journey, also encompassing the admin processes that occur after the customer has completed their journey.
As a starting point, this gives us an idea of how we might want to modularise our customer journeys. Add to Basket and Proceed to Checkout immediately stands out as a key part of the journey to gain a benefit from being a separate module – all journeys include this component. We can also assess how many times each other element is likely to be included in our planned journeys in order to craft our approach. Let’s imagine we want to cover the following basic paths in our Ghost Inspector suite:
|Journey||Product Discovery||Checkout Entry||Delivery Method||Payment Method|
|J1||Search (PD1)||Registration (CE1)||Standard (DM1)||Debit/Credit Card (PM1)|
|J2||Catalogue Browse (PD2)||Existing Customer (CE2)||Standard (DM1)||Debit/Credit Card (PM1)|
|J3||Direct Link (PD3)||Existing Customer (CE2)||Priority (DM2)||Debit/Credit Card (PM1)|
|J4||Catalogue Browse (PD2)||Registration (CE1)||Next Day (DM3)||PayPal (PM2)|
|J5||Search (PD1)||Existing Customer (CE2)||Collect+ (DM4)||PayPal (PM2)|
Implementation and refinement
Through creation of our scripts, we begin to notice specifics and adapt our original understanding to cope with these new discoveries.
When working through Product Discovery, we make a number of notable observations. PD3 is merely a direct link to a URL, so there’s no need to create a new script just for this. For PD1, it’s likely we’re going to want to use a flexible search query so we can use different search terms for each journey, or perhaps even make use of data-driven testing to run the tests with the most popular search terms. Therefore, we can use a variable within the Search module script and pass the value in from outside.
We notice that, by default, the Catalogue pages display out of stock products. This is not helpful for us, as we want to be certain that we can purchase the product we select. Therefore, we introduce a new module to remove OOS products and select a product. As ever, when we identify the potential to introduce a new module script, we consider the efficiency gains versus the added complexity.
In Checkout Entry, we notice that additional steps are required for new customers, as they will also need to enter a new address during checkout. For existing customers, we can use their default existing billing and shipping address(es). It’s highly likely we will want separate components for address creation, rather than including in CE1, so we can utilise these steps for existing customers if we want to.
While we can expect the Delivery Method to impact upon Warehouse fulfilment and dispatch, the front end customer journey actually only amounts to choosing between a series of radio buttons. Therefore, there’s very little benefit to having each of these as a separate script. Let’s use a single script to hold all these path choices. Eventually, we will use conditional steps and testing flags to control the path – look for a future article covering this.
Updating our understanding
Through implementation, our understanding of the site under test improves, likely resulting in documentation requiring updating. The reworked customer journey flow diagram illustrates what has changed as a result of a deeper understanding.
Configuring the tests in Ghost Inspector
Suite of script modules
These are our final test modules (or components). Notice how the correlate (and differ) from the final journey diagram above.
You will notice that all scripts are indicated in Ghost Inspector as Import Only. This is a relatively new feature, which can be enabled from the Script Settings:
Once enabled, we can see an overview of the journeys which inherit this script while still in the Settings panel:
If we access the test, the page where we would usually expect to see the most recent test run result now indicates the inheriting journey scripts. Reviewing this periodically can help us to spot potential script redundancy or duplication:
Suite of user journeys
The journey scripts themselves are placed in a separate suite in order to improve the usability of our test suites. As with the modules, we should always try to concisely describe the scope of the script in our naming:
Journey steps example
The following example shows how the Inherit steps from test step enables us to piece together our journeys with modules. This should provide an indication of how easy it would be to create a new journey script variation. While we still need some additional steps that are unique within the scope of the journey, the majority of the script is constructed using the Inherit step type: