I want to log name of the test suite before running it. I succeed on logging method names but couldn't figure out how I can do the same thing with suites. My code:
EDIT: I found the solution. Here is the code for those who need it.
public class TestCase {
private Logger logger = LogManager.getLogger(this.getClass());
protected static WebDriver driver;
private String url = PropertyManager.getUrl();
private String browser = PropertyManager.getBrowser();
#BeforeSuite
protected void setUp(ITestContext tes) {
System.setProperty("webdriver.chrome.driver","chromedriver.exe");
System.setProperty("webdriver.chrome.logfile", "chromedriver.log");
System.setProperty("webdriver.chrome.verboseLogging", "true");
driver = new ChromeDriver();
driver.get(url);
driver.manage().window().maximize();
logger.info("Starting up {} driver.", browser);
logger.info(tes.getSuite().getName());
}
This can be done by adding Listener in the project. Use IInvokedMethodListener to perform activities before invocation of intended method.
Steps:
Create a class lets say ListenerClass and implement IInvokedMethodListener interface in it.
public class ListenerClass implements IInvokedMethodListener
Add all unimplemented method and add below code in beforeInvocation method :
#SuppressWarnings("deprecation")
#Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
try {
if (method.getTestMethod().getMethod().getAnnotation(org.testng.annotations.BeforeSuite.class)
.toString() != null) {
System.out.println("Before suite annoted method name - " + method.getTestMethod().getMethodName());
System.out.println("Test suite name - " + testResult.getTestContext().getSuite().getName());
}
} catch (Exception e) {
}
}
Add the listener class in your testng.xml file
<listeners>
<listener class-name="ListenerClass"></listener>
</listeners>
<test name="Test_Name">
<classes>
<class name="Test_Class_Name" />
</classes>
</test> <!-- Test -->
Run testng.xml as TestNGSuite you will get the expected result. Let me know if any thing is there
Related
I have two testcases that has to be executed
1.Login to an App
2.Perform some operations
Below is the design of my code:
BaseTest.java
public abstract class BaseTest {
public WebDriver driver;
#BeforeSuite
public void openApplication() {
System.setProperty(chrome_key,chrome_value);
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-notifications");
driver = new ChromeDriver(options);
driver.manage().window().maximize();
driver.get(url);
}
}
LoginPage.java
public class LoginPage extends BasePage{
#FindBy (xpath = "//input[#id='username']")
WebElement userName;
#FindBy (xpath = "//input[#id='password']")
WebElement password;
public LoginPage(WebDriver driver) {
super(driver);
PageFactory.initElements(driver, this);
}
public void loginToApp(String username, String pwd) {
}
}
Account.java:
public class NewAccount extends BasePage{
#FindBy(xpath = "//span[text()='Accounts']/../..")
WebElement accountsTab;
public NewAccount(WebDriver driver) {
super(driver);
PageFactory.initElements(driver, this);
}
public void createNewAccount() {
}
}
LoginToApp.java:
public class LoginToApp extends BaseTest {
#Test
public void a_verifyLogin() throws IOException {
LoginPage hp = new LoginPage(driver);
hp.loginToApp(username, password);
}
}
CreateAccount.java:
public class CreateAccount extends BaseTest {
#Test
public void b_createAccountRecord() {
NewAccount na = new NewAccount(driver);
na.createNewAccount();
}
}
testng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Test">
<classes>
<class name="com.testcases.LoginToApp"/>
<class name="com.testcases.CreateAccount"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
With this framework structure, When I execute the testng.xml file, the first test in LoginToApp executes as expected. And When the control comes to the test in CreateAccount, the driver becomes Null and hence failing the execution of the 2nd Test.
Expected Flow:
1.Initialise Browser
2.Launch the url
3.Execute the #Test method of LoginToApp.java
4.Execute the #Test method of CreateAccount.java
Is it possible to achieve the above flow without making the WebDriver as static? If yes, please explain.
1.Initialise Browser (set this under before method)
2.Launch the url (give priority =0)
3.Execute the #Test method of LoginToApp.java (give priority =1)
4.Execute the #Test method of CreateAccount.java( give depends on method )
depends on method only execute if your loginapp test successfully run
I am having issues trying to run Selenium Web driver in a specific way, I've have setup TestNG + Selenium Web driver in my framework, the thing that I would like to accomplish is to run two suites that I've set up in the TestNG.xml files as bellow:
TestNG.xml
<suite>
<suite-files>
<suite-file path="src/testNG/suites/UserSignsOn.xml" />
<suite-file path="src/testNG/suites/PreSetup.xml" />
</suite-files>
</suite>
PreSetup.xml
<suite name="Pre Setup">
<test name="pre setup suite">
<classes>
<class name="Tests.PreSetup" />
</classes>
</test>
</suite>
UserSignsOn.xml
<suite name="User Signs On">
<test name="Get the Web Application">
<classes>
<class name="Tests.LoginPageTest" />
</classes>
</test>
</suite>
My test files look like this:
LoginPageTest.class
public class LoginPageTest extends BaseTest {
#Test
#Description("Login to the web application")
public void signInTheWebApplicationLocalHost(){ // some steps here }
}
PreSetup.class
public class PreSetup extends BaseTest {
#Test
#Description("Pre setup")
public void preSetupSteps(){ // some steps here }
}
As you can see my Test files extends a class, which is the following:
BaseTest.class
public class BaseTest {
protected EnvironmentManager environmentManager;
#BeforeTest
public void testSetup() {
environmentManager = EnvironmentManager.getInstance();
if(environmentManager.getDriver() == null){
// Here I am set up the driver!!!
environmentManager.initWebdriver();
environmentManager.startWebApplication();
}
}
#BeforeMethod
public void testName(ITestResult result){ // perform some actions }
#AfterMethod
public void status(ITestResult result){ // perform some actions }
#AfterTest // Here I am shutting down the driver
public void tearDown() { environmentManager.shutdownDriver(); }
}
The BaseTest.class calls to the EnvironmentManager.class which is a singleton class
It has the bellow code:
public class EnvironmentManager {
private static EnvironmentManager instance = null;
private WebDriver driver = null;
private String url = "www.google.com";
private EnvironmentManager(){}
// Public Methods
public void initWebdriver() {
if(driver == null){ driver = new ChromeDriver(); }
}
public void startWebApplication(){ driver.get(url); }
// Singleton method
public static EnvironmentManager getInstance() {
if (instance == null) instance = new EnvironmentManager();
return instance;
}
public void shutdownDriver(){
driver.quit();
driver = null;
}
public WebDriver getDriver(){ return driver; }
}
The issue resides after running the second test "PreSetup", in the console I got the error:
Session ID is null. Using WebDriver after calling quit()?
I notice that in the first test the driver session is:
ChromeDriver: chrome on MAC (0ff799fbfd14fc275b3b45c414765b15)
And in the second test is a different one:
ChromeDriver: chrome on MAC (09c6c47344756fe2979ee8a84094b1e3)
Any help is welcome :)
for all interested the solution is to rename the following testNG annotations:
#BeforeTest
#AfterTest
to
#BeforeSuite
#AfterSuite
I have a Base class with a method to open my URL that is called as #BeforeMethod in my test cases. The method takes a string argument for browser type which determines which browser is called. I am attempting to set a parameter in my xml launch file that can be inputted in my #BeforeMethod as argument for the openURL method.
Here is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="FullRegressionSuite" parallel="false">
<listeners>
<listener class-name="reporting.CustomReporter"></listener>
</listeners>
<test name="Test">
<parameter name ="browserType" value="Chrome"/>
<classes>
<class name="reporting.reporterTest"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Here are my tests:
#Listeners(CustomListener.class)
public class reporterTest extends Base {
#Test
public void testOne() {
Assert.assertTrue(true);
}
#Test
public void testTwo() {
Assert.assertTrue(false);
}
#Parameters({ "browserType" })
#BeforeMethod
public void setUp(String browserType) throws InterruptedException {
System.out.println(browserType);
openURL(browserType);
}
#AfterMethod
public void tearDown() {
driver.quit();
}
}
Here is my base class:
public class Base {
public static WebDriver driver = null;
//CALL WEB BROWSER AND OPEN WEBSITE
public static void openURL(String browser) throws InterruptedException {
//launches browser based on argument given
try{
if (browser == "Chrome") {
System.setProperty("webdriver.chrome.driver", "/Users/rossdonohoe/Desktop/SeleniumJava/Drivers/chromedriver");
driver = new ChromeDriver();
}
else if (browser == "Firefox") {
System.setProperty("webdriver.gecko.driver", "/Users/rossdonohoe/Desktop/SeleniumJava/Drivers/geckodriver");
driver = new FirefoxDriver();
}
else {
System.out.println("Error: browser request not recognized");
}
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
driver.get("https://www.google.com");
}
catch(Exception E) {
E.printStackTrace();
}
}
}
My #BeforeMethod is definitely receiving the parameter, as I'm printing its value to check and I'm getting "Chrome" in the console. However, openURL is failing at the 'delete all cookies' line with a null pointer exception (and my line "Error: browser request not recognized' is being printed in console), indicating that the string is not reaching openURL as an argument. Can anyone see what I'm doing wrong?
As the browser is a String variable , you need to use equals or contains or equalsIgnoreCase to check if the browser that you are fetching is "Chrome" or "Firefox".
So you need to use: if(browser.equals("Chrome")) and if(browser.equals("Firefox")) as the conditions instead of the conditions that you have used.
I have a java class that opens up two Chrome browsers, searches for "test 1" and "test 2", respectively. However, once both browsers open, only one browser with the google page will search for "test 1 test 2".
I believe this issue may be because I am calling the driver = new WebDriver from a parent class. However, I am not sure how to resolve the issue.
Here are my two methods that I am trying to run in parallel.
package webDrivertests;
public class googleTestClass extends Methods{
#Test
public void test1() throws InterruptedException {
googleTestClass object1;
object1 = new googleTestClass();
object1.launchBrowser();
object1.goToURL("https://www.google.com");
object1.enterValue("name","q","google test 1");
driver.quit();
}
#Test
public void test2() throws InterruptedException {
googleTestClass object2;
object2 = new googleTestClass();
object2.launchBrowser();
object2.goToURL("https://www.google.com");
object2.enterValue("name","q","google test 2");
driver.quit();
}
}
This is my xml file I use to call them.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="methods">
<test thread-count="2" name="Test" parallel="methods">
<classes>
<class name="webDrivertests.googleTestClass"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
The parent method that includes the driver
package webDrivertests;
// import statements
public class Methods {
public static WebDriver driver;
public void launchBrowser() {
System.setProperty("webdriver.chrome.driver","C:\\chromedriver_win32\\chromedriver.exe");
System.setProperty("webdriver.chrome.args", "--disable-logging");
System.setProperty("webdriver.chrome.silentOutput", "true");
driver = new ChromeDriver();
}
public void goToURL(String url) {
driver.get(url);
}
public void enterValue(String htmltype, String identifier, String value) throws InterruptedException {
if (htmltype == "id") {
WebElement element = driver.findElement(By.id(identifier));
element.clear();
element.sendKeys(value);
element.submit();
}
if (htmltype =="name") {
WebElement element = driver.findElement(By.name(identifier));
element.clear();
element.sendKeys(value);
element.submit();
}
Thread.sleep(3000);
}
}
Current Result: Two browsers are opened and each go to google.com. However only one browser will search for "test 1 test 2". Any help is appreciated! If possible, I would still like to use my parent class "Methods" as it contains a lot of methods I am using for my other real test cases.
Thanks in advance.
The problem lies in your test code. WebDriver object is being declared as a static object.
So this causes every test method to share the same instance.
To fix the problem remove the static keyword from the WebDriver declaration in your Methods class and try again.
Because of static declaration of the driver object in the class, it get's overridden parallel execution when second test called launchBrowser().
Obviously removing static will fix this issue but still you will fall in different issues of managing driver while your test bed and methods increase.
I would recommend to use any of TestNG extension that takes care of such requirement. We are using QAF which is built upon TestNG and provides driver management, resource management and many more features which are crucial for web/mobile/webservices testing.
guys. I trying to solve a problem with parallel running using RC Webdriver and TestNG, but unfortunately, I can't find solution last few hours. Maby you will see the code, and show me what, I actually doing wrong.
Goal:
Create architecture using RC WebDriver and TestNG, with an ability to run tests on a remote machine.
Main settings class is Sut:
private RemoteWebDriver driver = null;
#BeforeClass
public WebDriver getWebDriver() {
DesiredCapabilities dc = new DesiredCapabilities();
FirefoxProfile fp = new FirefoxProfile();
dc.setCapability(FirefoxDriver.PROFILE, fp);
dc.setBrowserName(DesiredCapabilities.firefox().getBrowserName());
try {
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), dc);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return driver;
}
#AfterClass
public void tearDown() {
driver.quit();
}
In this class we have two methods: getWebDriver() - for setup our remote webdriver, and tearDown() - for close web-page, when a test will be complete.
Class BaseStep:
private static ThreadLocal<Sut> sut = new ThreadLocal<Sut>();
public static Sut getSut() {
Sut currentSut = sut.get();
if (currentSut == null) {
currentSut = new Sut();
}
return currentSut;
}
It's an additional layer, which create 'new state for each new thread'.
Few page objects:
public class FacebookPage {
public void testLink() {
getSut().getWebDriver().get("http://facebook.com");
}
}
public class GooglePage {
public void testLink() {
getSut().getWebDriver().get("http://google.com");
}
}
And scenarious classes:
public class VerifyGooglePage {
GooglePage googlePage = new GooglePage();
#Test
public void verifyGoogleMainPage() {
googlePage.testLink();
}
}
public class VerifyFacebookPage {
Facebook facebookPage = new Facebook();
#Test
public void verifyFacebookeMainPage() {
facebookPage.testLink();
}
}
And my and testNG.xml file for running
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="1" name="Suite" parallel="tests">
<test name="FirstTest">
<classes>
<class name="scenarious.VerifyGooglePage"/>
</classes>
</test> <!-- Test -->
<test name="SecondTest">
<classes>
<class name="scenarious.VerifyFacebookPage"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
The problems is: When test complete, browser is not closed.
the Picture
I watched a lot of tutorials and articles in internet about it, but in no-one I cant found solution for my case. Could you please help me to find what I doing wrong.