Start the Chrome Browser with Extensions

You may need sometimes to run test automation scripts in the Chrome browser using Chrome extensions.

By default, when any browser is started by Selenium, no extensions are added to it.

Also, all browser options are the default ones.

There are 2 ways of starting Chrome with extensions.

 

1. Use a Custom Chrome Profile

The following steps can be used for starting Chrome with a custom profile:

  1. Create a folder for the new custom browser profile (example: C:\Selenium\BrowserProfile)
  2. In the Chrome bar, run the following command: chrome://version/
  3. Copy the Chrome executable folder path value

 

chrome version

4. Open Command Prompt

5. Go to the Chrome executable folder path using the following 2 commands:

cd /

cd C:\Program Files (x86)\Google\Chrome\Application

5. Execute the following command:

chrome -user-data-dir=C:\\Selenium\\BrowserProfile

6. The Chrome browser is opened and a new profile is created in the C:\Selenium\BrowserProfile folder.

7. Add a new extension to Chrome by going to

Settings–> Extensions –> Get More Extensions

8. Close the browser

9. Add the needed settings to the Selenium code:

 

public class TestClass {

WebDriver driver;

 

@Before
public void setUp() {

System.setProperty(“webdriver.chrome.driver”, “C:\\Selenium\\BrowserDrivers\\chromedriver.exe”);

ChromeOptions options = new ChromeOptions();

options.addArguments(“user-data-dir=C:\\Selenium\\BrowserProfile”);

options.addArguments(“–start-maximized”);

driver = new ChromeDriver(options);

}

 
@After
public void tearDown() {

driver.quit();

}

 

@Test
public void testScript() {

Thread.sleep(10000);

}
}

 

10. Run the code; the Chrome browser is opened and the new extension is added to it

These steps are also useful if other custom settings have to be set for the browser.

 

chrome extension

 

2. Load a Chrome Extension

The following steps can be used for loading Chrome with an extension:

  1. Run the following url in Chrome: chrome://extensions/
  2. Enable the developer mode
  3. Copy the id of the extension

developer mode

 

4. Run the following url in Chrome: chrome://version/

5. Copy the Chrome profile path

chrome profile path

6. Open the Chrome profile path in Windows Explorer

7. Open the Extensions folder

8. Open the folder that has the name equal to the extension id from step 3

9. If there is a version subfolder in the extension folder, open it

10. Copy the folder path

extension folder

11. Add the needed settings to the code:

public class TestClass {

WebDriver driver;

 

@Before
public void setUp() {

String pathToExtension = “C:\\Users\\home\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Extensions\\mbopgmdnpcbohhpnfglgohlbhfongabi\\2.3.1_0”;

ChromeOptions options = new ChromeOptions();

options.addArguments(“–load-extension=” + pathToExtension);

driver = new ChromeDriver(options);

}

 

@After
public void tearDown() {

driver.quit();

}

 

@Test
public void testScript() {

Thread.sleep(10000);

}
}

12. Run the code; the Chrome browser is opened and the new extension is added to it

 

chrome extension

 

Advertisements

How to Take Screenshots if The Selenium Script Fails

Taking a screenshot when your Selenium WebDriver script fails is a very useful technique.

It shows you the page where failure has happened.

The best way of taking the screenshot is through JUNIT rules.

 

 

bugs bunny upset

 

Incorrect Way of Taking a Screenshot

A short example will be used for our “take screenshot” discussion.

The example automates a very simple test case that

  1. opens the http://www.vpl.ca site
  2. executes a keyword search
  3. verifies that the number of results is greater than 0

 

The example uses the following classes:

  • TEST CLASS
    • the test class extends a test base class
    • it has 1 test script only
    • the test script uses page objects and assertions

 

  • TEST BASE CLASS
    • it is used for setting up and cleaning the test environment

 

  • HOME PAGE CLASS
    • it implements the user actions related to the home page (open page, search)

 

  • RESULTS PAGE CLASS
    • it implements the user actions related to results page (get results count)

 

  • SCREENSHOT CLASS
    • it takes a screenshot of the current page

 

TEST CLASS

public class HomePageTests extends TestBase{

String keyword = “java”;

 

@Test
public void searchReturnsResults() throws Exception {

HomePage homePage = new HomePage();

homePage.openIn(browser);

ResultsPage resultsPage = homePage.search(keyword);

assertTrue(resultsPage.getResultCount() > 0);

}

}

 

TEST BASE CLASS

public class TestBase {

public static WebDriver browser;

 

@BeforeClass
public static void setUp() {
browser = new Driver().get();
}

 

@AfterClass
public static void tearDown() {
browser.quit();

}

}

 

HOME PAGE CLASS

