Pages

Wednesday, March 5, 2014

Page Object Design patterns

 

Page Object is a Design Pattern which has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your AUT. The tests then use the methods of this page object class whenever they need to interact with that page of the UI. The benefit is that if the UI changes for the page, the tests themselves don’t need to change, only the code within the page object needs to change. Subsequently all changes to support that new UI are located in one place.
The Page Object Design Pattern provides the following advantages.
1. There is clean separation between test code and page specific code such as locators (or their use if you’re using a UI map) and layout.
2. There is single repository for the services or operations offered by the page rather than having these services scattered through out the tests.
In both cases this allows any modifications required due to UI changes to all be made in one place. Useful information on this technique can be found on numerous blogs as this ‘test design pattern’ is becoming widely used. We encourage the reader who wishes to know more to search the internet for blogs on this subject. Many have written on this design pattern and can provide useful tips beyond the scope of this user guide. To get you started, though, we’ll illustrate page objects with a simple example.
First, consider an example, typical of test automation, that does not use a page object.

/***
 * Tests login feature
 */
public class Login {

        public void testLogin() {
                selenium.type("inputBox", "testUser");
                selenium.type("password", "my supersecret password");
                selenium.click("sign-in");
                selenium.waitForPageToLoad("PageWaitPeriod");
                Assert.assertTrue(selenium.isElementPresent("compose button"),
                                "Login was unsuccessful");
        }
}
There are two problems with this approach.
  1. There is no separation between the test method and the AUTs locators (IDs in this example); both are intertwined in a single method. If the AUT’s UI changes its identifiers, layout, or how a login is input and processed, the test itself must change.
  2. The id-locators would be spread in multiple tests, all tests that had to use this login page.
Applying the page object techniques this example could be rewritten like this in the following example of a page object for a Sign-in page.

/**
 * Page Object encapsulates the Sign-in page.
 */
public class SignInPage {

        private Selenium selenium;

        public SignInPage(Selenium selenium) {
                this.selenium = selenium;
                if(!selenium.getTitle().equals("Sign in page")) {
                        throw new IllegalStateException("This is not sign in page, current page is: "
                                        +selenium.getLocation());
                }
        }

        /**
         * Login as valid user
         *
         * @param userName
         * @param password
         * @return HomePage object
         */
        public HomePage loginValidUser(String userName, String password) {
                selenium.type("usernamefield", userName);
                selenium.type("passwordfield", password);
                selenium.click("sign-in");
                selenium.waitForPageToLoad("waitPeriod");

                return new HomePage(selenium);
        }
}
and page object for a Home page could look like this.

/**
 * Page Object encapsulates the Home Page
 */
public class HomePage {

        private Selenium selenium;

        public HomePage(Selenium selenium) {
                if (!selenium.getTitle().equals("Home Page of logged in user")) {
                        throw new IllegalStateException("This is not Home Page of logged in user, current page" +
                                        "is: " +selenium.getLocation());
                }
        }

        public HomePage manageProfile() {
                // Page encapsulation to manage profile functionality
                return new HomePage(selenium);
        }

        /*More methods offering the services represented by Home Page
        of Logged User. These methods in turn might return more Page Objects
        for example click on Compose mail button could return ComposeMail class object*/

}
So now, the login test would use these two page objects as follows.

/***
 * Tests login feature
 */
public class TestLogin {

