Selenium Web driver--Failure Screenshot is not captured in TestNG report - selenium-webdriver

With below mentioned code,if the test case is pass-screenshot captured successfully and displayed in report.But when the test is failed--screenshot is not displayed.Even screenshot hyperlink is not displayed in report.Anybody can sort out the mistake in code?
package listeners;
import java.io.File;
import java.io.IOException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.TestListenerAdapter;
import java.util.logging.Logger;
#Listeners
public class CountryChoserLayer extends TestListenerAdapter {
#Test(priority=1)
public void choseCountry() throws Exception{
driver.findElement(By.id("intselect")).sendKeys("India");
driver.findElement(By.xpath(".//*[#id='countryChooser']/a/img")).click();
//window.onbeforeunload = null;
Date date=new Date();
Format formatter = new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss");
File scrnsht = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
String NewFileNamePath=("C://Documents and Settings//vlakshm//workspace//MyTNG//test-output//Screenshots"+"//SearsINTL_"+ formatter.format(date)+".png");
FileUtils.copyFile(scrnsht, new File(NewFileNamePath));
System.out.println(NewFileNamePath);
Reporter.log("Passed Screenshot");
System.out.println("---------------------------------------");
System.out.println("Country choser layer test case-Success");
System.out.println("---------------------------------------");
}
public String baseurl="http://www.sears.com/shc/s/CountryChooserView?storeId=10153&catalogId=12605";
public WebDriver driver;
public int Count = 0;
#Test(priority=0)
public void openBrowser() {
driver = new FirefoxDriver();
driver.manage().deleteAllCookies();
driver.get(baseurl);
}
#Test(priority=2)
public void closeBrowser() {
driver.quit();
}
#Override
public void onTestFailure(ITestResult result){
Reporter.log("Fail");
System.out.println("BBB");
//Reporter.setCurrentTestResult(result);
Date date=new Date();
Format formatter = new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss");
File scrnsht = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
//File scrFile = ((TakesScreenshot) WebDriver.globalDriverInstance).getScreenshotAs(OutputType.FILE);
String NewFileNamePath=("C://Documents and Settings//vlakshm//workspace//MyTNG//test-output//Screenshots"+"//SearsINTL_"+ formatter.format(date)+".png");
//System.out.println("AAA" + NewFileNamePath);
try {
//System.out.println("CCC");
FileUtils.copyFile(scrnsht,new File(NewFileNamePath));
System.out.println(NewFileNamePath);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("DDD");
e.printStackTrace();
}
Reporter.log("Failed Screenshot");
Reporter.setCurrentTestResult(null);
System.out.println("---------------------------------------");
System.out.println("Country choser layer test case Failed");
System.out.println("---------------------------------------");
}
#Override
public void onTestSkipped(ITestResult result) {
// will be called after test will be skipped
Reporter.log("Skip");
}
#Override
public void onTestSuccess(ITestResult result) {
// will be called after test will pass
Reporter.log("Pass");
}
}

Your onTestFailure method is not being called because you didn't specify listener for your test class. You are missing a value in #Listeners annotation. It should be something like
#Listeners({CountryChoserLayer.class})
You can find more ways of specifying a listener in official TestNg's documentation.
Another problem you are likely to encounter would be NullPointerException while trying to take screenshot in onTestFailure method. The easiest workaround for that would be changing the declaration of driver field to static. I run the code with those fixes and I got the report with screenshot.
I must add that in my opinion putting both test and listener methods into one class is not a good practice.

Related

Getting an error as while reading a JSON file containing 'Usernames' and 'Passwords' using TestNG DataProviders in Selenium