public class HomePage {

By searchTextBoxId = By.id(“globalQuery”);
By searchButtonLocator = By.xpath(“//input[@class=’search_button1′]”);

String url = “http://www.vpl.ca”;

WebDriver browserDriver;

 

public void openIn(WebDriver driver) throws Exception
{
try
{
browserDriver = driver;
browserDriver.get(url);
}
catch (Exception ex)
{
new Screenshot(browserDriver).capture(“HomePage class – openIn method”);

throw new Exception(“site cannot be loaded”);
}

}

 

public ResultsPage search(String keyword) throws Exception {

try
{
WebElement searchTextBox = browserDriver.findElement(searchTextBoxId);
searchTextBox.sendKeys(keyword);

WebElement searchButton = browserDriver.findElement(searchButtonLocator);
searchButton.click();

return new ResultsPage(browserDriver);
}
catch (Exception ex)
{
new Screenshot(browserDriver).capture(“HomePage class – search method”);

throw new Exception(“search method failed”);
}

}

}

 

RESULTS PAGE CLASS

public class ResultsPage {

By itemCountLocator = By.xpath(“//span[@class=’items_showing_count’]”);

WebDriver browserDriver;

 

public ResultsPage(WebDriver driver)
{
browserDriver = driver;
}

 

public int getResultCount() throws Exception {

int count = 0;

try
{

WebElement resultsCount = browserDriver.findElement(itemCountLocator);

String value = resultsCount.getText();

int index1 = value.indexOf(“of”) + 3;
int index2 = value.indexOf(“items”) – 1;

count = Integer.parseInt(value.substring(index1, index2));
}
catch (Exception ex)
{
new Screenshot(browserDriver).capture(“ResultsPage class – getResultCount method”);

throw new Exception(“result count cannot be determined”);
}

return count;

}
}

SCREENSHOT CLASS

public class Screenshot {

WebDriver driver;

 

public Screenshot(WebDriver driver)
{
this.driver = driver;
}

 

public void capture(String name) {

try {

new File(“src/screenshots”).mkdirs(); 
FileOutputStream out = new FileOutputStream
(“src/screenshots/” + name + “.png”);
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));

out.close();

}
catch (Exception e) {
}

}

}

 

The Screenshot class is responsible for taking a screenshot of the current page of the site and storing it in the /src/screenshots folder.

Each of the page object classes (HomePage, ResultsPage) uses a try/catch block for catching exceptions in each of their methods.

If an exception is caught, a screenshot of the current site page is generated in the catch() block.

 

This approach works well but it leads to a lot of duplicated code that needs to be maintained.

Each method will need to have code for taking the screenshot in the catch() block.

The more classes you have, the more of the duplicated code.

JUNIT rules offer a great way of simplifying the process of taking a screenshot in case of failures.

 

 

 

bugs-bunny

Use JUNIT Rules for Automatic Screenshot Taking

 

JUNIT  Rules allow very flexible addition or redefinition of the behavior of each test method in a test class.

Testers can reuse or extend one of the default Rules or write their own.

The rules are useful in situations when you want to build your own test automation report, when you want to take automatic screenshots, etc.

Read more about JUNIT rules here.

A very good tutorial on JUNIT rules can be found here.

 

How will JUNIT rules help with our code?

 

First,

We create a custom JUNIT rule that takes a screenshot automatically every time an exception is generated in the project:

 

public class ScreenshotTestRule implements TestRule {

WebDriver driver;

 

public ScreenshotTestRule (WebDriver driver)
{
this.driver = driver;
}

 
public Statement apply(final Statement statement, final Description description) {

return new Statement() {

@Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
}

catch (Throwable t) {
new Screenshot(driver).capture(getName(description.getClassName(), description.getMethodName()));

throw t;
}
}

 

private String getName(String className, String methodName) {
return className.substring(className.lastIndexOf(“.”) + 1) + “_” + methodName;
}
};
}
}

 

Second,

We add the JUNIT rule to the test base class:

 

public class TestBase {

public static WebDriver browser;

 

@Rule
public ScreenshotTestRule screenshotTestRule = new ScreenshotTestRule(browser);

 

@BeforeClass
public static void setUp() {
browser = new Driver().get();
}

 

@AfterClass
public static void tearDown() {
browser.quit();

}

}

 

Third,

We remove the “screenshot” code from the page object classes:

