Wednesday, July 27, 2016

AUTOMATION 20 - GUI 8, Building a Selenium test from concept to execution

Technical difficulty: ****

After my initial script in Selenium, I wanted to move to a more complex script later on.  Along the way though I've encountered a few difficulties.

Today I'm not going to just talk you through my new script and what it does, but also looking at the problems I encountered and how I solved them.  This will help open the lid on how to solve problems yourself when you hit roadblocks creating a basic script.  [Hint - ninja Google skills]

The good news though - once you've overcome a problem once, you get better at avoiding it a second time!


Problem 1: Flawed concept

I originally created the post "I'm hoping that this blog will have the most comments" - hoping that just that, I'd be able to create a script which would be able to have you generate a comment on that blog.

The plan was to select "Anonymous" user, add a comment, and publish it.  Only of course, that's how spam happens - the kind of thing that goes "interesting blog - check out my link where I got 50% off the retail price of brand name shoes".

Because such behaviour is abused, there's a Captcha filter to ensure that you're really a human being.  [Of course ironically we're trying to do this without being a human being].



Problem 2: Where's the comment box?

It looks so simple - we should be masters at this - I used the developer tools to locate elements on the comment box, and set up commands ...






But when I ran it, it couldn't be found.  In fact it went horribly wrong ...


This took some digging around with developer tools to investigate - but I noticed the comment box was a #document which had it's own header and footer.  That is to say it was provided in another frame to the main one we've used to far!



Fortunately WebDriver has a command driver.switchTo().frame() to allow us to move through frames.  Typically the main frame we use is driver.switchTo().frame(0).

I used a very simple piece of code added to our last script

page_info.switchTo().frame(4);
// Confirm if "Enter your comment" is there
if ( page_info.getPageSource().contains("Enter your comment"))
{
   System.out.println("Enter your comment");
}

I kept adjusting increasing the number in .frame() until I got "Enter your comment" found - then I knew I was in the right frame.

Extension material - try amending our previous script now, and see if you can get it to work for you.



Script brief

Because of these problems, the aim for the script has been slightly change, but that's all good (we learn more that way).

Our steps are as follows,

  • Load up my blog page, and select our desired frame.
  • Select "Anonymous" from the drop down list
  • Enter some text into the comment field
  • Select the Preview button
  • Confirm we see "Anonymous said" and the details of our comment

This gives us some nice experience using the frame selection, using drop-downs, entering text and selecting buttons.  Some core features covered!


I'll now take you through the new script published here a section at a time, explaining what each section does.  I do suggest you copy and paste it into Eclipse and have a bit of an experiment yourself using last time's guidelines.

WebDriver driver = new FirefoxDriver();
// Open our target page ... a previous blog articledriver.get("http://testsheepnz.blogspot.co.nz/2016/07/im-hoping-that-this-blog-will-have-most.html");

We pretty much covered this last time - declares a new WebDriver object, and opens the blog page.  Importantly, after last time's discussion, I've decided to use the nomenclature of "driver" for the object in keeping with most sample scripts you'll encounter, over the "page_item" I was using previously.

driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
Because I was having issues when I couldn't find the comment box, I wasn't sure if my checks were occurring before the page had loaded, so just put a small wait in to be sure.

//Switch to the frame that comments are kept indriver.switchTo().frame(4);

As before, this moves us into the page frame where we know that comments are.

//Select to comment as "anonymous"
Select select = new Select( driver.findElement(By.name("identityMenu")) );//select.selectByIndex(8);select.selectByValue("ANON");

Useful to just mention - the WebElement is a subclass of WebDriver (a page is made of multiple WebElements after all).  Likewise the Select object is a subclass of a WebElement object for a drop down list.

This command allows us to select one of the drop down options - we can use .selectByValue which compares against a text value you can get from prying with the developer tools.

Commented out is the method .selectByIndex - this chooses the 8th element in the drop down list.  Try uncommenting it out, and commenting out the .selectByValue commend.  Indeed, try altering the command to pick different items in the drop down.

//Select the comment body fieldString stringComment= "This is my comment";WebElement element = driver.findElement(By.id("commentBodyField"));element.sendKeys(stringComment);
This selects the comment text box and types in "This is my comment" using the .sendKeys command.

 //Select to preview
element = driver.findElement(By.id("postCommentPreview"));
element.submit();

This finds the Preview button and uses the .submit command to press it.

Finally I use some .contains checks to confirm that I can see "Anonymous said" and "This is my comment" on the page.  You might wonder why I'm testing "Anonyous" and "said" separately - if you check the page html code, you'll see there's an invisible character between the two words which interferes with the .contains checking!



Extension material

We've covered a lot today, although to only a shallow level.  Do look up the commands - some of these I looked up by simple Google searches of "WebDriver select drop down" and seeing what examples were out there to try.

An odd quirk I found with the Firefox page opened by WebDriver, I'd usually be signed out of any webpages - that could be worth exploring.

Come up with ways to select other options to comment on my blog page.  Maybe even try and log in and generate a comment without needing Captcha.

As always - have fun whilst you learn.

Project Aardvark: Script 2, Creating and previewing a comment

// "Project Aardvark" Part 2
// This code will attempt to post an anonymous comment & preview it
// Mike Talks 18/05/2016

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;


public class addComment {

    public static void main(String[] args) {

        // Create a new instance of the Firefox driver
        // This copies all the information about the page we've loaded into
        // the driver object

        WebDriver driver = new FirefoxDriver();
       
        // Open our target page ... a previous blog article
        driver.get("http://testsheepnz.blogspot.co.nz/2016/07/im-hoping-that-this-blog-will-have-most.html");
       
        // Print out the page title
        System.out.println("Page title is: " + driver.getTitle());
        


        // We need to add a small pause for loading
        driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
       
        //Switch to the frame that comments are kept in
        driver.switchTo().frame(4);
       
        //Select to comment as "anonymous"
        Select select = new Select( driver.findElement(By.name("identityMenu")) );
        //select.selectByIndex(8);
        select.selectByValue("ANON");

        //Select the comment body field
        String stringComment= "This is my comment";
        WebElement element = driver.findElement(By.id("commentBodyField"));
        element.sendKeys(stringComment);
       
        //Select to preview
        element = driver.findElement(By.id("postCommentPreview"));
        element.submit();
       
        //Confirm page contains "Anonymous said" / Comment
        if ( driver.getPageSource().contains("Anonymous") &&
                driver.getPageSource().contains("said") )
        {
            System.out.println("Confirmed: Anonymous said");
        }
       
        if ( driver.getPageSource().contains(stringComment))
        {
            System.out.println("Confirmed: " + stringComment);
        }      
       
    }
   
}

Friday, July 22, 2016

AUTOMATION 19 - GUI 7, Resources for exploring WebDriver commands

Technical level: ***

With our first Selenium WebDriver script written and working, it's a good place to think about resources and methods for finding out about other features and definitions of the WebDriver class.

Why we write - to explore

In the Selenium script that I published previously, I decided to change the name of the WebDriver object from the standard "driver" that I've always seen to "page_item".

For me, this was very much driven by my understanding of what the WebDriver class represents, a representation of all the data and selectable methods available on a page.

It led to some interesting conversations on Twitter as well, which I found really useful ...








The truth is, I find it hard to actually find a good explanation of the WebDriver class which we're using there.  But conceptually when I use it and the methods, I seem myself manipulating the page object with it.

Richard pointed out, that's useful as a start point, but you also need to understand that the WebDriver (and why it's often named "driver"), isn't just the page object, but it's the "thing" that manipulates the page as well.

