I have a issue with selenium where i am able to pass the testcase, but the issue is the execution of the testcase is very quick. Is there any way or attribute through which i can control the speed of the execution. I have been facing this problem big time. Any help will be greatly appreciated.
Below is my script for reference.
package test.selenium;
import java.util.concurrent.TimeoutException;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class test{
WebDriver driver;
public TrafficGroupUpdateTestNG() {
}
/**
* #throws java.lang.Exception
*/
#BeforeTest
public void setUp() throws Exception {
// Use Internet Explorer and set driver;
System.setProperty("webdriver.ie.driver",
"D:\\IBM\\Selenium\\IEDriverServer.exe");
driver = new InternetExplorerDriver();
// And now use this to visit URL
driver.get("URL Of JSP");
}
/**
* #throws java.lang.Exception
*/
#AfterTest
public void tearDown() throws Exception {
driver.close();
}
#Test
public final void test() {
final WebElement formElement = driver.findElement(By.id("search"));
final Select drelement = new Select(drelement.findElement(By.id("my_input")));
drelement.selectByIndex(0);
final WebElement submit = driver.findElement(By.id("Submit"));
submit.click();
}
}
It sounds like elements from AJAX calls are not visible or ready when document.ready status is updated. Working with my webdevs, I had them add a waiting class while they loaded things and remove it when they're done.
As a result, I was able to create this "WaitForPageLoad" method that waits until AJAX is finished. It's in C# but simple enough to translate into Java.
I used
Thread.sleep(2000);
A convinient way for making the page wait.
There are many ways you can control speed of the execution..
Implicity wait
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
by providing this imlicity wait, webdriver waits until 20 seconds before it returns object not found
explicit wait
WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
This will wait explicitly for given element..
Related
Tring to click on the input box, with script able to open the URL-https://jqueryui.com/datepicker/.In locator the id is available still getting No element foun.
Tried with thread.sleep as well
when i am running the script getting exception
package SeleniumWebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class HandlingCalender {
public static void main(String[] args) throws InterruptedException {
WebDriver driver =new ChromeDriver();
driver.get("https://jqueryui.com/datepicker/");
//driver.manage().window().maximize();
Thread.sleep(1000);
driver.findElement(By.id("datepicker")).click();
Element you trying to access is inside an iframe.
So, to access it you need first to switch into that iframe, as following:
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.class("demo-frame")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("datepicker"))).click();
I am working with Selenium Standalone Server 3.0.1. I am trying to add an Explicit Wait to my code to detect an element through xpath when the element becomes visible. In order to get some Java help I looked out for the source code for Selenium Standalone Server 3.0.1 but was unable to find it. I found the source code in selenium-java-2.53.1 release. I downloaded it and found selenium-java-2.53.1-srcs and added to my Eclipse IDE. From the help of FluentWait, I simply copy pasted the code in my Eclipse IDE and changed the variable names.
The sample code in documentation is like:
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
But when I implement this code, simply copy pasting it:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("//p[text()='WebDriver']"));
}
});
I am getting an error on FluentWait Class as The type FluentWait is not generic; it cannot be parameterized with arguments <WebDriver>
Here is the list of my imports:
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
Can anyone help me out please?
Update
Added an answer with respect to the modified constructor of FluentWait in Selenium v3.11.0
With the availability of Selenium v3.11.0 the constructor of FluentWait have changed. Now the argument type for withTimeout and pollingEvery is Duration. Here is the modified implementation :
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
public class Fluent_Wait {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.google.com");
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 500 milliseconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.name("q"));
}
});
}
}
I was also facing the same error, later I noticed that I was using the class name as fluentwait. After changing the class name it was working fine.
You need to specify expected condition inside the wait below is the modified code that could solve your problem.
Code:
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
public class DummyClass
{
WebDriver driver;
#Test
public void test()
{
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
until(new Function<WebElement, Boolean>()
{
public Boolean apply(WebElement element)
{
return element.getText().endsWith("04");
}
private void until(Function<WebElement, Boolean> function)
{
driver.findElement(By.linkText("Sample Post2"));
}
}
}
}
The simplest solution is to use the other method implementation:
withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(2))
The form withTimeout(Duration timeOut)
is still used and non-deprecated one
I was also facing same error that The type FluentWait is not generic; it cannot be parameterized with arguments <WebDriver> but i noticed a silly mistake that my main class was also named as FuentWait and it was not generic. I changed its name and error went away.
I got the same error since I named the class 'FluentWait' that I created in eclipse to implement fluent wait. Try renaming the class to a different name.
I am working with Selenium Standalone Server 3.0.1. I am trying to add an Explicit Wait to my code to detect an element through xpath when the element becomes visible. In order to get some Java help I looked out for the source code for Selenium Standalone Server 3.0.1 but was unable to find it. I found the source code in selenium-java-2.53.1 release. I downloaded it and found selenium-java-2.53.1-srcs and added to my Eclipse IDE. From the help of FluentWait, I simply copy pasted the code in my Eclipse IDE and changed the variable names.
The sample code in documentation is like:
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
But when I implement this code, simply copy pasting it:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("//p[text()='WebDriver']"));
}
});
I am getting an error on FluentWait Class as The type FluentWait is not generic; it cannot be parameterized with arguments <WebDriver>
Here is the list of my imports:
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
Can anyone help me out please?
Update
Added an answer with respect to the modified constructor of FluentWait in Selenium v3.11.0
With the availability of Selenium v3.11.0 the constructor of FluentWait have changed. Now the argument type for withTimeout and pollingEvery is Duration. Here is the modified implementation :
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
public class Fluent_Wait {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.google.com");
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 500 milliseconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.name("q"));
}
});
}
}
I was also facing the same error, later I noticed that I was using the class name as fluentwait. After changing the class name it was working fine.
You need to specify expected condition inside the wait below is the modified code that could solve your problem.
Code:
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
public class DummyClass
{
WebDriver driver;
#Test
public void test()
{
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
until(new Function<WebElement, Boolean>()
{
public Boolean apply(WebElement element)
{
return element.getText().endsWith("04");
}
private void until(Function<WebElement, Boolean> function)
{
driver.findElement(By.linkText("Sample Post2"));
}
}
}
}
The simplest solution is to use the other method implementation:
withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(2))
The form withTimeout(Duration timeOut)
is still used and non-deprecated one
I was also facing same error that The type FluentWait is not generic; it cannot be parameterized with arguments <WebDriver> but i noticed a silly mistake that my main class was also named as FuentWait and it was not generic. I changed its name and error went away.
I got the same error since I named the class 'FluentWait' that I created in eclipse to implement fluent wait. Try renaming the class to a different name.
Disclaimer: I come from a dynamic language background (Ruby) and I'm trying to level up my skills in Java. I fear with my problem here I'm thinking too much in the context of Ruby and would appreciate some pointers.
Problem:
I want to see how I can have a helper class know about the existence of a WebDriver instance without having to pass the instance around all the time. The reason I'm trying to avoid that is because it leads to extra method arguments and less fluent test writing.
Context:
I have a test case (LoginIT.java) that looks like this:
package com.testerstories.learning.symbiote;
import static com.testerstories.learning.helpers.Selenium.*;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class LoginIT {
WebDriver driver;
#BeforeTest
public void startBrowser() {
driver = new FirefoxDriver();
}
#AfterTest
public void quitBrowser() {
driver.quit();
}
#Test
public void loginAsAdmin() {
driver.get("http://localhost:9292");
withElement("open").click();
waitForPresence("username");
withElement("username").sendKeys("admin");
withElement("password").sendKeys("admin");
withElement("login-button").submit();
waitForPresence("notice");
assertThat(withElement("notice", "className"), equalTo("You are now logged in as admin."));
}
}
The key methods to note here are the calls to withElement and waitForPresence. These are defined on the Selenium class that I created and reference via the static import at the top.
Here is Selenium.java which contains that logic:
package com.testerstories.learning.helpers;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Selenium {
public static WebElement withElement(String identifier, String locator) {
switch (locator) {
case "className":
return driver.findElement(By.className(identifier));
default:
return withElement(identifier);
}
}
public static WebElement withElement(String identifier) {
return driver.findElement(By.id(identifier));
}
public static void waitForPresence(String identifier, String locator) {
WebDriverWait wait = new WebDriverWait(driver, 10, 500);
switch (locator) {
case "className":
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className(identifier)));
default:
waitForPresence(identifier);
}
}
public static void waitForPresence(String identifier) {
WebDriverWait wait = new WebDriverWait(driver, 10, 500);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(identifier)));
}
}
The key problem here are the lines that reference driver. When these methods were defined in LoginIT.java that wasn't an issue because WebDriver is defined there in the driver instance.
I do know that one answer to my problem is that I could just pass the WebDriver instance to each method. So, for example, I could use this method signature with withElement:
public static WebElement withElement(WebDriver driver, String identifier)
I'm adding another argument to pass in the WebDriver instance. But that means my test logic has to look like this:
withElement(driver, "username").sendKeys("admin");
withElement(driver, "password").sendKeys("admin");
withElement(driver, "login-button").submit();
Not the end of the world but it's less fluent and it just seems like there should be a better way.
Question:
Is there a better way?
Or am I in fact on the right track and should just accept that if I want the helper methods to be separate from the tests the driver reference must be passed in? And thus accept the slightly more verbose test statements?
Other Thought:
The only other thing I can immediately think of is that I create yet a third class that represents just WebDriver itself. This third class is then used by both my test (LoginIt.java) and my test helper (Selenium.java). I'm not sure how best to implement that but I'm also not sure if going that route makes sense.
I say that because it seems if I do that, I'm simply creating a class to wrap the creation of a WebDriver instance. So I have to create a class to then get an instance of that class so that I can create an instance of WebDriver. It seems like I'm adding complexity ... but maybe not. Hence my quest for pointers.
An alternative may be to allow your Selenium class to be initialized. Rather than having the methods be static, you can require the WebDriver reference in the class constructor.
package com.testerstories.learning.helpers;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Selenium {
private final WebDriver driver;
public Selenium(WebDriver webDriver) {
this.driver = webDriver;
}
public WebElement withElement(String identifier, String locator) {
switch (locator) {
case "className":
return driver.findElement(By.className(identifier));
default:
return withElement(identifier);
}
}
public WebElement withElement(String identifier) {
return driver.findElement(By.id(identifier));
}
public void waitForPresence(String identifier, String locator) {
WebDriverWait wait = new WebDriverWait(driver, 10, 500);
switch (locator) {
case "className":
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className(identifier)));
default:
waitForPresence(identifier);
}
}
public void waitForPresence(String identifier) {
WebDriverWait wait = new WebDriverWait(driver, 10, 500);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(identifier)));
}
}
Your LoginIT.java would then initialize the reference with in the #Before along with the driver, and change the formerly static calls to the instance you stood up:
package com.testerstories.learning.symbiote;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.testerstories.learning.helpers.Selenium;
public class LoginIT {
WebDriver driver;
Selenium selenium;
#BeforeTest
public void startBrowser() {
driver = new FirefoxDriver();
selenium = new Selenium(driver);
}
#AfterTest
public void quitBrowser() {
driver.quit();
}
#Test
public void loginAsAdmin() {
driver.get("http://localhost:9292");
selenium.withElement("open").click();
selenium.waitForPresence("username");
selenium.withElement("username").sendKeys("admin");
selenium.withElement("password").sendKeys("admin");
selenium.withElement("login-button").submit();
selenium.waitForPresence("notice");
assertThat(selenium.withElement("notice", "className"), equalTo("You are now logged in as admin."));
}
}
I'm not entirely certain if this solution follows best design practices, but here is what I ended up doing. (Note: I changed from TestNG to JUnit but other than that, everything is functionally equivalent.)
I created a Driver.java class:
package com.testerstories.learning.helpers;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class Driver {
private WebDriver driver;
public WebDriver getDriver() {
if (null == driver) {
driver = new FirefoxDriver();
}
return driver;
}
public void quitDriver() {
if (null != driver) {
driver.quit();
driver = null;
}
}
}
So this class is responsible for creating a driver instance and getting rid of that instance. It checks if the driver is null before creating so it won't keep creating new instances. Here I'm hard-coding a new instance of Firefox. Eventually I would have to make this class create new browser drivers based on what the user wants, but baby steps first.
Then I created DriverFactory.java which looks like this:
package com.testerstories.learning.helpers;
import org.junit.After;
import org.junit.Before;
import org.openqa.selenium.WebDriver;
public class DriverFactory {
private static Driver driver;
#Before
public void createDriver() {
driver = new Driver();
}
public static WebDriver getDriver() {
return driver.getDriver();
}
#After
public void quitDriver() {
driver.quitDriver();
}
}
This factory is used to create the driver instances. Notice the #Before and #After annotations. So this is where the tests have to rely on the driver factory. So what this means is that my tests now inherit the DriverFactory, whose responsibility is to provide an actual driver instance. So my LoginIT.java test now changes to this (continuing to use Jeremiah's provided solution as well):
package com.testerstories.learning.symbiote;
import com.testerstories.learning.helpers.DriverFactory;
import com.testerstories.learning.helpers.Selenium;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class LoginIT extends DriverFactory {
WebDriver driver;
Selenium selenium;
#Test
public void loginAsAdmin() {
driver = DriverFactory.getDriver();
selenium = new Selenium(driver);
driver.get("http://localhost:9292");
selenium.withElement("open").click();
selenium.waitForPresence("username");
selenium.withElement("username").sendKeys("admin");
selenium.withElement("password").sendKeys("admin");
selenium.withElement("login-button").submit();
selenium.waitForPresence("notice", "className");
assertThat(selenium.withElement("notice", "className").getText(), equalTo("You are now logged in as admin."));
}
}
I'm still doing some (all?) of the things that jpmc26 was concerned about and I can't honestly say I'm doing this well. But this does work.
If anyone has any thoughts -- particularly critical ones -- I'm most open to hearing them. As mentioned in my original question, I'm attempting to get better at Java after many, many years as a Ruby programmer. It's been rough going, to say the least.
Trying to test/learn selenium to login
the error - Exception in thread "main" org.openqa.selenium.ElementNotVisibleException: element not visible
package com.indeed.tests;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class test1 {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver",
"C:\\Users\\****\\Desktop\\neww\\trainingfiles\\chromedriver.exe.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.neopets.com/login/index.phtml");
driver.findElement(By.name("username")).sendKeys("test1");
}
private static void sleep(int i) {
}
}
I had a look at that web page. The problem is that there are two input fields with the name "username". One of them is not visible. Probably Selenium is getting that one. What you should do is:
List<WebElement> elements = driver.findElements(...);
and then get the second one (or the first, whatever), then try:
elements.get(1).sendKeys(...);