I have a basic test using TestNG. When I run the test using invocationcount = 2, threadpoolsize = 2 (just for testing), I can see in intellij that the tests is running currently but only one browser open.
Heres' my code:
public class GoogleTesting extends FluentTestNg {
// Defines the Driver
public WebDriver driver = new ChromeDriver();
#Override
public WebDriver newWebDriver() {
return driver;
}
#Test(invocationCount = 2, threadPoolSize = 2)
public void GoogleTest(){
goTo("http://google.com");
System.out.println(getCookies());
}
}
Anyone know how to fix this?
Here you have one webdriver instance and calling in two threads. You can try with thread local WebDriver as given below.
public class GoogleTesting extends FluentTestNg {
// Defines the Driver
private static ThreadLocal<WebDriver> WebDriverTL = new ThreadLocal<WebDriver>();
public void setWebdriver(Webdriver driver){
WebDriverTL.set(driver);
}
#Override
public WebDriver newWebDriver() {
return WebDriverTL.get ();
}
#beforeMethod
public void launch browser(){
WebDriver driver = new ChromeDriver();
setWebdriver(driver);
}
#Test(invocationCount = 2, threadPoolSize = 2)
public void GoogleTest(){
goTo("http://google.com");
System.out.println(getCookies());
}
}
Related
I've inherited a Java/Cucumber test application and it mixes web/Selenium based tests and REST based tests.
When any test is ran, Cucumber is instantiating every class, e.g. my step and page factory classes. The problem is when running REST based tests the Chrome driver is started too and Chrome opens.
As below in the (cut-down code), the call to initElements() is the cause but I don't really understand if/when it's needed and how to remove/lazily load or somehow remove or move this call.
public class XXXPages {
#FindBy(xpath = "//input[#id='user_name']")
private WebElement usernameField;
private WebDriverFactory webDriverFactory;
public XXXPages(WebDriverFactory webDriverFactory) {
this.webDriverFactory = webDriverFactory;
//PROBLEM CALL
PageFactory.initElements(webDriverFactory.getDriver(), this);
}
public XXXPages searchName() {
WebDriverWait wait = new WebDriverWait(webDriverFactory.getDriver(), Duration.ofSeconds(3));
wait.until(ExpectedConditions.elementToBeClickable(searchNamefield));
searchNamefield.click();
return this;
}
}
public class WebDriverFactory implements Closeable {
private RemoteWebDriver webDriver;
final String driverPath = System.getProperty("webdriver.chrome.driver", "src/test/resources/drivers/linux/chromedriver");
private void createDriver(){
System.setProperty("webdriver.chrome.driver", driverPath);
final ChromeOptions chromeOptions = new ChromeOptions();
this.webDriver = new ChromeDriver(chromeOptions);
}
public RemoteWebDriver getDriver() {
if (this.webDriver == null){
createDriver();
return webDriver;
}
return webDriver;
}
#Override
public void close() {
webDriver.quit();
}
}
You need to design a wrapper for your driver in lazy initialization manner. Implement a class that would implement WebDriver interface and initialize the driver when the first call to the method happens. Like:
public class LazyWebDriver implements WebDriver, Disposable {
private WebDriver delegate = null;
private WebDriver getDelegate() {
if (delegate == null) {
String driverPath = System.getProperty("webdriver.chrome.driver", "src/test/resources/drivers/linux/chromedriver");
System.setProperty("webdriver.chrome.driver", driverPath);
ChromeOptions chromeOptions = new ChromeOptions();
delegate = new new ChromeDriver(chromeOptions);
}
return delegate;
}
#Override
public void get(String url) {
getDelegate().get(url);
}
// Override other methods here..
}
It might be useful for you to read this post where such approach is described in complete example.
Using the above approach would make cucumber create object for LazyWebDriver which won't cause real driver creation. The driver will be created only if you will execute the tests that use it.
I am new to Selenium, so basically whenever I ran my test, it would open up the URL which I have mentioned in my test. In my same Test I have also mentioned to fill the username and Password.
But somehow once the browser gets launched and redirect to the URL, it opens up another instance of blank browser failing my script that element not found.
Please help me here.
///////////////////////////////////////////////////////////////////////////
public class TruefillTest extends BaseClass {
public Truefill truefill()
{
WebDriver driver=InitializeDriver();
return new Truefill(driver);
}
#Test
public void userLoginIntoTheSystem()
{
truefill().dashBoard().Url();
truefill().dashBoard().EnterUsername("bjdgfe#swcwr.com");
truefill().dashBoard().EnterPassword("Test1234");
}
///////////////////////////////////////////////
public class Truefill {
private WebDriver driver;
public Truefill(WebDriver driver) {
this.driver=driver;
}
public DashBoardPage dashBoard()
{
return new DashBoardPage(driver);
}
////////////////////////////////////////////////////////////
public class DashBoardPage {
private final WebDriver driver;
By Username= By.xpath("//input[#name='name']");
By Password= By.xpath("//input[contains(#id,'exampleInputPassword1')]");
public DashBoardPage(WebDriver driver) {
this.driver=driver;
}
public void Url()
{
driver.get("https://rahulshettyacademy.com/angularpractice/");
}
public void EnterUsername(String username)
{
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.findElement(Username).sendKeys(username);
}
public void EnterPassword(String password)
{
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.findElement(Password).sendKeys(password);
}
////////////////////////////////////////////////////////////
public class BaseClass {
WebDriver driver;
public WebDriver InitializeDriver()
{
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
return driver;
}
}
Each call to the truefill() method initializes a new instance of WebDriver. Since your test is calling it multiple times, it will start a new browser instance on each line. Instead, store the DashboardPage in a local variable:
#Test
public void userLoginIntoTheSystem() {
DashBoardPage dashBoardPage = truefill().dashBoard();
dashBoardPage.Url();
dashBoardPage.EnterUsername("bjdgfe#swcwr.com");
dashBoardPage.EnterPassword("Test1234");
}
You might also want to use a setup method to initialize the Truefill instance, rather than creating it on demand:
private Truefill truefill;
#BeforeEach
public void initializeTruefill() {
WebDriver driver = InitializeDriver();
truefill = new Truefill(driver);
}
#Test
public void userLoginIntoTheSystem() {
DashBoardPage dashBoardPage = truefill.dashBoard();
dashBoardPage.Url();
dashBoardPage.EnterUsername("bjdgfe#swcwr.com");
dashBoardPage.EnterPassword("Test1234");
}
This assumes JUnit 5. If you're using JUnit 4, the annotation is #Before instead of #BeforeEach.
I'm using cucumber and selenium.
I have three .feature files:
1)auth.feature
2)registration.feature
3)userInformation.feature
I have individual step definitons classes for them
1)authSteps.class
2)registrationSteps.class
3)userInformationSteps.class
IN each class I create webdriver like this
WebDriver driver = new WebDriver(ChromeDriver);
When I run the tests,all driver starts together,even if I have tagged test case and only run 1 case,the webdrivers are started too. #before doesn't work.
I want only to run the feature's webdriver. All if I test all features, I want to run the webdrivers in linear ways.
1.Create one AbstractHook class in TestScript package
public class AbstractHook {
protected static WebDriver driver;
protected WebDriver getdriver() {
if (driver == null) {
System.setProperty("webdriver.gecko.driver","geckodriver.exe");
driver = new FirefoxDriver();
} else if (driver == null) {
System.setProperty("webdriver.chrome.driver",
"chromedriver.exe");
driver = new ChromeDriver();
}
return driver;
}
2.Hook class
public class Hook extends AbstractHook {
AbstractHook df = new AbstractHook();
#Before
public void createdriver() {
df.getdriver();
driver.get("some url");// no need
}
}
3.TestScript code
public class TestScript01 extends AbstractHook {
WebDriver driver = getdriver();
#Given("^I want to open the gmail url on firefox$")
public void i_want_to_open_the_Gmail_url_on_firefox() throws Throwable {
driver.get("give some url");
}
}
4.Runner class
#RunWith(Cucumber.class)
#CucumberOptions(features = "Feature", monochrome = true, glue = { "com.scripts" }, plugin = { "pretty","html:target/cucumber" },
tags = {"#sa,#sanity" },
// dryRun = false)
public class RunnerClass {
}
Try in this way, The driver will be initialized once and used in all the TestScript classes .
I have 2 Java classes; Main.java and Methods.java. At Main.java, I initialize the chrome webdriver and I want to use the same webdriver for a method at Methods.java. Below are the codes.
Under Main.java
Methods getMethods = new Methods();
#BeforeTest
public void Setup()
{
System.setProperty("webdriver.chrome.driver", "C:\\...\\chromedriver.exe");
driver = new ChromeDriver();
driver.get(PropertiesConfig.getObject("websiteUrl"));
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void TestCase1()
{
getMethods.method1();
}
#AfterTest
public void QuitTC() {
getMethods.QuitTC(); }
Under Methods.java
public void method1 (){
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
….. }
public void QuitTC() {
driver.quit();
}
My question is how do I called the initialize Webdriver from Main.java and used it at Methods.java?
Any help with be appreciated! Thanks!
You can do something like this in a utility class (say TestUtil.java)
private static WebDriver wd;
public static WebDriver getDriver() {
return wd;
}
and then you can use following line to get the webdriver in any of the classes mentioned and work on it
WebDriver driver = TestUtil.getDriver();
Declare a global variable for driver like this :
WebDriver driver = null;
#BeforeTest
public void Setup()
{
System.setProperty("webdriver.chrome.driver", "C:\\...\\chromedriver.exe");
driver = new ChromeDriver();
driver.get(PropertiesConfig.getObject("websiteUrl"));
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
Now, you can call method1 from method class like this :
public class Methods{
public Methods(WebDriver driver){
this.driver = driver;
}
public void method1 (){
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
….. }
}
Now once you create the instance of Methods class, constructor would be called and driver reference could be passed.
Try this
Class1 {
public WebDriver driver = null;
public String baseURL="...";
public void openURL() {
System.setProperty("webdriver.chrome.driver", "D:...\\chromedriver.exe");
driver = new ChromeDriver();
driver.get(baseURL);
}
Class2 extends Class1 {
driver.findElement(....);
}
I want use a common WebDriver instance across all my TestNG tests by extending my test class to use a base class as shown below but it doesn't seem to work :
public class Browser {
private static WebDriver driver = new FirefoxDriver();
public static WebDriver getDriver()
{
return driver;
}
public static void open(String url)
{
driver.get(url);
}
public static void close()
{
driver.close();
}
}
I want to use the WebDriver in my test class as shown below, but I get the error message :
The method getDriver() is undefined for the type GoogleTest:
public class GoogleTest extends Browser
{
#Test
public void GoogleSearch() {
WebElement query = getDriver().findElement(By.name("q"));
// Enter something to search for
query.sendKeys("Selenium");
// Now submit the form
query.submit();
// Google's search is rendered dynamically with JavaScript.
// Wait for the page to load, timeout after 5 seconds
WebDriverWait wait = new WebDriverWait(getDriver(), 30);
// wait.Until((d) => { return d.Title.StartsWith("selenium"); });
//Check that the Title is what we are expecting
assertEquals("selenium - Google Search", getDriver().getTitle().toString());
}
}
The problem is that your getDriver method is static.
Solution #1: Make method non-static (this will either need to make the driver variable non-static as well, or use return Browser.getDriver(); )
public WebDriver getDriver() {
return driver;
}
Or, call the getDriver method by using Browser.getDriver
WebElement query = Browser.getDriver().findElement(By.name("q"));
You need to start your driver, one of many solution is to try #Before to add, Junit will autorun it for you.
public class Browser {
private WebDriver driver;
#Before
public void runDriver()
{
driver = new FirefoxDriver();
}
public WebDriver getDriver()
{
return driver;
}
public void open(String url)
{
driver.get(url);
}
public void close()
{
driver.close();
}
}