Getting an error as while reading a JSON file using TestNG DataProviders in Selenium.
Error:
class com.google.gson.JsonObject cannot be cast to class org.json.simple.JSONObject (com.google.gson.JsonObject and org.json.simple.JSONObject are in unnamed module of loader 'app')
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.gson.JsonParser;
import io.github.bonigarcia.wdm.WebDriverManager;
public class DataDrivenTest_json {
WebDriver driver;
#BeforeClass
void setUp() { /* to set up chromedriver */
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.MILLISECONDS);
}
#Test(dataProvider="dp") /* using dataproviders*/
void login(String data) {
String list[] = data.split(",");
driver.get("some website url");
driver.findElement(By.cssSelector("[id='Email']")).sendKeys(list[0]);//username
driver.findElement(By.cssSelector("[id='Password']")).sendKeys(list[1]);//password
driver.findElement(By.cssSelector("[type='submit']")).click();
}
#DataProvider(name="dp")
public String[] readJson() throws IOException{
#SuppressWarnings("deprecation")
JsonParser jsonparser = new JsonParser();
FileReader reader =new FileReader("C:\\Users\\dell\\eclipse-workspace-
photon\\ExcelDriven\\src\\test\\java\\Testdata.json");
#SuppressWarnings("deprecation")
Object obj = jsonparser.parse(reader); //java object
JSONObject userLoginsJsonObj = (JSONObject)obj;
JSONArray userLoginsArray =(JSONArray)userLoginsJsonObj.get("userLogins");
String array[] = new String[userLoginsArray.size()];
for(int i=0; i<userLoginsArray.size();i++) {
JSONObject users = (JSONObject)userLoginsArray.get(i);
String username = (String)users.get("username");
String password = (String)users.get("password");
array[i] = username+","+password;
}
return array;
}
#AfterClass
void tearDown() { //close driver
driver.close();
}
}
/*My MavenProject has testng included and pom.xml file has 'com.googlecode.json-simple' dependency added.Still the above error is visible in console.*/
You import class org.json.simple.JSONObject while you need to import com.google.gson.JsonObject. You cannot just cast an object to any class even if that class has the same name. The package of the class also matters.

Camel exchange header lost during test

I'm trying to test the onException(JsonProcessingException.class) route in the following class (please don't mind its name, I've cut some code out for clarity):
import org.apache.camel.Exchange;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonProcessingException;
import pl.muni.camel.sample.customer.domain.CustomerData;
import pl.muni.camel.sample.customer.route.processor.CreateCustomerErrorResponseProcessor;
import pl.muni.camel.sample.customer.route.processor.CreateCustomerOkResponseProcessor;
#Component
public class SendCustomerDataToQueueRoute extends RouteBuilder {
#Value("${http.rest.listener.host}")
private String restListenerHost;
#Value("${http.rest.listener.port}")
private int restListenerPort;
#Override
public void configure() {
restConfiguration()
.component("restlet")
.dataFormatProperty("prettyPrint", "true")
.host(restListenerHost)
.port(restListenerPort);
rest("/rest/v1/customer")
.post("/create")
.bindingMode(RestBindingMode.json)
.skipBindingOnErrorCode(false)
.consumes("application/json")
.type(CustomerData.class)
.produces("application/json")
.route().id("acceptCreateCustomerRequest")
.from("direct:acceptRequest")
.to("direct:processRequest");
onException(JsonProcessingException.class)
.handled(true)
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(400))
.to("direct:processException");
onException(Exception.class)
.handled(true)
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(500))
.to("direct:processException");
from("direct:processRequest").routeId("processCreateCustomerRequest")
.log("Received customer data: ${body}")
.process(new CreateCustomerOkResponseProcessor()).id("createOkResponse");
from("direct:processException").routeId("processCreateCustomerException")
.log(LoggingLevel.ERROR, "${exception.stacktrace}").id("logExceptionStackTrace")
.process(new CreateCustomerErrorResponseProcessor()).id("createErrorResponse");
}
}
I want to intercept the exchange after createErrorResponse processor and run some assertions on it. So far I've come up with this code, in which I weave in a mock endpoint after direct:processException endpoint:
import java.util.List;
import org.apache.camel.CamelContext;
import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.CamelSpringBootRunner;
import org.apache.camel.test.spring.EnableRouteCoverage;
import org.apache.camel.test.spring.MockEndpointsAndSkip;
import org.apache.camel.test.spring.UseAdviceWith;
import org.assertj.core.api.Assertions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.annotation.DirtiesContext;
import pl.muni.camel.sample.customer.infrastructure.rest.CreateCustomerResponse;
#UseAdviceWith
#MockEndpointsAndSkip("restlet*")
#EnableRouteCoverage
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
#SpringBootTest
#ComponentScan("pl.muni.camel.sample.customer")
#RunWith(CamelSpringBootRunner.class)
public class SendCustomerDataToQueueIntegrationTest {
#Produce
private ProducerTemplate producerTemplate;
#Autowired
private CamelContext context;
#EndpointInject(uri = "mock:error")
private MockEndpoint errorEndpoint;
#Before
public void setUp() throws Exception {
context.getRouteDefinition("processCreateCustomerRequest").adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() {
weaveByToUri("direct:processException")
.after()
.to("mock:error");
}
});
context.start();
}
#After
public void tearDown() throws Exception {
context.stop();
}
#Test
public void shouldReturnHttpStatus400ForInvalidJson() throws InterruptedException {
// given
final String customerDataString = "{\"firstName\": \"aaa\", \"lastname\": \"bbb\"}";
//when
producerTemplate.sendBody("direct:acceptRequest", customerDataString);
//then
errorEndpoint.expectedHeaderReceived(Exchange.HTTP_RESPONSE_CODE, 400);
errorEndpoint.assertIsSatisfied();
final List<Exchange> exchanges = errorEndpoint.getExchanges();
Assertions.assertThat(exchanges).hasSize(1);
final Exchange exchange = exchanges.get(0);
final CreateCustomerResponse response = exchange.getIn().getBody(CreateCustomerResponse.class);
Assertions.assertThat(response.isSuccess()).isFalse();
Assertions.assertThat(response.getErrorMessage()).startsWith("UnrecognizedPropertyException: Unrecognized field \"lastname\"");
}
}
Unfortunately, the Exchange.HTTP_RESPONSE_CODE header somehow disappears during the test and the assertion on errorEndpoint fails. I ran the test with debugger and breakpoint set within CreateCustomerErrorResponseProcessor class and there the header was still available.
Is there another way to set up the test and be able to retrieve the header or could this be a bug?
The URI you are weaving ("direct:processException") in your unit test is attached to a wrong route definition.
It should be:
context.getRouteDefinition("processCreateCustomerException").adviceWith(...)
(and not "processCreateCustomerRequest")