As Andrew confirmed, to forget about the "driver functionality" in there is equivalent to thinking about a puppet, without thinking about the strings and marionette controls.

Searching the net, I've struggled, even on the Selenium homepage to find a definitive list of all the commands available.  So plan B ...


WebDriver available parameters and functions

So, I've been somewhat frustrated trying to find a definitive list of what functions are available to be using WebDriver in Java.  I can find a few pages and books (listed below) giving some useful functions, but not a definitive library list.

One method that I use to explore functionality comes through Eclipse, and I'm going to share this simple (but powerful) approach with you ...

Eclipse will attempt to autofill when you reference an object attribute/method.  So with the code we've been using, if you type "page_info." you get a set of prompts for what's available - you can explore these, and even Google for more information.





The same happens when you explore the WebElement object "element." ...



This allows you to peel back and explore what features are available within these objects - have a go now.  Once you find a suggested name, you can explore it by either Googling, or trying it out through exploration to see what happens.



Some useful resources

The following are some free online resources which can help you get started,
Alan Richardson has a couple of really useful books, which you can order here,
  • Java For Testers - this is a really handy and relatively quick book which follows a similar pattern to my blog (more accurately I probably stole his style) - it explores in detail with examples you can follow along with.  I have a couple of Java books at home, and typically they're lengthy and intimidating tomes.  This got me where I needed with sufficient levels of detail - although I come from a C++ background.
  • Selenium Simplified - I only found out about this book this week.  Follows the same very strongly hands-on approach (which of course suits me fine), working through a lot of examples in detail.

