2.50/Automated Testing/Scripting Guidelines
In order to have useful and robust scripts, and to extend script's life among QA cycles, there's a list of best practices.
Contents |
Base URL
The whole test suite should have a centralized way to change target URL. I should be able to change it on just one place and that must make all scripts to point to new URL.
Example: I have to test a 2.40 release located at http://127.0.0.1:8180/openbravo240 a 2.50 project located at developers machine http://192.168.0.1:8880/openbravo and a daily build smoke test at http://192.168.114.1/openbravo_postgres
So, script should not have hard-coded URLs:
Script 1 (Wrong)
browser = new DefaultSelenium("localhost", 4444, "*chrome", "http://127.0.0.1:8180/");
Script 2 (Wrong)
browser = new DefaultSelenium("localhost", 4444, "*chrome", "http://127.0.0.1:8180/");
Instead of that, a config file should be created:
Config file
baseURL = "http://127.0.0.1:8180/"
Script 1 (Correct)
browser = new DefaultSelenium("localhost", 4444, "*chrome", baseURL);
Script 2 (Correct)
browser = new DefaultSelenium("localhost", 4444, "*chrome", baseURL);
Browser
The same as above, if I have to repeat the same test on Firefox 2, Firefox 3 and Internet Explorer, the browser should be also a parameter.
Note:Currently some scripts will only work with *firefoxproxy mode. This scripts will remain hard-coded. |
Avoid duplicated code
Scripts are usually recorded following user's steps. That means that recorded scripts will repeat code if the same task is needed in different scripts.
To avoid this problem, after recording a new script, it should be analyzed to factor code onto functions or sub classes.
The most relevant example is Login. If I have
browser.type("user", "userA"); // enter the password browser.type("password", "userA"); // click login button browser.click("buttonOK");
on every page, and something change on Login page (for example, buttonOK name is changed to loginButton) a full search and replace will be needed.
Instead of that, a single function will make the change trivial and also the main script will keep cleaner
Before factoring
...some selenium code... browser.type("user", "userA"); // enter the password browser.type("password", "userA"); // click login button browser.click("buttonOK"); ...more selenium code...
After factoring
...some selenium code... doLogin("userA", "userA"); ...more selenium code...
Use assertions
Assertions are the basis for deciding if a script executed correctly or not. These are the must have assertions for all scripts:
- The initial step of the script was executed
- The last step of the script was executed
- All the Process completed messages appears.
- The Issues to verify section of testcase scenarios.
Example: Consider this test case:
- Steps for Import language:
- Login as Openbravo/openbravo
- Go to General setup->Import/Export translations
- Select Italian(Italy) language
- Click on Import button
- Compile the application and restart tomcat
- Issues to verify:
- Login as Openbravo/openbravo, change on Role Information the language into italian and verify main menĂº and other windows are shown in correct language
In this case, a sub script should be added at the end of the main script:
...some Selenium code... ...launch of compiling process selenium.assert(doVerifyLanguage()); ...more Selenium code...
boolean doVerifyLanguage() { doLogin("Openbravo","openbravo"); doChangeRoleAndLanguage("SampleClientAdmin","italian"); //Verify a menu entry selenium.assert(cell(254,2),"Ciclo Ativo") //Verify a Sales Order field selenium.click(cell(269,2)); selenium.click(cell(289,2)); selenium.click(cell(291,2)); selenium.assert(paramDate.label,"Data") }
Note:Assertions should use the message parameter in order to provide a better understanding in case of failure. |
Element referencing
It is very important to use absolute references, such ID and Name, so changes on interface layout will not affect execution. Avoid using DOM references like
table[@id='grid_table']/tbody/tr[1]/td[2]
unless is the only way to get a reference.
Note:While scripting, a list of elements that only can be referenced using DOM will be made, so we can feed a request to Engineering team for adding new references. |
Element constants
All HTML elements referenced by a test should be coded as constants. And scripts should use the HTML elements only through its constants. This way, if the identifier of the element changes, we will require to change only the assignment of the constant. In addition to that, there are elements that are being located by their xpath. This is not the optimal way to locate elements, so for those we should file a bug to the ERP asking for an identifier, and use the xpath only temporarily. As soon as the bug is fixed, the identifier should be placed instead of the xpath. Again, this will represent only a change on the constant assignment.
Example:
/** Identifier of the file input field. */ private static final String FILE_INPUT_FILE = "inpFile";
Parameterized test cases
All tests should be coded in two parts:
- A generic test script that can be reused with different values for other tests.
- A scenario class that has the specific data to execute a test.
The test script will have the definition of test data as attributes. It will also have a function annotated with @Test, that's where all the steps to execute the test are called in sequence. This @Test function will call functions passing the attributes as parameters.
The scenario class is where the generic attributes of test script are assigned with a value. This class will have a function annotated with @Parameters, that will return a collection with the data specific to the test.
Comments
All classes, attributes, functions and parameters have to be clearly documented, following the coding conventions
Proper logging
In case of an error, the exact point of the error should be logged, so the QA team could easily verify error's origin.
- Sometimes the error is a bug that should be reported.
- Sometimes the application changed and the script should be updated.
- Sometimes is a environment issue.