PAGE 15 : Listeners In TestNG

Listeners:
Listeners are whom that listen to you.If you talk about Webdriver Listener so you should make a note of some classes and interfaces that we will use.

  •   WebDriverEventListener – This is an interface, which have some predefined methods so we will implement all of these methods.
  • EventFiringWebDriver- This is an class that actually fire Webdriver event

Why we are using Webdriver Listeners
If you talk about Webdriver we are doing some activity like type, click, navigate etc this is all your events which you are performing on your script so we should have activity which actually will keep track of it.
Take an example if you perform click then what should happen before click and after click.To capture these events we will add listener that will perform this task for us.
What is TestNG listener and How to implement in Selenium
When we talk about TestNG Listener we will use ITestListener Interface.This interface has some methods which we need to override as per our requirement.
 For example- take some method of ITestListener
@Override
  public void onFinish(ITestContext arg0) {
 }
@Override
  public void onStart(ITestContext arg0) {
}
@Override
 public void onTestFailure(ITestResult arg0) {
     }  etc
How to implement TestNG Listener
Its not that tough as compared to WebDriver Listeners we simply have to implement ITestListener interface and override all method as per requirement and its not required that you should have some statements in all methods but yes you should use some of that method Wisely
Scenario-
  1. If testcase is failing then what action should be performed
  2. If testcase is skipped then what should be action requested and so far..


STEP 1- CREATE A SIMPLE CLASS AND IMPLEMENT ITESTLISTENER LISTENER





STEP 2- OVERRIDE ALL UNIMPLEMENTED METHODS










