Login, search, create a profile are common things you have to do everywhere. eCommerce sites have “add to cart”, “view cart”, and checkout, while content-creation sites have tag, post, upload image, and edit a page. We can get enough understanding about these terms, easily enough, without even bothering to define the term pattern. So how do we test them?
Let’s start with Login.
Reusable Login Methods
The first thing you need to do in many application is login. It is a blocking condition. The way most testers solve this is by having two different tests. First, they test all the combinations of login, including the interesting failures, as one artifact. Then they have a simple, reusable login script, that appears at the top of every screen. This method combines four commands – type into username, type into password, click submit, wait for confirmation text that you are logged in, typically “hello, [full name as described in profile].” The screen might also verify some standard logged-in elements, or do an image compare. The simplest strategy is to cut and paste this into every test.
Then one day, something happens. The developers add a new field, “company id”, to login, in order to enhance security, like the below example. This is a real screen capture from a regional bank in the United States, which added the ‘commercial’ login flow, which has an additional text field.
All of a sudden, every single method fails. If the code is stored in plain text, a clever programmer can write a search-and-replace algorithm to fix it.
Then again, a clever programmer would have used a code snippet in the first place.
The Code Snippet
Most tools have a way of creating a snippet of reusable logic. The visual tools often create this as a sort of encapsulation. That is, create these four or five visual commands, then collapse them into a virtual command that can be cut and pasted around.
That has the same problem as general cut and paste.
What you want to do is create a method, or function, that can be stored in an external library. That library should be under version control, which we’ll discuss later. When the user interface changes to add a new field, the code only needs to change in one place, that code library. Make the change once and all the tests that failed suddenly pass. Problem solved.
In the case of login, we have some ‘pre-canned’ information. Username, password, and possibly, what to expect on the other side. If we change these to variables, then we can pass in a non-username, an invalid password, and expect an error message. This means our test software needs the capability to pass in variables.
We also want the ability to create variables on the fly. For example, we may want to create users in entirely different billing structures and make sure they cannot find each other with search. Or we may want to run multiple tests at the same time, and make sure those users have different names. My favorite way to do this is to user a date-time-stamp and stick it in a variable. For example “acount20180509130010010101” and “[email protected]” A code snippet can generate these. If you need to actually check those emails for received mail, consider using emails with a mailinator.com domain.
Once the pattern for snippets exists for login, you’ll find yourself making all kinds of snippets. Search is particularly easy – search for (term) expect (result text). Starting with a canned, known database of records, or at least one where you can calculate the result, search for terms and show how the search works. The result text could be “Showing 1-20 of 200”, along with the specific results – and these could be in order. Regular expressions are a great way to check order. For example:
/Test Results[\w\W]*Test Planning[\w\W]*Test Execution/
This code matches the three test terms in specific order, separated by any number (*) of word (\w) or non-word (\W). characters … which is anything. Here’s a similar code to match a div with the same text in Ranorex Studio:
div[@text~’Test Results[\w\W]*Test Planning[\w\W]*Test Execution’]
Snippets have different nicknames – in some tools they are called methods, functions, modules, or “user code”. Once you can add variables and regular expressions to your snippets, the opportunity to use them seems to pop up all over the place. The page object pattern is an attempt to define test automation itself in terms of reusable business functions (like login and search) then compose tests out of those functions. To the extent your tooling consists of code (as opposed to visual representations) it is a fantastic, if often misunderstood, place to start.
Use snippets enough and you see everything as a potential snippet.
Except sometimes you don’t want to go through the UI, and want to work at a lower level.
Command-Line Problems Vs Through the UI
Create a profile, in many ways, feels like login. Enter values into these fields, upload an image, confirm the results. If you leave a required field blank, see the correct error. All scriptable, all reusable.
Sometimes, though, you want to create a bunch of accounts. Perhaps you need three – two in the same account, to see each other when they search, and a third in a separate account.
In that case, calling the functions through the user interface will create delay. What we are doing is not really testing profile create. Instead, profile create is just a blocking condition for what we actually want to test. If I can, I prefer to offload the code from these to somewhere else — somewhere faster. We might store them in a test environment that we restore from disk. More likely, we’ll have a microservice or command-line function we can call to create profiles quickly.
Snippets are so good that we’ll be tempted to overuse them — especially for legacy applications where all the tester can see is the user interface. Don’t make that mistake.
This brings me to the final piece of code snippets – Version Control. If the code snippets (and tooling artifacts) are not versioned directly along with the production code, then the tests will be running against code that is different than the tests expect. The result will be false error reports, which requires the test-code to be “fixed.”
For today, it’s enough to say that all your testing code, including code snippets, should be safely stored under version control. Ideally in the same repository and branch as the production code.