public class HomePage {

By searchTextBoxId = By.id(“globalQuery”);
By searchButtonLocator = By.xpath(“//input[@class=’search_button1′]”);

String url = “http://www.vpl.ca”;

WebDriver browserDriver;

 

public void openIn(WebDriver driver) throws Exception
{
try
{
browserDriver = driver;
browserDriver.get(url);
}
catch (Exception ex)
{
throw new Exception(“site cannot be loaded”);
}

}

 

public ResultsPage search(String keyword) throws Exception {

try
{
WebElement searchTextBox = browserDriver.findElement(searchTextBoxId);
searchTextBox.sendKeys(keyword);

WebElement searchButton = browserDriver.findElement(searchButtonLocator);
searchButton.click();

return new ResultsPage(browserDriver);
}
catch (Exception ex)
{
throw new Exception(“search method failed”);
}

}

}

 

How does this work?

Every time an exception happens, the JUNIT custom rule is triggered.

The JUNIT rule generates a screenshot of the current page (the one where the exception occurs).

The screenshot is then saved in the /src/screenshot folder.

 

I hope that this article makes it clear how to take screenshots in your automation projects.

If you liked it, please share it with your friends.

 

 

bugs-bunny-thats-all-folks

 

Run Test Automation Scripts in Command Prompt With MAVEN

While developing the Selenium WebDriver test automation scripts, the scripts are executed within Eclipse.

But as soon as the scripts work as expected, you may want to make the scripts available to other team members.

Like other manual testers.

Or developers.

You may also want to run the test scripts automatically as scheduled jobs.

Or use them in a continuous integration process.

All these require the ability of running the test scripts in the Command Prompt.

Let`s see how you can do this.

We will use an example project that automates the following test case:

  1. opens the home page of the Vancouver Public Library site
  2. checks if the home page title is correct

The project uses 2 classes: test class and home page class.

TEST CLASS

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class TestClass {

  WebDriver driver;

  @Before
  public void setUp() {
    driver = new FirefoxDriver();
  }

  @After
  public void tearDown() {
    driver.quit();
  }

  @Test
  public void testScript() {
    HomePage homePage = new HomePage(driver);
    homePage.open();
    assertTrue(homePage.isTitleCorrect());
  }

}

HOMEPAGE class

import org.openqa.selenium.WebDriver;
public class HomePage {
  WebDriver driver;
  String url = "http://www.vpl.ca";
  String title = "Vancouver Public Library - Home";

  public HomePage(WebDriver driver) {
    this.driver = driver;
  }

  public void open()  {
    driver.get(url);
  }

  public Boolean isTitleCorrect() {
    return driver.getTitle().equals(title);
  }

}

The following phases are needed for running this code from command prompt.

Everything that follows assumes that Maven is installed on your computer.

If you dont have it installed, use this link for instructions.

If you want to learn more about Maven, this is a very good tutorial.

  1. Create the Maven Project

This can be done manually without Eclipse.

Or you can use Eclipse for generating the project:

  • Open Eclipse
  • Click File, New, Project
  • In the New Project window, expand the Maven category
  • Select Maven project and click Next

1. select maven project

  • Check the Create A Simple Project checkbox
  • Click Next

2. maven - create a simple project

  • Configure the Maven project by providing the Group ID, Artifact ID and Name

3. configure maven project

  • Click Finish

The project is created and it shows in the Navigator panel of Eclipse.

You can see the project structure by expanding the project node:

4. maven project structure

The project folder includes

  • SRC folder; includes source code for the test and page object classes.
  • TARGET folder; includes the resources generated by compiling the source code.
  • POM.XML file; it defines the project dependencies

Under the SRC folder, you will find 2 folders:

  • main; the page objects go here
  • test; the test classes go here

When the project is created, the POM.XML file has just a few lines:

5. initial pom file

The project does not have any dependencies added yet.

6. no maven dependencies

2. Add dependencies to the POM.XML file

2 dependencies are needed for our project:

  1. JUNIT
  2. SELENIUM

They are added to POM.XML by editing the file:

8. add junit and selenium dependencies to pom file

The project has now 2 dependencies added to it:

9. junit and selenium are added as dependencies

3. Add the test and page object classes to the project folders

Next, we need to add the test class to the SRC – TEST – JAVA folder.

The page object class is added to the SRC – MAIN – JAVA folder.

10. add class files

4. Execute the Maven Project in Eclipse

The Maven project can be executed by

  • right clicking on the project name
  • clicking Run As
  • clicking Maven Test

11. run maven test

The test script is being executed and the results are displayed in the Console panel.

12. build success from eclipse

After the project execution, you can see the .class files in the TARGET folder of the project:

13. class files are created

5. Run the Maven Project in Command Prompt

First, we need to get the project folder path.

This can be done by

  • right clicking on the project name
  • clicking Properties
  • getting the value of the Location field

14. get project path

The last steps of the process are:

  • close Eclipse
  • open Command Prompt
  • go to the project folder path
  • execute the project using the mvn test command

15. test runs in command prompt

Try to create your own project using this short tutorial.

If you have any questions, please leave them in the Comments section.


			

Do not use WebDriver APIs in the Test Script

Test automation starts with a test case.

For example:

1. open the home page of the site (http://www.vpl.ca)

2. run a keyword search

3. validate that the number of results for the keyword search is greater than 0

 

The test case is high level and includes actions that a user would take.

 

To automate it, it needs to be described at a lower level:

1. open the home page of the site (http://www.vpl.ca)

2. run a keyword search

2.1 find the search textbox element
2.2 type a keyword in the search textbox element
2.3 find the search button
2.4 click the search button

3. validate that the number of results for the keyword search is greater than 0

3.1 find the result count label element
3.2 get the value of the result count label
3.3 extract the number of results from the result count value
3.4 verify that the number of results is greater than 0

The code of the test automation script is below:

@Test
public void testFirstResult() {

String url = “http://www.vpl.ca”;

By searchTextBoxLocator = By.xpath(“//input[@id=’globalQuery’]”);

By searchButtonLocator = By.xpath(“//input[@class=’search_button’]”);

By resultsCountLocator = By.xpath(“//span[@class=’items_showing_count’]”);

 

driver.get(url);

WebElement searchField = driver.findElement(searchTextBoxLocator );

searchField.click();

searchField.sendKeys(“java”);

WebElement searchButton = driver.findElement(searchButtonLocator );

searchButton.click();

WebElement resultCountLabel = driver.findElement(resultsCountLocator );

String resultCountValue = resultCountLabel.getText();

int index1 = resultCountValue.indexOf(“of”) + 3;
int index2 = resultCountValue.indexOf(“items”) – 1;

resultCountValue = resultCountValue.substring(index1, index2);

int resultCount = Integer.parseInt(resultCountValue);

assertTrue(resultCount > 0);

}

 

The script includes many WebDriver API objects and methods:

  • WebElement objects
  • By objects
  • driver.findElement() method
  • getText() method
  • click(), sendkeys() methods()

 

Manual testers learning test automation write code that looks like this.

The code works.

Imagine having 50 other scripts similar to this.

What’s wrong here?

Scripts like this one have multiple problems:

– they are difficult to understand by manual testers with no programming experience
– they are difficult to change
– they are difficult to maintain

This way of writing test automation code is incorrect as per Simon Stewart, creator of Selenium WebDriver:

If you have WebDriver APIs in your test methods, You’re Doing It Wrong.

Simon Stewart.

 

So how do we fix the test scripts?

The Page Object Model helps:

“A page object wraps an HTML page, or fragment, with an application-specific API, allowing you to manipulate page elements without digging around in the HTML.”

Martin Fowler

 

This model states that page object classes should be created for each web page of the site.

The page object classes implement the interaction with the site using Selenium WebDriver APIs.

The test automation scripts use then the page object classes and assertions.

Basically, what we should do is to structure the test script so that it follows not the detailed test case but the high level one:

 

@Test
public void testResultsInfo()
{

HomePage home = new HomePage(driver);

home.open();

ResultsPage results = home.search();

assertTrue(results.resultsCount() > 0);

}

 

The test script does not include WebDriver API any longer.

It is as easy to read as the high level test case.

It uses 2 page object classes:

  1. HomePage
  2. ResultsPage

Lets see how the code can be added to these 2 classes.

 

HomePage class

It implements all user actions for the home page.

In this case, there are 2 actions only:

  1. open() – open the home page of the site
  2. search() – run a keyword search

 

public class HomePage
{

WebDriver driver;

String url = “http://www.vpl.ca”;

By searchTextBoxLocator = By.xpath(“//input[@id=’globalQuery’]”);

By searchButtonLocator = By.xpath(“//input[@class=’search_button’]”);

public HomePage(WebDriver driver)
{

this.driver = driver;

}
public void open()
{

driver.get(url);

}

public ResultsPage search(String keyword)
{

WebElement searchField = driver.findElement(searchTextBoxLocator);

searchField.click();

searchField.sendKeys(keyword);

WebElement searchButton = driver.findElement(searchButtonLocator);

searchButton.click();

return new ResultsPage(this.driver);

}

 

 

ResultsPage class

For the results page, we just need to have a method that returns the number of results:

public class ResultsPage {

WebDriver driver;

By resultsCountLocator = By.xpath(“//span[@class=’items_showing_count’]”);

public ResultsPage(WebDriver driver)
{

this.driver = driver;

}

public integer resultsCount()
{

WebElement resultCountLabel = driver.findElement(resultsCountLocator);

String resultCountValue = resultCountLabel.getText();

int index1 = resultCountValue.indexOf(“of”) + 3;
int index2 = resultCountValue.indexOf(“items”) – 1;

resultCountValue = resultCountValue.substring(index1, index2);

int resultCount = Integer.parseInt(resultCountValue);

return returnCount;

}

 

To summarize, the test automation scripts should not include WebDriver APIs.

Page object classes should be created for implementing user actions for each page.

The test scripts should use only page objects and assertions.