allure report +selenide, Attached console print log is empty

I am using selenide, testng and allure reports.My goal is just print console logs into the allure report
I am using below code (demo)to add text printed on console to attach to my allure reports :
import com.codeborne.selenide.testng.TextReport;
import com.codeborne.selenide.testng.annotations.Report;
import io.qameta.allure.Attachment;
import org.openqa.selenium.By;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import static com.codeborne.selenide.CollectionCondition.size;
import static com.codeborne.selenide.Condition.enabled;
import static com.codeborne.selenide.Condition.visible;
import static com.codeborne.selenide.Selenide.*;
import java.io.IOException;
import java.util.List;
#Report
#Listeners(TextReport.class)
public class GoogleTestNGTest {
#Attachment
public String logOutput(List<String> outputList) {
String output = "";
for (String o : outputList)
output += o + " ";
return output;
}
#AfterMethod
protected void printLog(ITestResult testResult) throws IOException {
logOutput(Reporter.getOutput(testResult));
}
#BeforeMethod
public void setUp() {
TextReport.onSucceededTest = true;
TextReport.onFailedTest = true;
open("http://google.com/ncr");
}
#Test(enabled = true)
public void failingMethod() {
$(By.name("q")).shouldBe(visible, enabled);
$("#missing-button").click();
}
#Test
public void successfulMethod() {
$(By.name("q")).setValue("selenide").pressEnter();
$$("#ires .g").shouldHave(size(10));
}
}
The problem is that the printLog is empty
screenshot
how i can fix it ?
I got this working by adding this to my browser setup method:
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(BROWSER, Level.ALL);
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
And added this to my code which handles the allure report generation:
List<String> logs = Selenide.getWebDriverLogs(LogType.BROWSER);
Allure.addAttachment("Console logs: ", logs.toString());
i am using for logs..
protected static void log(String stringToLog) {
final String uuid = UUID.randomUUID().toString();
final StepResult result = new StepResult()
.withName(stringToLog);
getLifecycle().startStep(uuid, result);
try {
getLifecycle().updateStep(uuid, s -> s.withStatus(Status.PASSED));
} finally {
getLifecycle().stopStep(uuid);
}
}

Null Pointer Exception using TestNG