Once you implement all your java program will look like
package testngDemo;

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class ListenerDemoExample implements ITestListener{

    @Override
    public void onFinish(ITestContext arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onStart(ITestContext arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onTestFailure(ITestResult arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onTestSkipped(ITestResult arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onTestStart(ITestResult arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onTestSuccess(ITestResult arg0) {
        // TODO Auto-generated method stub
        
    }

}

So let me implement some of the methods and I will start my test.
I will override following method onTestStart, onTestSuccess(), onTestFailure()

I have written a small test for facebook login and I am failing this testcase forcefully so that we can check how different events will be fired if testcase pass or fail

PROGRAM


package testngDemo;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.annotations.Test;

public class ListenerDemoExample implements ITestListener{

    // This is dummy tescase for facebook login
    @Test
    public void loginFB(){
       
        WebDriver driver=new FirefoxDriver();
        driver.get("http://www.facebook.com");
        driver.manage().window().maximize();
        driver.findElement(By.id("email")).sendKeys("mukesh@facebook.com");
        driver.findElement(By.id("wronglocator")).sendKeys("dont-tell");
        driver.findElement(By.id("loginbutton")).click();
    }
    
    
    
    
    @Override
    public void onFinish(ITestContext arg0) {
        // TODO Auto-generated method stub
       
    }

    @Override
    public void onStart(ITestContext arg0) {
        // TODO Auto-generated method stub
       
    }

    @Override
    public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
        // TODO Auto-generated method stub
       
    }

    @Override
    public void onTestFailure(ITestResult arg0) {
    
        System.out.println("Screen shot captured====="+arg0.toString());
       
    }

    @Override
    public void onTestSkipped(ITestResult arg0) {
        // TODO Auto-generated method stub
       
       
    }

    @Override
    public void onTestStart(ITestResult arg0) {
        // TODO Auto-generated method stub
        System.out.println("TestCase started====" +arg0.toString());
       
    }

    @Override
    public void onTestSuccess(ITestResult arg0) {
        // TODO Auto-generated method stub
       
        System.out.println("Congrates Testcase has been passed===="+ arg0.toString());
       
    }

}

 STEP 3- IT NOT COMPLETED YET NOW WE NEED TO MODIFY OUR XML FILE THAT IS KNOWN AS TESTNG.XML AND WE HAVE TO SPECIFY THIS LISTENER AND WE HAVE TO EXECUTE THAT XML FILE ONLY.


We have predefined listeners tag so that we will use today.
<listeners>
<listener class-name="testngDemo.ListenerDemoExample"/>
</listeners>

so your complete testng.xml file will look like.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="none">
<listeners>
<listener class-name="testngDemo.ListenerDemoExample"/>
</listeners>
  <test name="Test">
    <classes>
      <class name="testngDemo.ListenerDemoExample"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

STEP 4- SIMPLE RUN THIS TESTNG.XML FILE AND ANALYZE THE OUTPUT













Now if you analyze above output this event automatically getting triggered like once testcase start and testcase failed or testcase pass.
@listner is a testNG annotation. This is one very important annotation if you chose to have some default behavior for your test case when it fails, passes etc. For Eg : if you extend TestListenerAdapter class and write your implementation in a custom listner to override onTestFailure or onTestSuccess methods you will be able to do pretty much anything you want when a test fails or passes, like taking screenshots, writing something to database, sending emails etc.

Lets say your test fails and you want to rerun the test case automatically one more time when it fails. In that case you will be writing a custom listener to achieve what you need and plug the listener to your test case via @Listener annotation.
what does they do? 
listeners gives the flexibility for the user to listen to the events that are generated from the start of the execution of script till the end.

what kind of events?

events such as, when a test method goes into one of passed/failed/skipped state.
events such as, when a configuratiom annotated method goes into one of passed/failed/skipped state.
events such as before and after a annotated method is executed.

what is the actual purpose? 

the main intention for providing listeners is to extend the default reports behaviour of TestNg. Extend this feature to generate your own custom reports by listening to the above events.

what else can you do?

unlimited possibilities: Few imp things such as,
Before the start of execution, Check if the server is up and running
Sending an automatic status mail at the end of execution
Any other task of your need



Explaination2
Events are specific actions that happen on something for e.g., button clicked! is an event. A simple e.g., would be your mobile plays a sound everytime you get a call.. another event :) Incoming call is an “event” here and your mobile playing a tune is the result of an “event handler” being invoked :) [ Pats his back for that innovative e.g., hehehehe !! Smile will you.. am trying to take away the seriousness here.. sigh! ]
Listeners are basically those entities which are tuned into one or more events that may arise.
TestNG has awesomely managed to leverage this concept and provide a cleaner way of doing things.
So what are TestNG Listeners ?
They are basically “your” classes, which implement some interfaces that TestNG provides, so that when TestNG raises certain events it will look for all “classes” which are basically looking for such events and call the respective event handlers in them.. Confused ??
Its ok to be confused ! I was confused to the core too.
So lets start off with a sample program which will show how to use Listeners.
Here’s a sample Listener that I created, which basically takes care of Starting and Stopping a Selenium Server.
If you look at this listener, its no big complex thing. It is just an ordinary class that implements an Interface named “ISuiteListener”.
Whenever a class implements this listener, TestNG guarantees the end-user that it will invoke the methods onStart() and onFinish() before and after running a TestNG Suite.
So before TestNG picks up your suite for execution, it first makes a call to onStart() method and runs whatever has been scripted in this method. In a similar way, it again makes a call to onFinish() method after a suite has been run.
So what other listeners are there in TestNG ?
There are a lot of listeners. But I will give you an over view on the most common listeners that you would need :
·         org.testng.IReporter : Implement this listener within your class, if you want to customize the TestNG reports (for e.g., you might want your test reports to be available as an excel sheet or a word document or even a pdf for that matter). This would be the last of the calls that TestNG makes before closing your execution.
·         org.testng.IInvokedMethodListener : Implement this listener within your class, if you want something to be done before and after a method is invoked by TestNG. Some classic examples would be, instantiating and closing off the WebDriver for e.g.,.
·         org.testng.IInvokedMethodListener2 : Implement this listener within your class if you want all that IInvokedMethodListener can do, but also give you access to the ITestContext object. ITestContext object essentially is the contextual representation of all the relevant information for a given TestNG run.
·         org.testng.ITestListener : Implement this listener within your class if you want to be notified before and after a test (“<test>”) is run. This would also give you a way in which you can specify as to what should be done when a particular test is passed/skipped/failed etc., (A simple use case would be to implement some sort of a running commentary on the console indicating how many tests have so far run, how many passed and so on and so forth.

Ok, so now am guessing that you must be pretty aware of what listeners are all about and we also saw how to write a listener. Now comes the big question.
How do I let TestNG know that I have such a listener which it should invoke when it is executing my tests ?
There are essentially three ways of adding up a listener to a particular class. I will walk you through on all of the three ways [at-least these are the only ways I know of :) ] :
1. Using the @Listeners TestNG provided annotation.
This is the easiest way of binding your implemented TestNG Listener to your test class.
Before your class definition, you just add up this listener as below
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Listeners(SeleniumStarterListener.class)
public class IUseListeners {

    private Selenium selenium = null;

    @BeforeClass
    public void setup() {
        selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com");
        selenium.start();
    }

    @Test
    public void f() {
        selenium.open("http://www.facebook.com");
    }

    @AfterClass
    public void tearDown() {
        selenium.stop();
    }
}
Here if you notice, I am telling TestNG that for my test class “IUseListeners” I need TestNG to refer to the class SeleniumStarterListenerand invoke the corresponding methods within it as and when a relevant TestNG “triggered” event happens. So in this case, TestNG will first invoke my onStart() method in my Listener class before it begins executing my Test (remember, that if you dont provide a suite for your class as I have done here, TestNG creates a default suite, defines a default Test and adds up your testclass to it). That is why I when you execute this sample test along with the listener, the listener takes care of starting the selenium server and stopping it. Clean way of doing it isn’t it ?? That is what TestNG Listeners are there for :)
2. By using the <listeners> tag in your TestNG Template file.
Although approach 1 is more than enough to get you started, it’s not an “elegant” way of using Listeners, because you are forced to add this @Listeners section to each of your classes, which you perhaps wont want. So what you do is, you create a TestNG Suite file and then add up the listeners section to this suite file. That way, all of your tests would essentially leverage the listener that you wrote. So in our case, before the suite starts (remember a suite can contain one or more suites within itself, one or more tests within itself and each test<test> can have one or more test classes in it).
So here’s how a typical xml file would look like :
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="false">
    <listeners>
        <listener class-name="com.test.listeners.SeleniumStarterListener"/>
    </listeners>
    <test name="Test" preserve-order="false">
        <classes>
            <class name="com.test.IUseListeners" />
        </classes>
    </test>
</suite>
Pay close attention to the <listeners> section here. I have defined this listener at the suite level and have given the “fully qualified name”of my Listener class.
3. When you are working with TestNG class directly and want to pro-grammatically run your Tests you can specify your Listeners as below :
Here’s a sample code which shows you how to do this in a main() program of Java.
1
2
3
4
5
6
7
public static void main(String[] args){
 TestNG testng = new TestNG();
 Class[] classes = new Class[]{IUseListeners.class};
 testng.addListener(new SeleniumStarterListener());
 testng.setTestClasses(classes);
 testng.run();
 }






























No comments:

Post a Comment

About Me

My photo
You can reach me out at : jimmiamrit@gmail.com

Total Pageviews