I want to Skip (so I will see at the report that the tests / classes were skipped) with ITestListener, what I did is the listener class like so:
#Override
public void onStart(ITestContext context) {
String deviceName = context.getCurrentXmlTest().getParameter("deviceName");
System.out.println("device name : "+deviceName);
String className = context.getClass().getSimpleName();
System.out.println("class name : "+className);
if(!deviceName.contains("Galaxy S8")) {
System.out.println("Skipping class name : "+className);
throw new SkipException("Skipping class: " + className);
}
}
and I have test class :
#Test(priority = 1)
public void installAndDenyPhoneAccess() {
onePlus6ProInstallProcess.denyPhoneAccess();
}
at the testng.xml I added the listener:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel = "tests"
configfailurepolicy="continue">
<listeners>
<listener class-name="com.qa.listeners.TestListener" />
</listeners>
<test name="Samsung Note 10 - 5G">
<listeners>
<listener class-name="com.qa.listeners.TestListener" />
</listeners>
<parameter name="emulator" value="false" />
<parameter name="platformName" value="Android" />
<parameter name="udid" value="RPM" />
<parameter name="deviceName" value="Note 10 - 5G" />
<parameter name="systemPort" value="10000" />
<parameter name="chromeDriverPort" value="11000" />
<classes>
<class name="note5.Installation"/>
</classes>
</test>
<test name="Redmi 6A">
<listeners>
<listener class-name="com.qa.listeners.TestListener" />
</listeners>
<parameter name="emulator" value="false" />
<parameter name="platformName" value="Android" />
<parameter name="udid" value="192b" />
<parameter name="deviceName" value="Redmi 6A" />
<parameter name="systemPort" value="10000" />
<parameter name="chromeDriverPort" value="11000" />
<classes>
<class name="redmi6A.Installation"/>
</classes>
</test>
<test name="OnePlus 6 Pro">
<parameter name="emulator" value="false" />
<parameter name="platformName" value="Android" />
<parameter name="udid" value="73" />
<parameter name="deviceName" value="onePlus 6Pro" />
<parameter name="systemPort" value="10000" />
<parameter name="chromeDriverPort" value="11000" />
<classes>
<class name="onePlus6Pro.Installation"/>
</classes>
</test>
<test name="Galaxy S8">
<parameter name="emulator" value="false" />
<parameter name="platformName" value="Android" />
<parameter name="udid" value="ce3cb10c" />
<parameter name="deviceName" value="Galaxy S8" />
<parameter name="systemPort" value="10000" />
<parameter name="chromeDriverPort" value="11000" />
<classes>
<class name="galaxyS8.Installation"/>
</classes>
</test>
<test name="Samsung A21s">
<listeners>
<listener class-name="com.qa.listeners.TestListener" />
</listeners>
<parameter name="emulator" value="false" />
<parameter name="platformName" value="Android" />
<parameter name="udid" value="RdM" />
<parameter name="deviceName" value="Samsung A21s" />
<parameter name="systemPort" value="10000" />
<parameter name="chromeDriverPort" value="11000" />
<classes>
<class name="a21S.Installation"/>
</classes>
</test>
now the tests are not skipped and anyhow not all of them when runing together, only when run two.
So how to skip it? and also how to skip the all class if it can?
IAnnotationTransformer is used to modify the #Test annotation. And there is no option to skip a method using the #Test annotation. In order to forcefully skip it, you need to throw a SkipException.
From the code, it seems that you need to skip the test based on the class name alone and method names are not relevant. So I would suggest the use of ITestListener by overriding the onTestStart method as below:
public class MyTestListener implements ITestListener {
#Override
public void onTestStart(ITestResult result) {
String className = result.getTestClass().getName();
if(className.contains("abc") || className.contains("xyz")) {
throw new SkipException("Skipping class: " + className);
}
}
}
If you want to do this at the method level, you could use IInvokedMethodListener:
public class MyListener implements IInvokedMethodListener {
#Override
public void beforeInvocation(IInvokedMethod method, ITestResult result) {
Map<String, String> paramMap = method.getTestMethod()
.findMethodParameters(result.getTestContext().getCurrentXmlTest());
String className = method.getTestMethod().getTestClass().getName();
if(className.contains(paramMap.get("deviceName"))) {
throw new SkipException("Skipping class: " + className);
}
}
}
Related
I have facing one issue while executing the functions of a selenium class using TestNG XML + java.
The issue is, when I call both the test case functions under TC1 test name (say: <include name=“TC1” /> <include name=“TC2” /> ) am able to execute both the functions, but when I separate them like shown in below XML execution is getting failed, but no complication errors.
Below are the classes and XML I have created.
Main.class :
public class MainClass {
public static void main(String[] args) throws IOException {
TestNG runner = new TestNG();
List<String> suitefiles = new ArrayList<String>();
suitefiles.add(System.getProperty("user.dir") + “/Test.xml");
runner.setTestSuites(suitefiles);
runner.run();
}
}
Test.XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name=“Test” verbose="1" parallel="none" thread-count="1"
configfailurepolicy="skip">
<test name=“TC1” preserve-order="true"
enabled="true">
<groups>
<run>
<include name=“TC” />
</run>
</groups>
<classes>
<class name="com.callingfunction”>
<methods>
<include name=“TC1” />
</methods>
</class>
</classes>
</test>
<test name=“TC2” preserve-order="true"
enabled="true">
<groups>
<run>
<include name=“TC” />
</run>
</groups>
<classes>
<class name="com.callingfunction">
<methods>
<include name=“TC2” />
</methods>
</class>
</classes>
</test>
</suite>
CallingFunction.class
public class CallingFunction {
#BeforeSuite(alwaysRun = true)
public void prerequisite() {
// prerequisites
}
#Test(groups = { “TC” })
public void TC1(){
}
#Test(groups = { “TC” })
public void TC2() {
}
}
I'm doing some tests using Java + TestNG, but I noticed that the tests are not executing the #AfterTest method. The browser remains open when the other tests are running (when it runs the first test, CreateNewUserWithValidData(), this one doesn't call the #AfterTest method, causing that the other tests fail). I need that every test call the #AfterTest method.
My testng.xml file has the following structure:
<suite name="Sample Tests" verbose="1" >
<listeners>
<listener class-name="Utilities.Listeners.TestListener"></listener>
<listener class-name="Utilities.Listeners.AnnotationTransformer"></listener>
</listeners>
<test name="Regression" >
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="CreateNewUserWithValidData" />
<include name="LoginWithAValidUser" />
<include name="LoginWithAnInvalidUser" />
</methods>
</class>
</classes>
</test>
</suite>
My BaseTest class looks like this.-
public class BaseTest {
protected String baseURL;
protected WebDriver driver;
protected WebDriverWait wait;
protected APAuthenticationPage apAuthenticationPage;
protected APCreateAccountPage apCreateAccountPage;
protected APHomePage apHomePage;
protected APMyAccountPage apMyAccountPage;
protected APShoppingCartAddressesPage apShoppingCartAddressesPage;
protected APShoppingCartOrderConfirmationPage apShoppingCartOrderConfirmationPage;
protected APShoppingCartOrderSummaryBankwirePage apShoppingCartOrderSummaryBankwirePage;
protected APShoppingCartPaymentMethodPage apShoppingCartPaymentMethodPage;
protected APShoppingCartShippingPage apShoppingCartShippingPage;
protected APShoppingCartSummaryPage apShoppingCartSummaryPage;
public WebDriver getDriver() {
return driver;
}
#BeforeTest(alwaysRun = true)
public void setUp() {
Log.info("I am in Before Method! Test is starting!");
driver = WebDriverFactory.getDriver(BrowserType.Chrome);
wait = new WebDriverWait(driver, 10);
driver.manage().window().maximize();
}
#BeforeMethod
public void initSetup() {
String propertiesFile = "data.properties";
PropertyReader propertyReader = new PropertyReader();
apAuthenticationPage = new APAuthenticationPage(driver);
apCreateAccountPage = new APCreateAccountPage(driver);
apHomePage = new APHomePage(driver);
apMyAccountPage = new APMyAccountPage(driver);
apShoppingCartAddressesPage = new APShoppingCartAddressesPage(driver);
apShoppingCartOrderConfirmationPage = new APShoppingCartOrderConfirmationPage(driver);
apShoppingCartOrderSummaryBankwirePage = new APShoppingCartOrderSummaryBankwirePage(driver);
apShoppingCartPaymentMethodPage = new APShoppingCartPaymentMethodPage(driver);
apShoppingCartShippingPage = new APShoppingCartShippingPage(driver);
apShoppingCartSummaryPage = new APShoppingCartSummaryPage(driver);
baseURL = propertyReader.getProperty(propertiesFile, "AUTOMATION_PRACTICE_URL");
}
#AfterTest(alwaysRun = true)
public void tearDown() {
Log.info("I am in After Method! Test is ending!");
driver.close();
driver.quit();
}
}
And my tests are the following ones.-
public class AutomationPracticesTests extends BaseTest {
// Properties
private String emailAddress, password;
// Tests
#Test(description = "It creates a new user in the store",
priority = 1)
public void CreateNewUserWithValidData(Method method) {
startTest(method.getName(), "It creates a new user in the store");
emailAddress = Mocks.personalData().get(0).getEmail();
password = Mocks.personalData().get(0).getPassword();
apHomePage.goTo(baseURL);
apHomePage.clickOnSignInButton();
apAuthenticationPage.fillCreateAccountForm(emailAddress);
apAuthenticationPage.clickOnCreateAccountButton();
apCreateAccountPage.fillRegisterForm(Mocks.personalData());
apCreateAccountPage.clickOnRegisterButton();
Assert.assertTrue(apMyAccountPage.isLoaded());
}
#Test(description = "It logins successfully in the store with a valid user",
priority = 2)
public void LoginWithAValidUser(Method method) {
apHomePage.goTo(baseURL);
apHomePage.clickOnSignInButton();
apAuthenticationPage.fillSignInForm(emailAddress, password);
apAuthenticationPage.clickOnSignInButton();
Assert.assertTrue(apMyAccountPage.isLoaded());
}
#Test(description = "It throws an error when the user attempts to login with an invalid user",
priority = 3)
public void LoginWithAnInvalidUser(Method method) {
apHomePage.goTo(baseURL);
apHomePage.clickOnSignInButton();
apAuthenticationPage.fillSignInForm(Mocks.invalidPersonalData().getEmail(), Mocks.invalidPersonalData().getPassword());
apAuthenticationPage.clickOnSignInButton();
Assert.assertEquals("Authentication failed.", apAuthenticationPage.IsErrorBannerDisplayed());
}
}
I'm suspecting that's something related to the testng.xml file (but, tbh, there are some things that I don't understand about how to configure correctly this file).
I'll appreciate any help to solve my problem. Thanks in advance!
It's not a bug. It work as expected.
BeforeTest
BeforeMethod
Method 1: CreateNewUserWithValidData
BeforeMethod
Method 2: LoginWithAValidUser
BeforeMethod
Method 3: LoginWithAnInvalidUser
AfterTest
If you want to close the browser before method 2, then you need to change AfterTest --> AfterMethod, and initialize browser in BeforeMethod
If you just want to change the testng.xml
<test name="test1">
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="CreateNewUserWithValidData"/>
</methods>
</class>
</classes>
</test>
<test name="test2">
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="LoginWithAValidUser"/>
</methods>
</class>
</classes>
</test>
<test name="test3">
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="LoginWithAnInvalidUser"/>
</methods>
</class>
</classes>
</test>
public class FactoryTest {
#Test
#Parameters("Row")
public void run1(int row) throws MalformedURLException{
new Controller(row);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="methods">
<test thread-count="2" name="factory test" parallel="methods">
<classes>
<class name="RealPackage.FactoryTest">
<methods>
<include name="run1">
<parameter name="Row" value="1"/>
</include>
</methods></class>
</classes>
</test> <!-- OfficialTestName -->
</suite> <!-- Suite -->
This is an example of one of the tests I need to run. I need it to run in parallel with other tests. So in the test run1() I create a Controller(row) which initiates the test and I pass a row number to it. I want to run new Controller(1) and new Controller(2) and new Controller(3), etc all at the same time. I am able to do this if I change the java file to this:
public class OfficialTest {
#Test
public void run1() throws MalformedURLException{
new Controller(1);
}
#Test
public void run2() throws MalformedURLException{
new Controller(2);
}
#Test
public void run3() throws MalformedURLException{
new Controller(3);
}
#Test
public void run4() throws MalformedURLException{
new Controller(4);
}
#AfterMethod
public void close() {
System.out.println("closing");
}
}
but this isn't dynamic. I need to be able to run this using any range of number for the row. So I was thinking maybe I could generate an XML file that would take care of this but I still am not sure if it would even be able to run in parallel that way.
I was able to fix it with this:
public class ParallelTests
{
int row;
#Parameters({"Row"})
#BeforeMethod()
public void setUp(int rowParam) throws MalformedURLException
{
row = rowParam;
}
#Test
public void RunTest() throws InterruptedException, MalformedURLException
{
new Controller(row);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite thread-count="5" name="BlogSuite" parallel="tests">
<test name="Test 1">
<parameter name="Row" value="1"/>
<classes>
<class name="RealPackage.ParallelTests"/>
</classes>
</test>
<test name="Test 2">
<parameter name="Row" value="2"/>
<classes>
<class name="RealPackage.ParallelTests"/>
</classes>
</test>
<test name="Test 3">
<parameter name="Row" value="3"/>
<classes>
<class name="RealPackage.ParallelTests"/>
</classes>
</test>
<test name="Test 4">
<parameter name="Row" value="4"/>
<classes>
<class name="RealPackage.ParallelTests"/>
</classes>
</test>
<test name="Test 5">
<parameter name="Row" value="5"/>
<classes>
<class name="RealPackage.ParallelTests"/>
</classes>
</test>
</suite>
example.xml
<?xml version="1.0" encoding="UTF-8"?>
<Element>
<Language Type="Java">
<parameter name="JavatPoint">
<url>https://www.javatpoint.com/</url>
</parameter>
<parameter name="Guru99">
<url>https://www.guru99.com/</url>
</parameter>
<parameter name="w3schools">
<url>https://www.w3schools.com/</url>
</parameter>
</Language>
<Language sdkType="Python">
<parameter name="Tutorialspoint">
<url>https://www.tutorialspoint.com/python/</url>
</parameter>
<parameter name="LearnPython">
<url>https://learnpythonthehardway.org/</url>
</parameter>
<parameter name="Code Academy">
<url>https://www.codecademy.com/learn/learn-python</url>
</parameter>
</language>
</Element>
I need to parse this example.xml based on the Type(ex.java,python) to get the url value and add those values to an arrayList. As I am not aware of xmlHolder can anyone please guide me to achieve this?
Thank you.
You can do it with Groovy like this (please note the last in your example is with a lower-case L and is not valid XML):
import groovy.util.XmlSlurper
def xmlString ='''
<Element>
<Language Type="Java">
<parameter name="JavatPoint">
<url>https://www.javatpoint.com/</url>
</parameter>
<parameter name="Guru99">
<url>https://www.guru99.com/</url>
</parameter>
<parameter name="w3schools">
<url>https://www.w3schools.com/</url>
</parameter>
</Language>
<Language sdkType="Python">
<parameter name="Tutorialspoint">
<url>https://www.tutorialspoint.com/python/</url>
</parameter>
<parameter name="LearnPython">
<url>https://learnpythonthehardway.org/</url>
</parameter>
<parameter name="Code Academy">
<url>https://www.codecademy.com/learn/learn-python</url>
</parameter>
</Language>
</Element>
'''
// error in closing tag
def Element = new XmlSlurper().parseText(xmlString)
def arr = []
def a = Element.Language.each() { node ->
node.attributes().each { att, lang ->
println lang
arr = []
node.'**'.findAll() { childnode -> childnode.name() == 'parameter' }.url.each {
arr.add(it)
}
}
arr.each { println it }
}
#BeforeClass I get null null errors I believe it's something with my before class.What about optional do you need them? FAILED CONFIGURATION: #BeforeClass setUp(null, null) I tried to add different maven dependiencies maybe its because of selenium version its still wont work.
public class Practice {
WebDriver driver;
//Check this ont out
#BeforeClass(alwaysRun = true)
#Parameters({ "browser", "url" })
public void setUp(#Optional("browser") String browser, #Optional("url") String url) {
BaseTest base = new BaseTest(browser, url);
driver = base.getDriver();
}
#Test
public void Check() {
try {
System.out.println("Passed Test case...");
Assert.assertTrue(driver.getTitle().contentEquals("Google"));
} catch (Exception ee) {
System.out.println("NOOOOO ");
ee.printStackTrace();
Assert.assertEquals("noooo " + ee, "iT SHOULD NOT fAIL");
}
}
public class Selen {
private WebDriver driver;
private String browser;
private String url;
public Selen(String browser, String url) {
this.browser = browser;
this.url = url;
if (browser.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.firefox.marionette",
"C:\\Users\\geckodriver.exe");
final FirefoxProfile firefox = new FirefoxProfile();
driver = new FirefoxDriver();
driver.get(url);
}
else if (browser.equalsIgnoreCase("chrome")) {
// set path to chromedriver.exe
System.setProperty("webdriver.chrome.driver", "C:\\Drivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--enable-automation", "test-type=browser", "--disable-plugins", "--disable-infobars",
"--disable-notifications", "start-maximized");
driver = new ChromeDriver(options);
driver.get(url);
}
else if (browser.equalsIgnoreCase("Edge")) {
// set path to Edge.exe
System.setProperty("webdriver.edge.driver", ".\\MicrosoftWebDriver.exe");
driver = new EdgeDriver();
driver.get(url);
} else {
}
}
public String getBrowser() {
return this.browser;
}
public String getBaseUrl() {
return this.url;
}
public WebDriver getDriver() {
return this.driver;
}
#AfterClass
public void tearDown(WebDriver driver) {
quitDriver(driver);
}
protected static void quitDriver(WebDriver driver) {
try {
if (driver != null) {
driver.quit();
}
} catch (Exception ee) {
System.out.println("Failed: " + ee);
;
}
}
**Failed Configuration**
[RemoteTestNG] detected TestNG version 6.14.3
Check() test case...
There was a problem:
java.lang.NullPointerException
at com.seleniumae.exercise.Practice.Check(Practice.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
TeNg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test thread-count="5" name="Test">
<parameter name="browser" value= "Chrome" />
<parameter name="url" value="https://www.google.com/"/>
<classes>
<class name="com.seleniumae.exercise.Practice"/>
<class name="com.seleniumae.exercise.Practice1"/>
<class name="com.seleniumae.exercise.Practice2.java"/>
</classes>
</test> <!-- Test -->
<test thread-count="5" name="Test">
<parameter name="browser" value ="Firefox" />
<parameter name="url" value="https://www.google.com/"/>
<classes>
<class name="com.seleniumae.exercise.Practice"/>
<class name="com.seleniumae.exercise.Practice1"/>
<class name="com.seleniumae.exercise.Practice2"/>
</classes>
</test> <!-- Test -->
<test thread-count="5" name="Test">
<parameter name="browser" value="InternetExplore" />
<parameter name="url" value="https://www.google.com/"/>
<classes>
<class name="com.seleniumae.exercise.Practice"/>
<class name="com.seleniumae.exercise.Practice1"/>
<class name="com.seleniumae.exercise.Practice2.java"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
The issue could be about parameters with browser taking one parameter like chrome when it should be another parameter.
Syntax to define #Optional annotation :
public void setUp(#Optional("browser_name") String browser, #Optional("site_name") String url)
And you are implementing in following way without using #Optional("value")
public void setUp(#Optional String browser, #Optional String url) throws MalformedURLException {
TestNG.xml - please write parameters like below
<suite name="Suite">
<test thread-count="5" name="Test">
<parameter name="url" value="https://www.google.com/"/>
<parameter name="browser" value= "Chrome" />
Note - TestNG provides you flexibility of declaring parameters as optional. When we declare a parameter as optional and If defined parameter is not found in your testng.xml file, The test method will receive the default value which is specified inside the #Optional annotation.