        public void testLogin() {
                SignInPage signInPage = new SignInPage(selenium);
                HomePage homePage = signInPage.loginValidUser("userName", "password");
                Assert.assertTrue(selenium.isElementPresent("compose button"),
                                "Login was unsuccessful");
        }
}
There is a lot of flexibility in how the page objects may be designed, but there are a few basic rules for getting the desired maintainability of your test code. Page objects themselves should never be make verifications or assertions. This is part of your test and should always be within the test’s code, never in an page object. The page object will contain the representation of the page, and the services the page provides via methods but no code related to what is being tested should be within the page object.
There is one, single, verification which can, and should, be within the page object and that is to verify that the page, and possibly critical elements on the page, were loaded correctly. This verification should be done while instantiating the page object. In the examples above, both the SignInPage and HomePage constructors check that the expected page is available and ready for requests from the test.
A page object does not necessarily need to represent an entire page. The Page Object design pattern could be used to represent components on a page. If a page in the AUT has multiple components, it may improved maintainability if there was a separate page object for each component.
There are other design patterns that also may be used in testing. Some use a Page Factory for instantiating their page objects. Discussing all of these is beyond the scope of this user guide. Here, we merely want to introduce the concepts to make the reader aware of some of the things that can be done. As was mentioned earlier, many have blogged on this topic and we encourage the reader to search for blogs on these topics.

Monday, February 10, 2014

Selenium WebDriver


WebDriver is a tool for automating web application testing, and in particular to verify that functionalities work as expected. It aims to provide a friendly API that’s easy to explore and understand, easier to use than the Selenium-RC (1.0) API, which will help to make your tests easier to read and maintain.
Let us first get clarified about the difference types of selenium that is/was available in the past and the present.
Selenium Core is the heart of the original Selenium implementation, and is a set of JavaScript scripts that control the browser. This is sometimes referred to as “Selenium” and sometimes as “Core”.
Selenium RC was the name given to the language bindings for Selenium Core, and is commonly, referred to as just “Selenium” or “RC”. This actually came up with two components. Selenium server and the client libraries.
.Selenium WebDriver fits in the same role as RC did, and has incorporated the original 1.x bindings. It refers to both the language bindings and the implementations of the individual browser controlling code. This is commonly referred to as just “WebDriver” or sometimes as Selenium 2.
Selenium1.0+WebDriver=Selenium 2.0
SELENIUM WEBDRIVER WORKING
    WebDriver is designed in a simpler and more concise programming interface along with addressing some limitations in the Selenium-RC API.
    WebDriver is a compact Object Oriented API when compared to Selenium1.0
    WebDriver works at the OS/browser level:
    For instance, command type works at the OS level rather than changing the value of the input elements with JavaScript
    It drives the browser much more effectively and over comes the limitations of Selenium 1.x which affected our functional test coverage, like the file upload or download, pop-ups and dialogs barrier or self-signed certificates problems
Selenium RC, It ‘injects’ JavaScript functions into the browser when the browser was loaded and then used its JavaScript to drive the AUT within the browser. WebDriver does not use this technique. Again, it drives the browser directly using the browser’s built in support for automation.
WebDriver drives the tests natively with the browser and emulates the Human interaction with website. Implementation differs on each browser’s.
The merge of the projects combines the strengths of both frameworks: Selenium 2.0 will provide both Selenium 1.x and WebDriver APIs.
This document concentrates more on WebDriver implementation using the WebDriver Java API.
WebDriver is the name of the key interface against which tests should be written, but there are 11 implementing classes, listed as below:
    AndroidDriver,
    AndroidWebDriver,
    ChromeDriver,
    EventFiringWebDriver,
    FirefoxDriver,
    HtmlUnitDriver,
    InternetExplorerDriver,
    IPhoneDriver,
    IPhoneSimulatorDriver,
    RemoteWebDriver,
    SafariDriver

Selenium Vs Webdriver



Selenium uses JavaScript to automate web pages. This lets it interact very tightly with web content, and was one of the first automation tools to support Ajax and other heavily dynamic pages. However, this also means Selenium runs inside the JavaScript sandbox. This means you need to run the Selenium-RC server to get around the same-origin policy, which can sometimes cause issues with browser setup.