I am trying to automate and have integrated Selenium with Appium and I am using Eclipse with TestNG for execution.
Now within a project I have a package with two classes; the first class is for login into the App and the second class is for logout
First class code -
package com.gma.test;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class LoginApp {
public AppiumDriver driver;
#BeforeSuite
public void beforeMethod() throws InterruptedException {
File app = new File("C:\\Users\\mc30058\\Downloads\\gma-QA-RELEASE-QRCode-07022015_v4.5.4028.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName","Android Emulator");
capabilities.setCapability("platformVersion", "4.4");
capabilities.setCapability("app", app.getAbsolutePath());
try {
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS);
driver.findElement(By.xpath("//android.widget.Button[#resource-id='com.mcdonalds.app:id/button_choose_closest']")).click();
driver.findElement(By.xpath("//android.widget.Button[#text='Continue']")).click();
driver.findElement(By.xpath("//android.widget.Button[#text='OK']")).click();
}
#Test (priority=1)
public void Login() {
driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS);
driver.findElement(By.xpath("//android.widget.TextView[#text='Sign In']")).click();
driver.findElement(By.xpath("//android.widget.EditText[#resource-id='com.mcdonalds.app:id/signin_edittext_email']")).sendKeys("anuj.shrivastava#us.mcd.com");
driver.findElement(By.xpath("//android.widget.EditText[#resource-id='com.mcdonalds.app:id/signin_edittext_password']")).sendKeys("Anujtest2");
currentTime();
driver.findElement(By.xpath("//android.widget.Button[#text='Sign In']")).click();
driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS);
driver.findElement(By.xpath("//android.widget.Button[#text='Yeah, count me in!']")).isDisplayed();
currentTime();
driver.findElement(By.xpath("//android.widget.Button[#text='No, thanks. I like to be out of the loop']")).click();
}
private void currentTime() {
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println( sdf.format(cal.getTime()) );
}
}
Second class code:
package com.gma.test;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Logout {
public AppiumDriver driver;
#Test (priority=3)
public void LogoutApp() {
driver.findElement(By.xpath("//android.widget.TextView[#content-desc='Navigation Button']")).click();
driver.findElement(By.xpath("//android.widget.TextView[#text='Sign Out']")).click();
driver.findElement(By.xpath("//android.widget.Button[#text='Sign Out']")).click();
}
}
Contents from Testng.xml
<suite name = "GMA Automation">
<test name = "GMA Automation">
<classes>
<class name = "com.gma.test.LoginApp"/>
<class name = "com.gma.test.Logout"/>
</classes>
</test>
</suite>
I receive Null Pointer exception after execution of first class. Appium server stops saying no more commands received. Please help.
You are getting NPE b'coz you have declared one more driver reference public AppiumDriver driver; in your Logout class.
And you are using this driver reference without instantiation.
In logout class you forget to instantiate your AppiumDriver driver.
try this:
public AppiumDriver driver;
driver = new AndroidDriver();

the method get(class <ReportClass>) is undefined for the type ExtentReport

i'm making selenium extent report but i'm getting error on - static final ExtentReports extrpt=ExtentReports.get(ReportClass.class);
after mouse hover on get i'm getting below info.
the method get(class ) is undefined for the type ExtentReports
it's my simple java project please tell me where am i doing mistake.
package DemoPacakge;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.relevantcodes.extentreports.ExtentReports;
public class ReportClass {
// * ReportClass .class will become TheClassName.class
static final ExtentReports extrpt=ExtentReports.get(ReportClass.class);
public void test()
{
WebDriver driver =new FirefoxDriver();
driver.get("http://learn-automation.com/advance-selenium-reporting-with-screenshots/");
String tile=driver.getTitle();
Assert.assertTrue(tile.contains("learn"));
}
}
Please see the examples section: http://extentreports.relevantcodes.com/1x/docs.html#examples
There are a few errors such as, you are not initializing the report with a "file-path". You have not instructed Extent to start a test either. Try with the below code, it should work:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.LogStatus;
public class ReportClass {
static final ExtentReports extrpt = ExtentReports.get(ReportClass.class);
WebDriver driver;
#BeforeClass
public void beforeClass() {
extrpt.init("file-path.html", true);
extrpt.config().displayCallerClass(false);
}
#Test
public void test() {
extrpt.startTest("Test");
driver = new FirefoxDriver();
extrpt.log(LogStatus.INFO, "Starting FirefoxDriver..");
driver.get("http://learn-automation.com/advance-selenium-reporting-with-screenshots/");
extrpt.log(LogStatus.INFO, "Navigating to learn-automation.com..");
String title = driver.getTitle();
extrpt.log(LogStatus.INFO, "Title: " + title);
try {
Assert.assertTrue(title.contains("learn"));
extrpt.log(LogStatus.PASS, "Step Passed");
}
catch (AssertionError e) {
extrpt.log(LogStatus.FAIL, "<pre>" + e.getMessage() + "</pre>");
}
}
#AfterTest
public void afterTest() {
driver.quit();
extrpt.endTest();
}
}

Resources