Search This Blog

Showing posts with label Selenium. Show all posts
Showing posts with label Selenium. Show all posts

Tuesday, November 18, 2014

Logging using AbstractWebDriverEventListener/WebDriverEventListener

WebDriverEventListener is an Interface and AbstractWebDriverEventListener is an abstract class. These are used for logging before an event occurs.They behave similar to the listeners(iTestListener) in TestNG.

It has few custom abstract methods defined under the class/interface.In order to use these listener one has to extend AbstractWebDriverEventListener  or implement WebDriverEventListener and the custom class has to override the below methods.







Sample Implementation

I have created an custom webdriver logger class ("WebdriverLogger") which implements the webdriver event listener interface and overrides all methods under it.Find the Sample Page below:

WebdriverLogger.class

 public class WebdriverLogger implements WebDriverEventListener{  
      @Override  
      public void beforeNavigateBack(WebDriver arg1){  
           System.out.println("beforeNavigateBack");  
      }  
      @Override  
      public void afterNavigateBack(WebDriver arg1){  
           System.out.println("afterNavigateBack");  
      }  
      @Override  
      public void afterScript(String arg0, WebDriver arg1){  
           //-Add Code  
      }  
      @Override  
      public void beforeScript(String arg0, WebDriver arg1){  
      }  
      @Override  
      public void beforeFindBy(By arg0, WebElement arg1 , WebDriver arg2){  
      }  
      @Override  
      public void afterFindBy(By arg0, WebElement arg1 , WebDriver arg2){  
      }  
      @Override  
      public void beforeClickOn(WebElement arg1 , WebDriver arg2){  
           System.out.println("beforeClickOn");  
      }  
      @Override  
      public void afterClickOn(WebElement arg1 , WebDriver arg2){  
           System.out.println("afterClickOn");  
      }  
      @Override  
      public void beforeNavigateForward(WebDriver arg2){  
      }  
      @Override  
      public void afterNavigateForward(WebDriver arg2){  
      }  
      @Override  
      public void beforeNavigateTo(String url, WebDriver arg2){  
           System.out.println("beforeNavigateTo");  
      }  
      @Override  
      public void afterNavigateTo(String url, WebDriver arg2){  
           System.out.println("afterNavigateTo");  
      }  
      @Override  
      public void afterChangeValueOf(WebElement arg0, WebDriver arg1){  
      }  
      @Override  
      public void beforeChangeValueOf(WebElement arg0, WebDriver arg1){  
      }  
      @Override  
      public void onException(Throwable t, WebDriver arg1){  
           System.out.println("Exception Caught"+t.getMessage());  
      }  
 }  

Tests have been defined in a separate class 'TestWebdriverListener' which adds the event and triggers the logging process.

TestWebdriverListener.java

public class TestWebdriverListener {  
      private static WebDriver driver;  
      private static EventFiringWebDriver edriver;  
      @BeforeMethod  
      public static void setUp(){  
           driver=new ChromeDriver();  
           edriver=new EventFiringWebDriver(driver);  
           edriver.register(new WebdriverLogger());  
           edriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);  
      }  
      @Test  
      public static void testMobikwik(){  
           edriver.navigate().to("https://www.mobikwik.com/");  
           //edriver.findElement(By.xpath("//*[@id='gs_htif0']")).sendKeys("George Bernard Shaw");  
           edriver.findElement(By.xpath("//ul[@class='user-auth-nav nav-secondary sub-block quarter flushright hud-light']//li[@class='sub-block one-w glued tiny']/a")).click();  
      }  
      @AfterMethod  
      public static void tearDown(){  
           edriver.quit();  
      }  
 }  

Sample Output

 Starting ChromeDriver (v2.9.248315) on port 45663  
 beforeNavigateTo  
 afterNavigateTo  
 beforeClickOn  
 afterClickOn  
 PASSED: testGoogle  
 ===============================================  
   Default test  
   Tests run: 1, Failures: 0, Skips: 0  
 ===============================================  

Tuesday, October 28, 2014

Drag and Drop objects to a specific location using Sikuli

Sometimes we need to drag and drop objects in order to automate certain functionality.For Eg: dropping files into upload area in order to get uploaded. We use 'Actions' class in selenium whereas when we need to drop an image on a specific location on the screen, i prefer Sikuli. Below code describes it :

      @Test  
      public static void dragAndDrop() throws FindFailed{  
           Screen scr = new Screen();  
           Pattern pt=new Pattern("dest.png");  
           scr.wait(pt,10);  
           Region iregion=scr.find("dest.png");  
           iregion.dragDrop(iregion,iregion.offset(new Location(566,363)));  
      }  
     