Dave Haeffner wrote The Selenium Guidebook which came highly recommended, and includes video tutorials if you go for the full package.  He also has a weekly newsletter you can subscribe to.


Mark Collin has written Mastering Selenium WebDriver, which is also on my reading list.

And don't forget, if you're in New Zealand, and want a Selenium course, then my friend Kim Engel runs a Selenium courseKim'll fix it!  I've received a lot of help from Kim's instructor with this series.

Monday, July 18, 2016

AUTOMATION 18 - GUI 6, Running our first Selenium WebDriver script

Technical level: ****

To get the most out of this post, you will need a very basic level of Java (I hope to write a short series on this, but I have to get this epic series finished first).

If you're followed the preceeding steps, then you've installed all the software you need, and set up your Java project area with links to the Selenium WebDriver Jar files.

Now you're ready to try your first script!

There is a great simple script here, which I've seen a lot of sites use, and is the equivalent of "Hello World" for Selenium.

I actually wanted to have a script that did and checked for something, so created Script 1, which you can find on a previous post here.  Open it up, and copy into Eclipse in your Java class (overriding what's there).

What we'll do is start by looking at what it does when run, and then taking a look at all the commands inside...

Hit run!

To make it run, hit the green play button here which will compile and build the code before running it ...


A Firefox browser pops up, open at the surreal entry I added about aardvarks last week ...



The output in Eclipse says this ...


If you have any problems, my advice is,
  • Make sure Selenium WebDriver and Firefox are up to date.  
  • Check consistent class name - should be"PageCheck.java" and "public class PageCheck" match. Anything else, Google the error message.  This is pretty much a developer masterclass in how they solve problems.



The script does the following,
  • It opens Firefox and my Aardvark post
  • It captures the page title, and prints to the screen
  • It checks the whole page for the phase "blue aardvark" and prints it's found it - I mention "blue aardvark" in the article.
  • It checks the whole page for the phase "red aardvark" and prints it's found it - I mention "red aardvark" in the comment.
  • It checks the original post content for the phase "blue aardvark" and prints it's found it.
  • It checks the original post content for the phase "red aardvark", finds nothing (it's in the comments), so prints nothing.

Although I've done a good job commenting it to make it readable, I'm now going to go through the commands used, and explain what they're all about, so you can understand how this script holds together.

import org.openqa.selenium.*;

There is a whole series of import commands, which brings import the parts of the Selenium JAR libraries that I need for our scripts.

In actual fact, I don't need the following right now, but likely to need them in script 2 - so left them in (a bad habit I know).

If I didn't use these import commands, I'd get all sorts of errors of items not find ... in fact I've commented it out and hit run, and I got ...


public class PageChecker

This declares the class we're using.  To be honest with something so simple we're not really using it as a class, just so it can run right now.  Classes are an important concept in modern languages like C# and Java, but too complicated to explore right now.

public static void main(String[] args)

This is the main function - that is the first thing which will be triggered when we hit run and the Java has compiled.

WebDriver page_item = new FirefoxDriver();

This sets an instance of a Firefox driver that we can use.  Most code declares it as "WebDriver driver", but I felt that "WebDriver page_item" would be easier to follow - we can read the page content by looking at the data within page_item, and can likewise manipulate the page by calling page_item, methods.

It's on this command that a Firefox browser instance is triggered on your computer.

page_item.get("http://testsheepnz.blogspot.co.nz/2016/07/im-hoping-that-this-blog-will-have-most.html");

This causes the Firefox page_item to go to a web address, the address of my blog post.

System.out.println("Page title is: " + page_item.getTitle());

The command println prints to the command line.  It prints out part of the page_item data, relating to the page title.

if ( page_item.getPageSource().contains("blue aardvark"))

This calls a page_item method, where it checks the page content for the text provided - "blue aardvark".  If it's found it prints to screen it's been found.

The "red aardvark" if-statement is the same, just using a different search string.

WebElement element = page_item.findElement(By.id("post-body-8711143007795160191"));

A web element is a part of the page - we've declared it to be by id "post-body-8711143007795160191", which corresponds to the original post - not the title or the comments.

There are several alternative methods we could have used to declare the web element - such as by name or class ID.  But we've already covered via our previous work using developer tools how to do this.

Check out these two posts here and here for more background information

if ( element.getText().contains("blue aardvark"))

Very similar to the previous if-statement, only this time we're looking for the text string in the element, not the whole page.

Hence this time we'll find "blue aardvark" in the original post, but not "red aardvark".



Next time we'll look at how you can explore more Selenium commands, and we'll create a more complicated script.


Extension material
  • Write a check for "See it run"
  • Add a comment to that blog, and create a check for it
  • Google other examples of Selenity commands that you can perform

Project Aardvark: Script 1, Basic page checks

// This is the code for the basic PageCheck for
// "Project Aardvark"
// Mike Talks 18/05/2016

// This code is customised from
// http://www.seleniumhq.org/docs/03_webdriver.jsp#setting-up-a-selenium-webdriver-project


// The following declarations import required packages from the
// Selenium .jar libraries we included in our project
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

public class PageChecker {

    public static void main(String[] args) {

        // Create a new instance of the Firefox driver
        // This copies all the information about the page we've loaded into
        // the page_item object
        WebDriver page_item = new FirefoxDriver();
       
        // Open our target page ... a previous blog article
        page_item.get("http://testsheepnz.blogspot.co.nz/2016/07/im-hoping-that-this-blog-will-have-most.html");
       
        // Print out the page title
        System.out.println("Page title is: " + page_item.getTitle());
       
        // Confirm if there is a blue aardvark in the page
        if ( page_item.getPageSource().contains("blue aardvark"))
        {
            System.out.println("Whole page contains blue aardvark");
        }

        // Confirm if there is a redaardvark in the page
        if ( page_item.getPageSource().contains("red aardvark"))
        {
            System.out.println("Whole page contains red aardvark");
        }       
       
        // We are now going to capture an element of the current page
        // I've used developer tools to find the ID for it
        // This is the main body of the piece (and excludes comments & title)
        WebElement element = page_item.findElement(By.id("post-body-8711143007795160191"));
       
        // Confirm if there is a blue aardvark in the element
        if ( element.getText().contains("blue aardvark"))
        {
            System.out.println("Original post element contains blue aardvark");
        }

        // Confirm if there is a red aardvark in the element
        if ( element.getText().contains("red aardvark") )
        {
            System.out.println("Original post element contains red aardvark");
        }               
    }

}

AUTOMATION 17 - GUI 5, Setting up a Selenium project

Technical level: ****

Last time we installed everything we needed for Selenium WebDriver.  Before we can try out some instructions, we need to set up our Java project area, including importing the Selenium JAR library.


Creating your project

First you need to setup your project area ...

From the menu select File -> New -> Project



Select Java Project, then Next

 
Set a project name as project Aardvark & select Finish


 Your project is now all set up.

 


Create a (main) Java class

Now you need to define the main Java class for your project...

Now, right click it an select New -> Class



From the Java Class select “public static void main (String[] args)" checkbox, type a Name of “PageChecker” then Finish.  This sets up a main function in the Java class, which is central to being able to run your script when you’re ready.


Once finished it should look like,



Link in the Selenium JAR libraries

Now need to add in the Selenium JARs we downloaded last time...

Right click on Project Aardvark and then Build Path -> Configure Build Path



Select the Libraries tab and Add External JARs


 Add in ALL the .jar files you downloaded from Selenium and extracted into your Documents folder – including those in the libs files …



Then select OK.

You should now save your project area – you’re ready for your first automated check, which we'll cover next time.

New Step - Bring in the browser driver Added 22/08/16

Since this post was originally printed, there have been some changes which have impacted how WebDriver works.  Read about it here.

It used to be that you could operate Firefox out-of-the-box.  Now you need to bring in Gecko driver executable and bring it into the folder you have your PageChecker project in.

You can download the drivers from here - but as the page says, be aware that they are third party drivers!