Automated tests at Openbravo should be reusable and stable, but not too complex.
With this in mind we have chosen a design that's not so fast to implement as the recorded tests; and that is not so slow as a multilayered mirror of the application.
On the other hand, this design is more flexible and harder to break than recording scripts. However, it's not so reusable as the multiyared approach.
It's a compromise between stability and time.
It's based on the Screen Object pattern, where every frame or window on the application has its own Object that encapsulates the elements present in the screen and the actions and verifications that can be done with those elements.
Tests for Openbravo ERP using selenium RC - Java have two groups of clases: screen definitions and test controllers. Every test has one controller and can use as many screen definitions as required.
There has to be a class for every section of the application interface. This classes contain the definitions of interface elements (buttons, text fields, links, combo boxes, tables, etc) and all the possible actions that can be done with those elements.
For example, there's a class for the Purchase Order screen, and there's another for the Delete Client screen. In addition, there are classes for the Login screen, the menu frame, the product selector pop up, and many others.
Interface elements are defined as a Java constant, and it's value must be the same as the element's identifier on the HTML file.
/** Identifier of the new button */ private static final String BUTTON_NEW = "buttonNew";
Every class has the definitions of elements present in the screen that it represents. They can't have definitions of elements from other screens.
The functions defined on a screen class execute and verify actions that can be done using the elements present in the screen they represent. They can't execute or verify actions from other screens.
In addition, they can serve as a controller for the pop ups that appear pressing the buttons in the screen. For example, this means that a function defined in a screen class can press a button that opens a selector; and call the function in the pop up that selects the required data.
This is a quick overview of the main classes. For further details refer to the javadocs.
It has the definition of all the elements in the login form: user and password text fields and login button.
This class has 3 functions, that define the possible actions that can be done on this screen:
- open() - opens the login screen
- login(String userName, String password) - fills the userName and
password, clicks the login button and waits for the page to load
- verify(boolean logged, String username) - verifies that the user was
logged or not. If the result (i.e. the page loaded after clicking the login button) is not the expected, errors are logged.
Note: there's also a Logout class that contains the definitions of elements and actions necessary to perform a logout and verify that it succeeded.
Every folder, subfolder and link that is shown in the menu must be defined in this class as a public constant.
/** Initial Client Setup menu item */ public static final String INITIAL_CLIENT_SETUP = "childform225";
This class has only one function, that clicks a sequence of menu items and waits until the requested page is loaded.
This is a base class. All the form windows in the application must extend this class, because it defines all the common components and actions that are present on form screens.
This is a base class. All the process windows in the application must extend this class, because it defines all the common components and actions that are present on process screens.
This is a base class. All pop ups in the application must extend this class, because it defines all the common components and actions that can be done on pop ups.
There are some other classes that are more specific types of pop ups, like Selector and Filter.
This is the box that displays messages on the application. This class is used when a message has to be verified. It logs errors if the message displayed is not the expected, or if no message was shown.
Test controllers specify the actions that have to be done on windows in order to complete a test.
Most tests should independent GUIUnit test that use DbUnit to handle its dependencies (if any).
The tests of some suites will depend on other tests of the same suite, but this will be done only on some qualified cases. For example, the Smoke Suite that tests a the use of the application using the most common flows in sequence.
They are classes that extend the base test class OpenbravoERPTest (com.openbravo.test.integration).
For example, the initial client setup test has the following steps:
- Click initial client setup menu item
- Fill client data
- Click Ok
- Verify the message displayed
Thus, the test controller for the initial client setup has to:
- Call the login function of the Login class with the user name and password.
- Call the select function of the Menu class with all the menu items that have to be clicked to show the Initial Client Setup screen.
- Call the function of the Initial Client Setup process window that fills the text fields, checks the required check boxes, and clicks the ok button.
- Call the function that verifies the message displayed.
- Call the logout function of the Logout class.
More complex tests would require to use more classes. For example, if the tests says that a Business Partner has to be created and then a Bank using the previously created partner, the classes corresponding to those screens have to be used.
Every test must have at least one function with the @Test annotation. You can find more details on How to automate a test case.