Firebase Test Lab - I can't use ScreenShotter with UIAutomator, as I have no Activity - screenshot

I'm trying to use the ScreenShotter feature in Test Labs, on Firebase within my UIAutomator tests.
However, instead of just needing a context, it needs an Activity, and I can't get or don't have one from within a UIAutomator test.
Am I screwed Does this only work with Espresso?

You can use an ActivityInstrumentationTestCase2 and use Espresso and UiAutomator if you need.
public class SampleActivityTests extends ActivityInstrumentationTestCase2<SampleActivity> {
private UiDevice mDevice;
public SampleActivityTests() {
super(SampleActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
getActivity();
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
public void testAddNote() throws InterruptedException {
// Take a screenshot when app becomes visible.
onView(isRoot());
ScreenShotter.takeScreenshot("sample 1", getActivity());
mDevice.pressDPadLeft();
mDevice.pressDPadLeft();
ScreenShotter.takeScreenshot("sample 2", getActivity());
}
}

Related

How to attach/embed captured screenshots during custom softAssertion into Cucumber Report?

In soft assertion screenshot get captured when softAssertions.assertAll() is called. So to capture screenshots for each soft Assertion failure, created simple CustomAssertion which extends to SoftAssertions and in that override a method name onAssertionErrorCollected().
Below is the sample code.
public class CustomSoftAssertion extends SoftAssertions {
public CustomSoftAssertion() {
}
#Override
public void onAssertionErrorCollected(AssertionError assertionError) {
File file = TestRunner.appiumDriver.getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(file, new File(System.getProperty("user.dir") + File.separator + "ScreenShots" + File.separator + LocalDate.now().format(DateTimeFormatter.ofPattern("MMMM_dd_yyyy")) + File.separator + "demo.png"), true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
In the step definition file:
CustomSoftAssertion softAssertion = new CustomSoftAssertion();
softAssertion.assertThat(isLogin).isTrue();
Above code is working properly. But, how to this captured attach/embed this screenshots into the cucumber report?
Note: For Assertion I am using Assertj library.
You attach scenarios to the report by using scenario.attach. This means you'll have to setup some plumbing to get the scenario into the assertion.
public class CustomSoftAssertion extends SoftAssertions {
private final Scenario scenario;
public CustomSoftAssertion(Scenario scenario) {
this.scenario = scenario;
}
#Override
public void onAssertionErrorCollected(AssertionError assertionError) {
// take screenshot and use the scenario object to attach it to the report
scenario.attach(....)
}
}
private CustomSoftAssertion softAssertion;
#Before
public void setup(Scenario scenario){
softAssertion = new CustomSoftAssertion(scenario);
}
#After // Or #AfterStep
public void assertAll(){
softAssertion.assertAll();
}
#Given("example")
public void example(){
softAssertion.assertThat(isLogin).isTrue();
}

Where do Before and After hooks go in Cucumber

I have a fairly simple Cucumber test framework with a feature file, a step definitions file, and a test runner class that looks like this:
#RunWith(Cucumber.class)
#CucumberOptions(features = "src/test/java/com/tests/cucumber/features/ui/ExampleTest.feature",
glue = { "com.tests.cucumber.stepdefinitions" },
)
public class ExampleTestRunner {
}
This runs a scenario in the feature file just fine. Now I want to add a Before and After hook to do some setup and teardown, but I can't for the like of me get the hooks to run. I've tried adding the hooks to the ExampleTestRunner and to the StepDefinition class, but they never run. Where should I put these hooks? At the moment, the hooks just look like this, but I'll add content to them once I've worked this out!
package com.tests.cucumber.stepdefinitions;
import cucumber.api.java.After;
import cucumber.api.java.Before;
public class StepDefinitions {
#Before
public void before() {
System.out.println("starting before()");
}
}
Thanks for any help.
I am a little hesitant to answer this question even though I managed to get this to work. As far as I can tell, the problem was that I had added the Before and After methods in classes that were extended by other classes. In this situation, the tests would not run. I had to add the Before and After methods to a class that was not extended.
It feels like this is similar to the situation in which if you specify a step definition in a class that is extended by another class, then the step definition is considered to have a duplicate definition. Do I have the correct diagnosis here?
I use like this;
Runner Class:
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src\\test\\features\\ui_features"},
glue = {"com\\base\\tm\\auto_reg\\tests\\ui_tests\\price_features"},
plugin = {"com.cucumber.listener.ExtentCucumberFormatter:"}
)
public class PriceFeatureRunner {
#BeforeClass
public static void setup() {
RunnerUtil.setup(PriceFeatureRunner.class);
}
#AfterClass
public static void teardown() {
RunnerUtil.teardown();
}
}
RunnerUtil.java:
public class RunnerUtil {
public static void setup(Class<?> clazz) {
String reportPath = "target/cucumber-reports/" + clazz.getSimpleName().split("_")[0] + "_report.html";
ExtentProperties extentProperties = ExtentProperties.INSTANCE;
extentProperties.setReportPath(reportPath);
}
public static void teardown() {
UiHooks uiHooks = new UiHooks();
uiHooks.afterScenario();
ExtentReportConfiguration.configureExtentReportTeardown();
}
}
UiHooks.java
public class UiHooks implements HookHelper {
public static final String BASE_URL = "https://www.stackoverfow.com/";
private Scenario scenario;
#Override
#Before
public void beforeScenario(Scenario scenario) {
this.scenario = scenario;
Reporter.assignAuthor(System.getProperty("user.name"));
}
#Override
#After
public void afterScenario() {
if (HookUtil.driver != null) {
HookUtil.driver.quit();
}
if (HookUtil.seleniumBase != null) {
HookUtil.seleniumBase.stopService();
}
}
#Override
#After
public void afterTest() {
if (HookUtil.driver != null) {
HookUtil.driver.quit();
}
if (HookUtil.seleniumBase != null) {
HookUtil.seleniumBase.stopService();
}
}
}
HookHelper.Java
public interface HookHelper {
#Before
void beforeScenario(Scenario scenario);
#After
void afterScenario();
void afterTest();
}

Selenium: How to stop execuing subsequest steps in #Test method after catching an exception using TestNG Listener?

I am working on PageFactory in Page Object Model and TestNG framework for automation. I am using beforeFindBy method in WebDriverEventListener to listen for the presence of an element. When an element is not present, NoSuchElementException is thrown and I catch the exception using try-catch block. How to stop executing remaining steps in #Test method. I do not want to use try-catch in my #Test method. Any suggestion on changes in my design is most appreciated. Below is my design.
LoginPage
public class LoginPage {
#FindBy(xpath = "//img[#src='/webres_5786257bd7c8a5.72130757/themes/default/images/login/logo.png']")
WebElement loginLogo;
public LoginPage(WebDriver driver, ExtentTest test) {
this.driver = driver;
PageFactory.initElements(driver, this);
this.test = test;
}
public void verifyLoginPageLogo() throws IOException {
Assert.assertTrue(loginLogo.isDisplayed());
test.log(LogStatus.PASS, "Logo is displayed", takeScreenshot(driver, test));
}
}
Listenter
public class CustomListeners extends TestListenerAdapter implements WebDriverEventListener {
//All Implemented Methods
public void beforeFindBy(By by, WebElement element, WebDriver driver) {
try {
driver.findElement(by);
} catch (NoSuchElementException e) {
System.out.println("Element " + by + "not found");
}
}
}
Test class
#Listeners(CustomListeners.class)
public class Test1 extends BaseTestSuite {
LoginPage lp;
TabMenu tm;
#Test(priority = 0, testName = "Verify Login")
public void login() throws Exception {
lp = new LoginPage(driver, test);
tm = new TabMenu(driver, test);
driver.get(Constants.url);
lp.verifyLoginPageLogo(); //Element not present here
lp.setUserName("dmin");
lp.setPassword("admin");
lp.clickLoginBtn();
tm.verifyTabMenu();
tm.isCurrentTab("Dashboard");
}
}
The Login PageObject ideally should not contain assertion code. That code should be in your test class. Also the Extent functionality should also be in the test class and not the PageObject.
There is no need for a testng listener or a webdrivereventlistener. In the PageObject if restructure the verifyLoginPageLogo() method to below -
public boolean isLoginPageLogoDisplayed() throws IOException {
//Write logic to check if element is displayed.
//Return false in case of exception etc
}
In the test class do this -
Assert.assertTrue(lp.isLoginPageLogoDisplayed());
If an ArrertionError is thrown the remaining steps are skipped automatically.
ALso look at creating a BasePageObject which has utility methods for checking presence, displayed, finding elements etc etc. Just extend this.

screenshot listener in selenium with TestNG

I have a testcase that will invoke the driver as a non static variable. I also have added screenshot listener in my test case. When the test case fails The control is automatically sent to the screenshot listener, however since my driver is a NON-STATIC variable it could not be accessed in the screenshot listener. So I get nullpointer exception.
To solve this I created a simple base test class with help of stackoverflow like below and extend it in each testclass
public asbtract baseTest() {
private WebDriver driver;
public WebDriver getDriver() {
return driver;
}
#BeforeMethod
public void createDriver() {
Webdriver driver=XXXXDriver();
}
#AfterMethod
public void tearDownDriver() {
if (driver != null)
{
try
{
driver.quit();
}
catch (WebDriverException e) {
System.out.println("***** CAUGHT EXCEPTION IN DRIVER TEARDOWN *****");
System.out.println(e);
}
}
}
In my listener, I access the base class as follows
public class ScreenshotListener extends TestListenerAdapter {
#Override
public void onTestFailure(ITestResult result)
{
Object currentClass = result.getInstance();
WebDriver webDriver = ((baseTest) currentClass).getDriver();
if (webDriver != null)
{
File f = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
//etc.
}
}
My test class looks like this
#Listeners(value = FailureReport.class)
public class LoginTest extends baseTest{
Login login = new Login(getDriver());
#Test(description = "Verify Expand the Menu", priority = 0)
public void navigateloginpage() {
login.expandMenuScreenLogin();
login.navigateLoginPage();
}
#Test(description = "User login Sucessfully", priority = 1)
public void successLogin() {
login.login();
}
When I run this it gives me the error
org.testng.TestNGException:
Cannot find class in classpath: com.fbf.automation.tests.LoginTest
at org.testng.xml.XmlClass.loadClass(XmlClass.java:81)
at org.testng.xml.XmlClass.init(XmlClass.java:73)
at org.testng.xml.XmlClass.<init>(XmlClass.java:59)
at org.testng.xml.TestNGContentHandler.startElement(TestNGContentHandler.java:548)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:745)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1359)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:195)
at org.testng.xml.XMLParser.parse(XMLParser.java:38)
at org.testng.xml.SuiteXmlParser.parse(SuiteXmlParser.java:16)
at org.testng.xml.SuiteXmlParser.parse(SuiteXmlParser.java:9)
at org.testng.xml.Parser.parse(Parser.java:172)
at org.testng.TestNG.initializeSuitesAndJarFile(TestNG.java:302)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:45)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
Process finished with exit code 0
Later when I changed my test class as follows it ran correctly
#Listeners(value = FailureReport.class)
public class LoginTest extends baseTest{
Login login;
#Test(description = "Verify Expand the Menu", priority = 0)
public void navigateloginpage() {
login = new Login(getDriver());
login.expandMenuScreenLogin();
login.navigateLoginPage();
}
#Test(description = "User login Sucessfully", priority = 1)
public void successLogin() {
login.login();
}
Isn't it possible to declare the code
login = new Login(getDriver());
outside #test method rather than writing it inside the #test method. Or are there anyother alternative ways I can call the above code
You may create Login object inside #BeforeClass method
#BeforeClass(alwaysRun = true)
public void setUp() throws Exception {
login = new Login(getDriver());
}

how to solve Test run failed: Instrumentation run failed due to 'Native crash' in robotium

I am trying JUnit test but facing following issue.
When I select Android JUnit Test by right clicking on Project it shows following message
Test run failed: Instrumentation run failed due to 'Native crash'
and when I right click on TestApk.java and select Android JUnit Test, it shows
Test run failed: Instrumentation run failed due to java.lang.ClassNotFoundException
Two cases occurs
Here is my source code.
#SuppressWarnings("unchecked")
public class TestApk extends ActivityInstrumentationTestCase2 {
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.nhn.android.ndrive";
private static Class launcherActivityClass;
static {
try {
launcherActivityClass = Class
.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public TestApk() throws ClassNotFoundException {
super(launcherActivityClass);
}
private Solo solo;
#Override
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
public void testDisplayBlackBox() {
//Enter any integer/decimal value for first editfield, we are writing 10
solo.clickOnWebElement(By.id("com.nhn.android.ndrive:id/actionbar_photo_left_button"));
solo.clickOnWebElement(By.id("com.nhn.android.ndrive:id/gnb_group_layout"));
//Enter any integer/decimal value for first editfield, we are writing 20
solo.clickOnWebElement(By.id("com.nhn.android.ndrive:id/actionbar_open_drawer_button"));
//Click on Multiply button
solo.clickOnButton("com.nhn.android.ndrive:id/base_menu_task_open_button");
//Verify that resultant of 10 x 20
//assertTrue(solo.searchText("200"));
}
#Override
public void tearDown() throws Exception {
solo.finishOpenedActivities();
}
}
but package name is not wrong.
how to solve this problem?