How to implement AbstractWebdriverEventListener in a script - selenium

I have created a file with the name SeleniumTestListener.java and I have written the below code:
#override
#AfterMethod(alwaysrun=true)
public class UITestNGListener extends AbstractWebDriverEventListener
{
// TODO Auto-generated method stub
#Override
#AfterTest(alwaysRun=true)
public void onException(Throwable exception, WebDriver driver) {
System.out.println("Failed Failed Failed");
}
Now when I am trying to run the script(purposely making it to fail after login into my application)
But it is failing with a configuration issue
org.testng.TestNGException:
Method onException requires 2 parameters but 0 were supplied in the #Configuration annotation.
Can someone please help how to pass the values(throwable exception, webdriver driver) for this?
Thanks much for the help

You can't use #AfterMethod on a class.
If you specify parameters in a test method, you need to pass these parameters either with the #Parameters annotation or by using a #DataProvider.

Related

How to log unique statements for each tests in the ExtentReport with the implementation of ITestListener?

I am currently using the ExtentReport framework to generate a comprehensive test report after TestNG completes its suite of test class using Selenium.
To make the process easier and to reduce code, I am using a listener class to automate the Test Success and Test Failure scenerios such that in case of every success/failure, there will some actions done to the report automatically. The listener implementation goes like this:
public class Listeners extends Base implements ITestListener{
ExtentTest test;
ExtentReports extent=ExtentReporterNG.getReportObject();
**ThreadLocal**<ExtentTest> extentTest =new **ThreadLocal**<ExtentTest>();
public void onTestStart(ITestResult result) {
// TODO Auto-generated method stub
test= extent.createTest(result.getMethod().getMethodName());
extentTest.set(test);
}
public void onTestSuccess(ITestResult result) {
takeScreenShotandAttachtoReport();
extentTest().get().log("Success");
}
public void onTestFailure(ITestResult result) {
takeScreenShotandAttachtoReport();
extentTest().get().log("Failure");
}
public void onFinish(ITestContext context) {
// TODO Auto-generated method stub
extent.flush();
}
As above, with every test case, an ExtentTest ThreadLocal would be instantiated along the interface methods, which would execute with respect to their individual listeners based on the test results. This reduces the extra code that are needed for the same implementation if ExtentReport was to be instantiated on every test class. However, this implementation has its own hurdle: It would not allow variations (logging, individual test result customization, etc). Say I'd want some ExtentReport logging to be done for each unique test case, I have no ways to invoke the listener and do any type of logging for that particular test.
Is there anyway that this can be solved?

Using a one time login for my test suite in testNg

The code listed below is supposed to login in the 2nd #Test block and it will pick it up from the login file has been created. I extends the "Testbase" class. It is logging in fine, but the second code not able to pick it up from there, and again it performs the same function twice thus it opens the web browser twice. Please any suggestion will be highly appreciated. Thank you
public class Case_Trackin extends TestBase{
public WebDriver driver;
#Test
public void OpeningBrowser() throws IOException InterruptedException
{
Login();
}
#Test (dependsOnMethods="OpeningBrowser", alwaysRun=true ) //This block of code previews the ExcelSpreadsheet file
{
}
#AfterMethod public void tearDown()
{
//driver.quit();
}
}
The #Test will be called twice if you are passing the excel data twice. In #AfterMethod the quit method is commented. And make one #Test in one class file as possible.
It looks like you have two different tests. Once the first method runs, it closes (since you are extending the tearDown() method). So when the second method is going to run, there will be no login thus won't be able to perform its goal.
You should include the login method call in all tests(methods in this case) that need that to perform its goals, or change your testBase from #AfterMethod to #AfterClass.

get Annotation of test method in testNG ITestListener

I am trying to integrate TestLink with TestNG
Approach is below
1>Write ITestListner with onTestFailure and onTestSuccess
2> get Annotation of the method(like testName which will be equivalent to test name in testlink) which is being failed/success in a variable
3>Make connection with TestLink using API available and update the test case.
However I am struggling to find method Annotation value in ITestListner and requirement is to get annotation values in ITestListner only so that correct test cases can be updated in Test_link
Can someone please help me how to get Test Method annotation value in ITestListner or any other approach in which i can integrate testlink update with TestNG
Hi Thanks niharika for help
,First of all you are correct in explaining use of TestNG but we are using TestNG for Selenium and already there are around 1000 test cases writen in test Methods and we have to live with that
Some how i have figured the solution ,we can still get the testName of the test method using two listners
This is just work around I am not sure if this is the best approach but as of now solving my purpose
package com.automation.testng.listner;
import org.testng.*;
public class MyIInvokeMethodListner_TestName_TestLink implements IInvokedMethodListener {
public static String testName;
public void afterInvocation(IInvokedMethod arg0, ITestResult arg1) {
// TODO Auto-generated method stub
}
public void beforeInvocation(IInvokedMethod m, ITestResult tr) {
// TODO Auto-generated method stub
//This give the Annotation Test object
org.testng.annotations.Test t=m.getTestMethod().getMethod().getAnnotation(org.testng.annotations.Test.class);
MyIInvokeMethodListner_TestName_TestLink.testName = t.testName().toString();
}
}
MyITestListner goes like below
package com.automation.testng.listner;
import org.testng.*;
public class MyITestListner_TestLink extends TestListenerAdapter {
/*IAnnotationTransformer at;
public Listner_1()
{
this.at = new Annotation_listner();
}*/
#Override
public void onTestFailure(ITestResult tr)
{
System.out.println("Hurray !I am being inboked from Test listner");
MyIInvokeMethodListner_TestName_TestLink a = new MyIInvokeMethodListner_TestName_TestLink();
System.out.println(MyIInvokeMethodListner_TestName_TestLink.testName);
}
public void onTestSuccess(ITestResult tr)
{
MyIInvokeMethodListner_TestName_TestLink a = new MyIInvokeMethodListner_TestName_TestLink();
System.out.println(MyIInvokeMethodListner_TestName_TestLink.testName);
}
}
Basically we are getting the method and then using Test Annotation class setting the static variable which can be used in MyITestListner
The ITestListener is the one which is used after <test> tag. For getting the method name and annotation specifics, you need to implement IInvokedMethodListener and in the after/before methods of this interface, and use something like method.getTestMethod().getMethodName() to get the executing method name.
If you are adding testName at the method level, I think you are doing it wrong since the help of testng mentions this "The name of the test this test class should be placed in. This attribute is ignore if #Test is not at the class level."
If you are indeed specifying the #Test at your class level then you can get it as below :
method.getTestMethod().getTestClass().getTestName()
A bit ugly and you probably want to wrap those parts in null checks in your code but this is how you get the testName specified in the annotation from the ITestResult:
iTestResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).testName()

Is it a way to get the test method name within TestNG listeners on Configuration phase?

I have a TestNG listener that implements IInvokedMethodListener. On #BeforeMethod I need to setup some test context, here is the example:
public class ThucydidesInvokedMethodListener implements IInvokedMethodListener2 {
public void beforeInvocation(final IInvokedMethod method, final ITestResult testResult) {
boolean areBeforeMethods = method.getTestMethod().getTestClass().getBeforeTestMethods().length > 0;
if ((areBeforeMethods && method.getTestMethod().getTestClass().getBeforeTestMethods()[0] == method.getTestMethod()) ||
!areBeforeMethods && method.isTestMethod()) {
final ThucydidesTestContext context = new ThucydidesTestContext(testResult);
testResult.setAttribute(contextKey(), context);
context.before();
}
}
but also I need a test name that will be executed after the BeforeMethod to use this test name in the reports. Is this possible using TestNG?
Also I've tried IInvokedMethodListener2 that additionally has ITestContext, but it doesn't provide the test name as well.
Using a listener for configuring your tests sounds wrong to me - that is what the #Before* annotations are for.
I do not know how to get your desired information with a listener, but with #BeforeMethod it is simple: Just add a parameter of type java.reflect.Method to your method signature and TestNG will inject the current method which you can then ask for its name and everything else you want to know.
All "magic' for the TestNG annotations is documented here:TestNG dependency injection
HTH
/Jens
import java.lang.reflect.Method;
public class TestToGetMethodName
{
#BeforeMethod
public void handleTestMethodName(Method method)
{
String testName = method.getName();
}
}
Well, with IInvokedMethodListener, the beforeInvocation method gives you IInvokedMethod method.
method.getTestMethod.getMethodName() give you method name.

junit.framework.AssertionFailedError: No tests found in register

I'm having a problem getting this test case to work. Can anyone point me in the right direction? I know I'm doing something wrong, I just don't know what.
import org.junit.*;
import com.thoughtworks.selenium.*;
import org.openqa.selenium.server.*;
#SuppressWarnings("deprecation")
public class register extends SeleneseTestCase {
Selenium selenium;
private SeleniumServer seleniumServer;
public static final String MAX_WAIT = "60000";
public final String CRN = "12761";
public void setUp() throws Exception {
RemoteControlConfiguration rc = new RemoteControlConfiguration();
rc.setAvoidProxy(true);
rc.setSingleWindow(true);
rc.setReuseBrowserSessions(true);
seleniumServer = new SeleniumServer(rc);
selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://google.com/");
seleniumServer.start();
selenium.start();
}
#Test
public void register_test() throws Exception {
//TESTS IN HERE
}
#After
public void tearDown() throws Exception {
selenium.stop();
// Thread.sleep(500000);
}
}
And I'm getting the following errors:
junit.framework.AssertionFailedError: No tests found in register
at jumnit.framework.TestSuite$1.runTest(TestSuite.java:97)
I'm stumped.
You can't both extend TestCase (or SeleniumTestCase) and also use JUnit annotations (#Test). The test runners for JUnit3 and 4 are different, and my assumption is when JUnit sees that you've extended TestCase, it uses the old runner.
Remove the #Test annotation, and instead follow the old convention of naming your test with the word "test" prefixed, and that will fix it.
public void testRegister() throws Exception {
//TESTS IN HERE
}
PS. I'd recommend following more standard Java naming conventions, such as camel casing.
PPS. Here's a link that explains this in more detail.
This means you did not created method names starting with test in following test cases class what you running currently
I was able to solve this error in my case--that is, running tests with a <junit> Ant task--by pointing to a 1.7 or later version of Ant. Ant 1.7+ honors nested <classpath> elements, in which I was pointing to a JUnit 4.x jar, which as CodeSpelunker indicated understands #Test annotations. http://ant.apache.org/faq.html#delegating-classloader provided the aha moment for me.
I'm using mockk in Kotlin for Android and I had this error.
My class was declared like this (autogenerated by Android Studio):
class MyClassTest : TestCase() {
but removing TestCase fixed the error
class MyClassTest {