Keeping Your Test Code Squeaky Clean with the Arrange, Act, Assert (AAA) Pattern
The Arrange, Act, Assert (AAA) pattern is a neat little strategy to help keep your test code cleaner and easier to read and maintain. In this article, we’ll show you the benefits of using this approach to structure your tests.
Keeping your tests readable and maintainable is one of the most important requirements in test automation. The specific goal is to avoid flaky, brittle and expensive tests.
There are several strategies to help us achieve this goal, such as using the Page Object pattern to organize web elements, separating the data from the test logic to avoid code duplication, keeping test cases and functions small, following a naming standard, writing comments in code, etc.
Another approach that can help us to structure our test code and keep it clean is the Arrange, Act, Assert (AAA) pattern, which is often overlooked.
What is the AAA pattern?
The AAA stands for Arrange, Act, Assert, the three logical components that we should include when structuring our tests.
The Arrange part is where we set up our environment, i.e. everything we need to run our test code. This includes initializing objects, dependencies, and all data required for the test case.
The Act part is where we execute the test by calling the functions set up in the previous step.
Finally, the Assert part is where we specify the pass criteria for the test, which fails it if not met, i.e. if the actual results of the test don’t match those we expected.
We will explain each of these steps in more detail below.
The main benefit of the AAA pattern is a clear separation of what is being tested from the setup and result verification, which makes the code easier to read and understand. Better readability helps identify key aspects of our tests, thus helping improve the review, maintenance and debugging of our tests. So, it could be helpful to separate each step visually, e.g. by placing comments or empty lines, like this:
While the AAA pattern is mainly intended for unit tests, this approach can be also used for other types of testing, such as UI, as we’ll show in this article.
Also, it should be noted that there is a similar concept for acceptance criteria in Behavior Driven Development (BDD) called Given, When, Then. There is plenty of argument over whether these two concepts are the same thing or not.
The truth is that the structure of the test is pretty much the same in both styles. The difference is one of the levels of abstraction. The Arrange, Act, Assert pattern describes what the test code does from a more technical perspective, while Given, When, Then approach explains what user actions the test describes.
Using the AAA pattern in an actual test
We’ll use Ranorex Webtestit to take a closer look at each separate phase of the AAA pattern in action.
Ranorex Webtestit simplifies the whole testing process from scaffolding the test environment to using Page Objects to separating data from test logic. Another important thing is that when you create a new test file or generate a new test using snippets in Ranorex Webtestit, it already comes with the AAA pattern added in a form of comments to help you structure your test.
Assuming that you have created Page Objects and added all elements required for the test, you can proceed and create a test file by right-clicking the ‘tests’ folder and selecting ‘New’ > ‘Test file.’
Ranorex Webtestit will create a new test file with comments suggesting how to use the Arrange, Act and Assert steps when structuring your test.
To show how to put the AAA pattern into use, we will create a simple test that opens the shopping page, adds items to the cart, places an order, and asserts that the amount for ordered items is correct. Each part will be explained separately.
As we said, the Arrange part is where we prepare things for our test. In this case, that would be setting up a driver and opening Ranorex Webtestit Demoshop page that we’re going to use for this test.
The Arrange part is usually done manually, which can be a bit of a hassle as some scenarios may be more complicated than others.
However, the driver instance will be created automatically after you have created a new test file using Ranorex Webtestit, so you don’t have to worry about that setup code.
Also, the real preparation part is actually done in Page Objects, so all you need to do in the test is to right-click into the code editor and select “Instantiate Page Object” at the bottom of the context menu, as suggested by the Arrange comment.
Choose the Page Object from the list. For the Arrange part, we’ll select the Page Object for the items overview page and change the address to https://demoshop.webtestit.com/.
The code will look like this (Java example):
After completing this step, we can proceed to the Act part.
In this step, we want to:
- Add all three items from the Items Overview page to the cart
- Perform a checkout
- Fill out the form and place an order
We will instantiate three Page Objects for cart, checkout, and confirmation phases of the test in the same way we instantiated the Page Object in the Arrange step.
This way, all methods from the Page Objects can be easily called with just a few clicks.
The code for our Act phase will look like this:
We can then proceed to the final step to confirm that our system under test has behaved as expected.
Assert is an evaluation step in which we compare the actual test result with the expected result.
In this test, we added three items in the cart and we expect the total amount to be €3,700.00.
You could use
Assert.assertTrue(actual==expected), but it is a better practice to use
assertEquals because this method provides both actual and expected values, which can be very useful when debugging a failure.
Also, we don’t have to write any teardown code, because Ranorex Webtestit also takes care of the cleanup after the completion of test methods.
So, in the end, our test will look like this:
In this article, we demonstrated how the AAA pattern could help structure our tests in such a way that we can easily differentiate between each separate phase from a test setup to the verification of results. Implementing this practice in our workflow ensures better readability and easier maintenance because anyone from our team can look at the test code and learn what behavior has been verified and why it has worked.
The code examples used in this article are from the Java Demoshop project that can be downloaded from our GitHub repository.
The Demoshop samples are also available for TypeScript and Python, two languages also supported by Ranorex Webtestit.
These projects can also be found in the Samples section when you download a free, full-featured trial of Ranorex Webtestit.