WebDriver on the other hand uses native automation from each language. While this means it takes longer to support new browsers/languages, it does offer a much closer ‘feel’ to the browser. If you’re happy with WebDriver, stick with it, it’s the future. There are limitations and bugs right now, but if they’re not stopping you, go for it.
Selenium Benefits over WebDriver
* Supports many browsers and many languages, WebDriver needs native implementations for each new languagte/browser combo.
* Very mature and complete API
* Currently (Sept 2010) supports JavaScript alerts and confirms better
Benefits of WebDriver Compared to Selenium
* Native automation faster and a little less prone to error and browser configuration
* Does not Requires Selenium-RC Server to be running
* Access to headlessHTMLUnit can allow really fast tests
* Great API

Thursday, November 28, 2013

Log4J Levels

This log4j post is a tutorial post describing different levels of logging in log4j. This is for log4j beginners only but if you wish to refresh, go ahead and enjoy!
Log4j logger contains three main components namely logger, appender and layout. Logger takes care of the logging mechanism and deals with level of logging. Log4j provides five standard levels of logging. There are two more special levels given by log4j. Above all these, log4j allows you to create custom levels.

Five standard log4j levels

DEBUG Level

This log4j level helps developer to debug application. Level of message logged will be focused on providing support to a application developer.

INFO Level

This log4j level gives the progress and chosen state information. This level will be generally useful for end user. This level is one level higher than DEBUG.

WARN Level

This log4j level gives a warning about an unexpected event to the user. The messages coming out of this level may not halt the progress of the system.

ERROR Level

This log4j level gives information about a serious error which needs to be addressed and may result in unstable state. This level is one level higher than WARN.

FATAL Level

This log4j level is straightforward and you don’t get it quite often. Once you get this level and it indicates application death.

Two special log4j levels

ALL Level

This log4j level is used to turn on all levels of logging. Once this is configured and the levels are not considered.

OFF Level

This log4j level is opposite to ALL level. It turns off all the logging.

New Trace Level added in Log4j

TRACE Level

This log4j level gives more detailed information than the DEBUG level and sits top of the hierarchy. This level is introduced from version 1.2.12 in log4j.

Custom log4j levels

Log4j’s levels are mostly sufficient for all common applications. Rarely you may need a new Level apart from the levels provided by log4j. In that case you can extend org.apache.log4j.Level class and have your own custom level implementation.

Log4j Logger Output

When a logger is created, generally you assign a level. The logger outputs all those messages equal to that level and also all greater levels than it. So the order for the standard log4j levels are:

Log4J Levels

TRACE LevelDEBUG LevelINFO LevelWARN LevelERROR LevelFATAL Level
TRACE LevelYYYYYY
DEBUG LevelNYYYYY
INFO LevelNNYYYY
WARN LevelNNNYYY
ERROR LevelNNNNYY
FATAL LevelNNNNNY
ALL LevelYYYYYY
OFF LevelNNNNNN

Log4j Level Inheritance Rule

There can be instances when you don’t assign a level to the logger. In such cases log4j handles it seamlessly based on the following level inheritance rule:
The inherited level for a given logger C, is equal to the first non-null level in the logger hierarchy, starting at C and proceeding upwards in the hierarchy towards the root logger.
That means, if you have a package as com.foo.bar and you didn’t allocate a level, then it will inherit the level from com.foo package. Still in that package also if the level is not available, then it will inherit from the log4j root level. The log4j’s root logger is instantiated and available always. Log4j’s root logger by default has DEBUG level.

Sample code:

private Logger log = Logger.getLogger(ClassName.class);
public void MyMehodABC()
{
try
{
log.info(“we are in MyMethodABC”);
// code
}
}
For this you have to configure log4j.properties file for configuring where to display this file.
Using log4j you can manage logging mechanism in File, Console etc etc…
catch(Exception e)
{
log.error(e.getMessage(),e);
}

 Configure log4j

1| Download log4j.jar  and add into build path
2| Open src folder under project
3| Create a new text file.
4| Paste the following..

#Application Logs
log4j.logger.devpinoyLogger=DEBUG, dest1
log4j.appender.dest1=org.apache.log4j.RollingFileAppender
log4j.appender.dest1.maxFileSize=5000KB
log4j.appender.dest1.maxBackupIndex=3
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
log4j.appender.dest1.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss} %c %m%n
log4j.appender.dest1.File=\logs\\SeleniumLogs.log
#do not append the old file. Create a new log file everytime
log4j.appender.dest1.Append=true