Specific location on the screen can be indicated using 'Location' class.It accepts x-cord and y-cord and returns the region.It follows the below flow :

  • Prepare the pattern using the image
  • Wait for pattern to be visible on the screen
  • Create a Screen Object
  • Locate the image region using new Screen().find()
  • Use dragDrop() to move the region with the help of Location class.
Note: Please take a screenshot of the image and use it with the above code and use SIKULI-IDE to simulate before code.

Page Object vs LoadableComponent

Page Object Pattern

As per selenium wiki : The Page Object pattern represents the screens of your web app as a series of objects.Here what we mean by objects is, these are the sample areas within a page. In simple words, Page Object model is the combination of Pages and its associated components.

Benefits

  • Maintainability is easy : When application represented as a series of pages, if we have a change of functionality/UI in one of the page we can very easily fix that up and should concerned about that page , not the whole framework.
  • Reuses the Code : A single method inside a page class can be called N no. of times
  • Easy Readability : Below diagram explains it better

Design Overview


Pitfall

As noticed from the above design, When i wanted to test few objects from HomePage , I defined my HomePageTest class but unfortunately i had to call few methods of LoginPage in order to visit HomePage.

Now why cant we have a mechanism/structure where, when we create object of HomePage, it should ensure that HomePage is loadable and takes the user to the HomePage. Something like below : 

Loadable Component

LoadableComponent is a abstract base class, whose only task is to ensure that all pages are loadable when we create object of a page class. 
When we extend LoadableComponent class, we should override these 2 following abstract methods:
  • load()
  • isLoaded()

Design Overview






































Hope it helps :)

Tuesday, September 16, 2014

Xpath Formation using preceding-sibling,following-sibling & descendant

'descendant' attribute is used to select the first element on a page always

 <ul>  
   <li> Buy</li>  
   <li> Buy using Credit Card</li>  
   <li> Buy using Debit Card</li>  
   <li> Buy using Cash On Delivery </li>  
 </ul>  
  • Select the very first `li`
     /descendant::li[contains(text(),'Buy')][1]  
    
  • Select the preceding Sibling of the a node
  •  /descendant::li[contains(text(),'Buy')][2]/preceding-sibling::li  
    
    Selection
     <li> Buy</li>  
    
  • Select the following Sibling of a node
  •   /descendant::li[contains(text(),'Buy')][3]/following-sibling::li  
    
    Selection
     <li> Buy using Cash On Delivery </li>  
    

Tuesday, June 17, 2014

Sikuli- Not Compulsory But Necessary

Why We Need Sikuli :

There are certain genuine issues that we face while automating web applications using Selenium Webdriver.For eg: -

(1) Compose Mail : - Adding Attachment
(2) Downloading PDF
(3) Printing Page

The reason is as simple as Selenium cant handle window based pop ups .

Lets Get Started :

Now a solution would be not going for finding xpath and locating elements instead locate elements using some unique property.So Sikuli came to existence by detecting components using image based screenshots.

Its as simple as saying , Give the image to Sikuli and Tell me what needs to done and thats it.

Example : A java library if Sikuli is available here

Below is the code to click on a element when image of the element is given to it.

public static String hitOKbtn(String path) {

        try {
            //Create and initialize an instance of Screen object  
            Screen screen = new Screen();

            //Add image path 
            Pattern image = new Pattern(path);

            //Wait 10ms for image
            screen.wait(image, 10);

            //Click on the image
            screen.click(image);

        }catch(Throwable t) {
            // report error
            System.out.println("Error while clicking on element -"+t.getMessage());

            APPLICATION_LOGS.debug("Error while clicking on element -"+t.getMessage());

            return "Fail";
        }

        return "Pass";
    }

Thanks.I hope it helps :)

Monday, June 16, 2014

Python- Logging Architecture

Python Logging module helps in logging to multiple destination handlers.

It has a very simper architecture as below : -

(1)  Logger,LogObject,Handler and Formatter are the main Actor of this architecture.

(2) There are in total 5 types of severity Levels as defined below with severity in ASCENDING order: -
DEBUG
INFO
WARNING
ERROR
CRITICAL

(3) Logger,Handlers has severity levels

(4) Logger generally inspects the message and does the below 2 operation : -
   
     (4.1)Ignores the message if the message is less severe than the Logger

   (4.2) Otherwise creates LogRecord object from message and passes it to Handler.




(5) Handler responsible for the following 2 tasks : -
  • Outputs message - to a file, stream, socket or where ever you want it to go. You can add a Handler to the Logger by using the addHandler method of the Logger.
  • The Handler also has a level. Once the Handler receives the LogRecord from the Logger, it will ignore any LogRecord that has a severity level that is smaller than its own level. Otherwise it passes the LogRecord to its Formatter

 (6) Each Handler has one Formatter (which you can customize to your taste). The Formatter formats the LogRecord message to the desired format and sends the formatted text back to the Handler.


Putting It All Together :



Thanks . I hope it helps ;)