When it comes to test automation you probably use a framework of your own and has a model of the test cases. For example you will have your Util classes. When you write the UI test cases it might bee necessary to set some environmental values etc. using these Util classes. In such scenarios you will need to generate a customized test class which is different from the default class structure generated by Selenium IDE.
I will provide a few scenarios as examples and how to customize the templates accordingly.
I will consider the default template provided by for 'Java / JUnit 4 / WebDriver' as the base.
Calling your own classes within the test case
We will consider a scenario where you want to include the test case into a set of existing test case set. You have written all other test classes by extending a common class and you need call methods in the parent class within the test class.
Following is the start of a test class generated by exporting using 'Java / JUnit 4 / WebDriver'
package com.example.tests;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;
public class Test {
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
@Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
baseUrl = "http://techspace-ps.blogspot.com/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
We need to change the following sections in order for this test class to fit into the rest of the test classes.
So when we generate 10 test classes, we will have this method in each of them. When all those test classes are put together, it seems to be a bad practice to have the same method everywhere.
You can easily move the method to the base test class, so that it is available to all the test classes by inheritance. In that case you just need to stop the method generating for each class through modifying the template.
You need to remove the lines relevant to such private methods from the 'options.footer' section.
I have generated the same test using the default template and our customized template. You can compare the differences...
In the next post I will explain how to use this JUnit 4 based template to generate testNG based test classes with simple modifications as above.
- The package name
- Add imports
- Extend another class
- Take WebDriver through another class
Now let's see how we can do these.
- Open Selenium IDE
- Go to Options > Options
- Open Formats tab
- Select 'Java / JUnit 4 / WebDriver'
- Click on Source button on the bottom
- Copy and paste the content into a Text Editor
First give a new name to the customized template. (Let's say OurTemp)
Edit 'this.name' property to include the new name.
this.name = "OurTemp";
To change the package name,
Edit 'this.options' section as follows
this.options = {
receiver: "driver",
packageName: "our.test.sample",
indent: '2',
initialIndents: '2',
showSelenese: 'false',
defaultExtension: "java"
};
By editing options.header section you can add new imports and extend a another class.
Also you can use the methods of parent class as well.
options.header =
"package ${packageName};\n" +
"\n" +
"import java.util.regex.Pattern;\n" +
"import java.util.concurrent.TimeUnit;\n" +
"import org.junit.*;\n" +
"import static org.junit.Assert.*;\n" +
"import static org.hamcrest.CoreMatchers.*;\n" +
"import org.openqa.selenium.*;\n" +
"import org.openqa.selenium.firefox.FirefoxDriver;\n" +
"import our.sample.import.BaseTest;\n" +
"import our.sample.import.BrowserManager;\n" +
"import org.openqa.selenium.support.ui.Select;\n" +
"\n" +
"public class ${className} extends BaseTest{\n" +
indents(1) + "private WebDriver driver;\n" +
indents(1) + "private String baseUrl;\n" +
indents(1) + "private boolean acceptNextAlert = true;\n" +
indents(0) + "\n" +
indents(1) + "@Before\n" +
indents(1) + "public void setUp() throws Exception {\n" +
indents(2) + "super.init(userMode);\n" +
indents(2) + "driver = new FirefoxDriver();\n" +
indents(2) + "baseUrl = \"${baseURL}\";\n" +
indents(1) + "}\n" +
indents(0) + "\n" +
indents(1) + "@Test\n" +
indents(1) + "public void ${methodName}() throws Exception {\n";
Moving Selenium generated util methods to a separate class
If you have generated test classes using Selenium IDE, you must have noticed following method at the end of each test class.
private boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
You can easily move the method to the base test class, so that it is available to all the test classes by inheritance. In that case you just need to stop the method generating for each class through modifying the template.
You need to remove the lines relevant to such private methods from the 'options.footer' section.
options.footer =
indents(1) + "}\n" +
indents(0) + "\n" +
indents(1) + "@After\n" +
indents(1) + "public void tearDown() throws Exception {\n" +
indents(2) + "driver.quit();\n" +
indents(2) + "String verificationErrorString = verificationErrors.toString();\n" +
indents(2) + "if (!\"\".equals(verificationErrorString)) {\n" +
indents(3) + "fail(verificationErrorString);\n" +
indents(2) + "}\n" +
indents(1) + "}\n" +
indents(0) + "\n" +
indents(1) + "private boolean isElementPresent(By by, WebDriver wd) {\n" +
indents(2) + "try {\n" +
indents(3) + "driver.findElement(by);\n" +
indents(3) + "return true;\n" +
indents(2) + "} catch (NoSuchElementException e) {\n" +
indents(3) + "return false;\n" +
indents(2) + "}\n" +
indents(1) + "}\n" +
indents(0) + "\n" +
indents(1) + "private boolean isAlertPresent() {\n" +
indents(2) + "try {\n" +
indents(3) + "driver.switchTo().alert();\n" +
indents(3) + "return true;\n" +
indents(2) + "} catch (NoAlertPresentException e) {\n" +
indents(3) + "return false;\n" +
indents(2) + "}\n" +
indents(1) + "}\n" +
indents(0) + "\n" +
indents(1) + "private String closeAlertAndGetItsText() {\n" +
indents(2) + "try {\n" +
indents(3) + "Alert alert = driver.switchTo().alert();\n" +
indents(3) + "String alertText = alert.getText();\n" +
indents(3) + "if (acceptNextAlert) {\n" +
indents(4) + "alert.accept();\n" +
indents(3) + "} else {\n" +
indents(4) + "alert.dismiss();\n" +
indents(3) + "}\n" +
indents(3) + "return alertText;\n" +
indents(2) + "} finally {\n" +
indents(3) + "acceptNextAlert = true;\n" +
indents(2) + "}\n" +
indents(1) + "}\n" +
indents(0) + "}\n";
Alternatively, we can write a util class in our test package and move this method in to that. When doing that we will also have to pass the 'driver' instance as a parameter. So the new method will look like following. public boolean isElementPresent(By by, WebDriver driver) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
With this change you will have to stop the method generation using the same approach as above. Additionally, you need to modify the template to change how this method gets called. (Include the argument in method call)WDAPI.Utils.isElementPresent = function(how, what) {
return "isElementPresent(" + WDAPI.Driver.searchContext(how, what) + ", driver)";
};
So the customized template is still on the text editor. Let's add it to Selenium-IDE.- Goto Selenium IDE
- Go to Options > Options
- Open Formats tab
- Click Add button on bottom-left corner
- Copy and paste the template into the new window replacing its source content and add the name you added in the source, to the top field
- Save the new template
- Restart IDE
- Record a test
- Go to 'File > Export Test Case As' menu
- Select the new template ('OurTemp')
- Save the test with a proper name and correct file extension
I have generated the same test using the default template and our customized template. You can compare the differences...
Test generated with default template
package com.example.tests;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;
public class Blog {
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
@Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
baseUrl = "http://www.seleniumhq.org/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
@Test
public void testBlog() throws Exception {
driver.get(baseUrl + "/projects/ide/");
try {
assertTrue(isElementPresent(By.linkText("Browser Automation")));
} catch (Error e) {
verificationErrors.append(e.toString());
}
}
@After
public void tearDown() throws Exception {
driver.quit();
String verificationErrorString = verificationErrors.toString();
if (!"".equals(verificationErrorString)) {
fail(verificationErrorString);
}
}
private boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
private boolean isAlertPresent() {
try {
driver.switchTo().alert();
return true;
} catch (NoAlertPresentException e) {
return false;
}
}
private String closeAlertAndGetItsText() {
try {
Alert alert = driver.switchTo().alert();
String alertText = alert.getText();
if (acceptNextAlert) {
alert.accept();
} else {
alert.dismiss();
}
return alertText;
} finally {
acceptNextAlert = true;
}
}
}
Test generated with customized template
package our.test.sample;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import our.sample.import.BaseTest;
import our.sample.import.BrowserManager;
import org.openqa.selenium.support.ui.Select;
public class Blogtest extends BaseTest{
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
@Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
baseUrl = "http://www.seleniumhq.org/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
@Test
public void testBlog() throws Exception {
driver.get(baseUrl + "/projects/ide/");
try {
assertTrue(isElementPresent(By.linkText("Browser Automation")));
} catch (Error e) {
verificationErrors.append(e.toString());
}
}
@After
public void tearDown() throws Exception {
driver.quit();
String verificationErrorString = verificationErrors.toString();
if (!"".equals(verificationErrorString)) {
fail(verificationErrorString);
}
}
}
Hope this helps ...In the next post I will explain how to use this JUnit 4 based template to generate testNG based test classes with simple modifications as above.
No comments:
Post a Comment