5| Save it with an extension, '.properties'. e.g., log4j.properties
6| Now, log through the script as shown below.

public class classname {
private static Logger Log = Logger.getLogger(classname.class);

@BeforeTest
public void setUp() throws Exception {
Log.info("_______started server_______");
Log.warn("Warn");
baseUrl = "https://qa.knewknovel.com";    
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
    
@Test
public void testAbi() throws Exception {
driver.get(baseUrl + "/web/browse.v");
Log.info("_______Test Inprogress_______");
}
    
@AfterTest
public void tearDown() throws Exception {    
Log.info("_______Stopping server_______");
driver.quit();
}
}

6| Execute the test and check the log file, SeleniumLogs.log under

How to capture the URL of the 'about to' download file on a browser



You can detect a downloading event with chrome.downloads.onCreated listener and perevent it with chrome.downloads.cancel method.

But chrome.downloads API is expiremental and only works on chrome dev channel version for now.

chrome.downloads.onCreated.addListener(function(DownloadItem downloadItem) {
   chrome.downloads.cancel(downloadItem.id , function() {
       console.log("Download was cancelled")
   });
});

HelpFulLink:

https://docs.google.com/document/d/12rNimeeGaA8jEV60PPKtT4pmJYmY9ae_edl3hJyoXYE/edit?hl=en_US

JavaScript code in Chrome extensions can be divided in the following groups:

Extension code - Full access to all permitted chrome.* APIs.
This includes the background page, and all pages which have direct access to it via chrome.extension.getBackgroundPage(), such as the browser pop-ups.

Content scripts (via the manifest file or chrome.tabs.executeScript) - Partial access to some of the chrome APIs, full access to the page's DOM (not to any of the window objects, including frames).
Content scripts run in a scope between the extension and the page. The global window object of a Content script is distinct from the page/extension's global namespace.

Injected scripts (via this method in a Content script) - Full access to all properties in the page. No access to any of the chrome.* APIs.
Injected scripts behave as if they were included by the page itself, and are not connected to the extension in any way. See this post to learn more information on the various injection methods.

To send a message from the injected script to the content script, events have to be used. See this answer for an example. Note: Message transported within an extension from one context to another are automatically (JSON)-serialised and parsed.

In your case, the code in the background page (chrome.tabs.onUpdated) is likely called before the content script script.js is evaluated. So, you'll get a ReferenceError, because init is not .

Also, when you use chrome.tabs.onUpdated, make sure that you test whether the page is fully loaded, because the event fires twice: Before load, and on finish:

//background.html
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        // Execute some script when the page is fully (DOM) ready
        chrome.tabs.executeScript(null, {code:"init();"});
    }
});

How to Take screenshot when it is minimized using selenium webdriver




Following code will work like charm in Selenium

public void  takeScreenshot(String Name)
{
try
{
RemoteWebDriver augmentedDriver =(RemoteWebDriver) new Augmenter().augment(driver);
File screenshot = ((TakesScreenshot)augmentedDriver).getScreenshotAs(OutputType.FILE);
new File(WD_Components.outputDirectory+"//ScreenShot").mkdir();
FileUtils.copyFile(screenshot, new File(WD_Components.outputDirectory+"//ScreenShot//"+Name+".jpg"));
setLog("INFO", "Successfully taken the screenshot");
}

catch (Exception e) 
{
// TODO: handle exception
setLog("ERROR", "Not taken the screenshot"+e);
}
}
Augment()

//Enhance the interfaces implemented by an instance of the RemoteWebDriver based on the returned Capabilities of the driver. Note: this class is still experimental. Use at your own risk.

Below code will help to capture the screenshot of specific element in Selenium(Partial)

public class Shooter{

    private WebDriver driver;

    public void shootWebElement(WebElement element) throws IOException  {

        File screen = ((TakesScreenshot) this.driver).getScreenshotAs(OutputType.FILE);

        Point p = element.getLocation();

        int width = element.getSize().getWidth();
        int height = element.getSize().getHeight();

        BufferedImage img = null;

        img = ImageIO.read(screen);

        BufferedImage dest = img.getSubimage(p.getX(), p.getY(), width,   
                                 height);

        ImageIO.write(dest, "png", screen);

        File f = null;

        f = new File("S:\\ome\\where\\over\\the\\rainbow");

        FileUtils.copyFile(screen, f);

    }

}


It will Maximize the window and take the screenshot

File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
FileUtils.copyFile(scrFile, new File("c:\\tmp\\screenshot.png"));



Below code will help to reduce the image file size using Java


In addition to scaling the image per Hovercraft Full of Eels answer, you can experiment with setting the jpeg quality to something less than the default:

Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter)iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(0.5);   // integer between 0 and 1

Also, depending on the type of screenshots you are taking, you might find some file size reduction by using a different image file format based on palettes, such as PNG(8-bit) or GIF. These formats can use less file size as compared to jpeg when the image contains limited set of colors that occur in frequent blocks of the same color. ...like many traditional GUI application screenshots.

Recording Screencast of Selenium Tests



I was looking for ways to record a video/screencast of Selenium Test Run in Java and came across this brilliant tool called Monte Media Library developed by Werner Randelshofer. This post describes using the ScreenRecorder class from Monte Media Library for recording screencast of Selenium Tests in Java.
Little about ScreenRecorder
ScreenRecoder supports “AVI” and “QuickTime” format for recording the video. For “AVI” format you need to install TSCC Codec (Techsmith Screen Capture Codec) while “QuickTime” format is supported by Apple’s QuickTime Player. ScreenRecorder provides multiple configurations for colors, mouse cursor, screen rate, mouse rate, audio etc. on GUI as well as programmatically.
You need to download ScreenRecorder.jar file from Monte’s Home Page. ScreenRecorder.jar can be launched as a standalone GUI for recording actions from Desktop window or you can add this to your project and import ScreenRecorder class for recording screen video programmatically.
Using ScreenRecorder Class
Following example is created in Eclipse and you need to add ScreenRecorder.jar to the build path of Project.
ScreenRecorder.jar contains ScreenRecorder class which can be called from a Selenium Script for recording the test session in following way:
2| Add MonteScreenRecorder.jar into buildpath
3| Locate startRecording() and stopRecording() on apt location
4| Run the test
5| After finishing testrun check the location, C:\Users\username\Videos for recorded video, "ScreenRecording 2013-10-18 at 15.01.43.avi"

import java.awt.*;
import org.monte.media.Format;
import org.monte.media.math.Rational;
import static org.monte.media.AudioFormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;
import org.monte.screenrecorder.ScreenRecorder;

public class className {
private ScreenRecorder screenRecorder;

@Test
public void test01() throws Exception {
className videoRecord = new className();
videoRecord.startRecording(); //Started recording
driver.get("www.xyz.com");
Thread.sleep(2000);
videoRecord.stopRecording(); //Stopped recording

}


 public void startRecording() throws Exception
     
GraphicsConfiguration gc = GraphicsEnvironment
              .getLocalGraphicsEnvironment()
              .getDefaultScreenDevice()
              .getDefaultConfiguration();

this.screenRecorder = new ScreenRecorder(gc,
              new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI),
              new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
                   CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
                   DepthKey, 24, FrameRateKey, Rational.valueOf(15),
                   QualityKey, 1.0f,
                   KeyFrameIntervalKey, 15 * 60),
              new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, "black",
                   FrameRateKey, Rational.valueOf(30)),
              null);
this.screenRecorder.start();    
}

public void stopRecording() throws Exception
{
this.screenRecorder.stop();

}
The ScreenRecorder captures screen interactions like a charm which can be very useful for analysing Selenium Tests.