Selenium get value of current implicit wait - selenium

I realize that Selenium has a default value for implicit waits, but how do I get this value if I change it? For example:
driver.implicitly_wait( 13 );
How do I later get the 13 value from the driver?

Unfortunately there's no getter for that.
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/WebDriver.Timeouts.html
There isn't for explicit waits either.
http://selenium.googlecode.com/svn/trunk/docs/api/java/com/thoughtworks/selenium/Wait.html

I know I'm a couple years late, and #JaneGoodall is not wrong -- there is no built-in function for that. But it's not impossible!
It's not very difficult to create your own versions of the WebDriver interface and browser-specific driver class. And then, you can put whatever code you want into the driver!
Example:
MyDriver.java (specialized version of WebDriver, not quite mandatory but a very good idea):
public interface MyDriver extends WebDriver {
void setWait(int timeout);
int getWait();
}
MyChrome.java (specialized version of ChromeDriver -- works the same for any browser)
public class MyChrome extends ChromeDriver implements MyDriver {
int timeout = 0;
public void setWait(int timeout) {
this.timeout = timeout;
this.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
}
public int getWait() {
return timeout;
}
}
And now, to use it, MyProgram.java:
public class MyProgram {
MyDriver driver = new MyChrome();
driver.setWait(10);
assert(driver.getWait() == 10);
}
I hope this is helpful!

For those who came here from google. In 2018 it seems like there is a method to get those timeouts at least in javascript (I know question was about java):
const {implicit, pageLoad, script} = await driver.manage().getTimeouts();
Hope this will help.

TL;DR - This is not a solution to get implicit waits. You cannot get the implicit wait in Java even today, without using a workaround like this.
In 2020, selenium 3.141.59 still does not have a getter for any timeouts. The WebDriver interface has a nested interface Timeouts which does not define any getters. RemoteWebDriver, which is the parent of Chrome and Firefox drivers, implements the WebDriver interface and it does not add a getter for timeouts.
RemoteWebDriver implements WebDriver.Timeouts, but it does not store the value of implicit timeout anywhere, as you can see from the code below.
protected class RemoteTimeouts implements Timeouts {
public Timeouts implicitlyWait(long time, TimeUnit unit) {
execute(DriverCommand.SET_TIMEOUT, ImmutableMap.of(
"implicit", TimeUnit.MILLISECONDS.convert(time, unit)));
return this;
}
public Timeouts setScriptTimeout(long time, TimeUnit unit) {
execute(DriverCommand.SET_TIMEOUT, ImmutableMap.of(
"script", TimeUnit.MILLISECONDS.convert(time, unit)));
return this;
}
public Timeouts pageLoadTimeout(long time, TimeUnit unit) {
execute(DriverCommand.SET_TIMEOUT, ImmutableMap.of(
"pageLoad", TimeUnit.MILLISECONDS.convert(time, unit)));
return this;
}
} // timeouts class.
The execute() method in the RemoteWebDriver takes the wait inside a Map of parameters, but it does not make that map or the wait settings accessible to us via a getter.
protected Response execute(String driverCommand, Map<String, ?> parameters)
//Open the source code to see why you can't make your own getter for implicitWait.

This can print real timeout value (plus calculating time, usually within 100ms):
public void getCurrentWaitTimeout() {
long milliseconds = java.time.ZonedDateTime.now().toInstant().toEpochMilli();
driver.findElements(By.cssSelector(".nonExistingElement"));
milliseconds = java.time.ZonedDateTime.now().toInstant().toEpochMilli() - milliseconds;
log.info("Current waiting timeout is {} milliseconds", milliseconds);
}
So you can always call such a method to be sure you know actual timeout, not the value you tried to set.

For Java version of Selenium, org.seleniumhq.selenium:selenium-api:4.0.0-beta-4
allows you to get the current implicit wait duration:
WebDriver.manage().timeouts().getImplicitWaitTimeout()
With this method, it makes possible to temporarily change the timeout to let's say 1 second and restore it afterwards:
final Duration originalTimeout = driver.manage().timeouts().getImplicitWaitTimeout();
driver.manage().timeouts().implicitlyWait(Duration.of(1, ChronoUnit.SECONDS));
... // do something
// restore the original timeout
driver.manage().timeouts().implicitlyWait(originalTimeout);
Probably, this functionality is present even before selenium-api:4.0.0-beta-4.

I get the defined implicitTimeout with:
driver.manage().timeouts().getImplicitWaitTimeout().getSeconds()

Many years later, in Python, using selenium 4.4.3 you can access the timeouts very easily via simply:
print(driver.timeouts.implicit_wait)
print(driver.timeouts.page_load)
print(driver.timeouts.script)
Note that when I call driver.implicitly_wait(60), it changed the implicit_wait value only.
Also, there is no such function as driver.manage() in Python, as in the Java answers above.

Related

WebDriverWait Selenium approach

Regarding the WebDriverWait data type, I am assuming that only one instance is needed of such data type, which means I could potentially create a wrapper and allow only one instance creation by using a singleton pattern approach.
At the present time I used thread.sleep and basically everywhere I need that function to be called I am extending from the class which probably not the best approach. Also of course I should be using WebDriverWait instead of thread. What should the approach be?
So far I created a page object with web elements and a separate service for the logic itself, so now I need also WebDriverWait in every service since it’s a necessary operation.
A cookie window that gets popped up once customer opened the page:
/**
* acceptCookies -> clickable
* cookieBanner -> just to identify that cookie component showed up.
* PageFactory -> will initialize every WebElement variable with a reference to a corresponding element on the actual web page.
*/
public class CookieModal {
WebDriver driver;
#FindBy(css = ".cookie-accept-all")
public WebElement acceptCookies;
public CookieModal(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
}
Then I separated the service (actions):
public class CookieService {
private final CookieModal cookieModal;
public CookieService(WebDriver driver) {
this.cookieModal = new CookieModal(driver);
}
public void acceptCookies() {
cookieModal.acceptCookies.click();
}
}
This must be changed to WebDriverWait, but I also think extending from AbstractPage in every page object is not necessary. Is my structure OK and how should I initialise WebDriverWait?
public class AbstractPage {
// This is not good as thread sleep is not dynamic and you
// have to specify time yourself change to webdriver wait
private AbstractPage microsleep(Integer milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (Throwable e) {
String error = String.format("Unable to put thread to sleep (requested %d milliseconds).", milliseconds);
throw new RuntimeException(error, e);
}
return this;
}
public AbstractPage emulateWaitingUser() {
return microsleep(800);
}
public AbstractPage sleep(Integer seconds) {
return microsleep(1000 * seconds);
}
Selenium supports integrating explicit waits into page objects. This is achieved by using a special way of how you initialize your page. In your example you are doing this:
PageFactory.initElements(driver, this);
which involves some basic default way. However, you can add more complexity here, but you get a more effective architecture at the same time.
You can extend the AjaxElementLocator class where you will override isElementUsable method in the way that would involve any sort of condition and waits. Then you will be initializing your page(s) with that locator through a dedicated LocatorFactory. Some example of how to use all that classes you can find here.
WebDriverWait is commonly used with the ExpectedConditions class. In that case, you cannot just wait for 800 ms. You need to wait until a condition is met. For example, wait until page title is displayed, or wait until loader icon is not visible, wait until login button is clickable, etc.
That means if you wish to instantiate a wait in an abstract method, you will need to add an unknown (and non-abstract) wait condition. You could just instantiate a general wait object and then add a condition when it is known, but it seems a bit incomplete.
Another idea that comes to my mind is declaring WebDriverWait as a field in Cookie Service class and pass it to its methods.

Do we need to give less time declared for ExplicitWait compared to Implicitwait

Somewhere I read that mixing Implicit and Explicit gives unprecitable result. Is it true?
Source: https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#advanceduserinteractions
WARNING: Do not mix implicit and explicit waits! Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.
In that case, do we need to give less time/equal to Implicit wait???
Honestly, with a good implementation of test automation framework, you don't need implicitWait. You should always explicitly wait for the conditions.
The implicit wait might cause your tests to run slower. Automated Test Suite should always run as fast as possible to provide feedback to the team.
BUT, if you insist on using it, you can simply create some kind of method/class where you turn off implicit waits, perform explicit wait, and restore implicit wait value.
Something like this:
public class Wait {
private static final int IMPLICIT_WAIT_TIME = 10; //store your default implicit wait here or use .properties file
private WebDriver driver;
private int timeout = 10;
private List<Class<? extends Throwable>> exceptions = new ArrayList<>();
public Wait(WebDriver driver) {
this.driver = driver;
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //turn off implicit wait
}
public Wait setTimeout(int seconds) {
this.timeout = seconds;
return this;
}
#SafeVarargs
public final Wait ignoring(Class<? extends Throwable>... exceptions) {
this.exceptions.addAll(Arrays.asList(exceptions));
return this;
}
public void until(ExpectedCondition... expectedConditions) {
WebDriverWait wait = new WebDriverWait(driver, timeout);
if (exceptions.size() > 0) {
wait.ignoreAll(exceptions);
}
wait.until(ExpectedConditions.and(expectedConditions));
driver.manage().timeouts().implicitlyWait(IMPLICIT_WAIT_TIME, TimeUnit.SECONDS); //restore implicit wait
}
}

Setting up selenium webdriver for parallel execution

I am trying to execute a large suite of selenium tests via xUnit console runner in parallel.
These have executed and I see 3 chrome windows open, however the first send key commands simply executes 3 times to one window, resulting in test failure.
I have registered my driver in an objectcontainer before each scenario as below:
[Binding]
public class WebDriverSupport
{
private readonly IObjectContainer _objectContainer;
public WebDriverSupport(IObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}
[BeforeScenario]
public void InitializeWebDriver()
{
var driver = GetWebDriverFromAppConfig();
_objectContainer.RegisterInstanceAs<IWebDriver>(driver);
}
And then call the driver in my specflow step defintions as:
_driver = (IWebDriver)ScenarioContext.Current.GetBindingInstance(typeof(IWebDriver));
ScenarioContext.Current.Add("Driver", _driver);
However this has made no difference and it seems as if my tests are trying to execute all commands to one driver.
Can anyone advise where I have gone wrong ?
You shouldn't be using ScenarioContext.Current in a parallel execution context. If you're injecting the driver through _objectContainer.RegisterInstanceAs you will receive it through constructor injection in your steps class' constructor, like so:
public MyScenarioSteps(IWebDriver driver)
{
_driver = driver;
}
More info:
https://github.com/techtalk/SpecFlow/wiki/Parallel-Execution#thread-safe-scenariocontext-featurecontext-and-scenariostepcontext
https://github.com/techtalk/SpecFlow/wiki/Context-Injection
In my opinion this is horribly messy.
This might not be an answer, but is too big for a comment.
why are you using the IObjectContainer if you are just getting it from the current scenario context and not injecting it via the DI mechanism? I would try this:
[Binding]
public class WebDriverSupport
{
[BeforeScenario]
public void InitializeWebDriver()
{
var driver = GetWebDriverFromAppConfig();
ScenarioContext.Current.Add("Driver",driver);
}
}
then in your steps:
_driver = (IWebDriver)ScenarioContext.Current.Get("Driver");
As long as GetWebDriverFromAppConfig returns a new instance you should be ok...

phpunit selenium usage

My question is about phpunit+selenium usage.
The standard usage of this union is
class BlaBlaTest extends PHPUnit_Extensions_SeleniumTestCase
{... }
OR
class BlaBlaTest extends PHPUnit_Extensions_Selenium2TestCase
{...}
The first one (PHPUnit_Extensions_SeleniumTestCase) is not very convinient to use
(e.g. there is no such thing as $this->elements('xpath')).
Second(PHPUnit_Extensions_Selenium2TestCase) also has limited functionality
(e.g. there is no such functions as waitForPageToLoad() or clickAndWait(),
and using something like $this->timeouts()->implicitWait(10000) looks for me like
complete nonsense).
Is it possible to use the functional
PHPUnit_Extensions_SeleniumTestCase + PHPUnit_Extensions_Selenium2TestCase
in one test class?
Maybe smb knows good alternatives to phpunit+selenium?
Inspired by Dan I've written this for use in PHPUnit_Extensions_Selenium2TestCase and it seems to work ok:
/**
* #param string $id - DOM id
* #param int $wait - maximum (in seconds)
* #retrn element|false - false on time-out
*/
protected function waitForId($id, $wait=30) {
for ($i=0; $i <= $wait; $i++) {
try{
$x = $this->byId($id);
return $x;
}
catch (Exception $e) {
sleep(1);
}
}
return false;
}
Sorry for resurrecting this but I'd like to hopefully clear up some confusion for anyone stumbling across this.
You're saying that you wanted functionality from RC and WebDriver combined where there are workarounds to it, but I wouldn't recommend it. Firstly you'll need to understand the difference between both frameworks.
My brief definitions...
Selenium RC (PHPUnit_Extensions_SeleniumTestCase) is script oriented. By that I mean it will run your tests exactly how you expect the page to respond. This often will require more explicit commands such as the waitForPageToLoad() that you have mentioned when waiting for elements to appear and/or pages to loads.
Selenium WebDriver (PHPUnit_Extensions_Selenium2TestCase) uses a more native approach. It cuts off 'the middle-man' and runs your tests through your chosen browsers driver. Using the waitForPageToLoad() example, you wont need to explicitly put that wherever you open a page in your code because the WebDriver already knows when the page is loading and will resume the test when the page load request is complete.
If you need to define an implicit timeout in WebDriver, you will only need to place that in the setUp() method within a base Selenium class that will be extended in your test classes;
class BaseSelenium extends PHPUnit_Extensions_Selenium2TestCase {
protected function setUp() {
// Whatever else needs to be in here like setting
// the host url and port etc.
$this->setSeleniumServerRequestsTimeout( 100 ); // <- seconds
}
}
That will happily span across all of your tests and will timeout whenever a page takes longer than that to load.
Although I personally prefer WebDriver over RC (mainly because it's a lot faster!) there is a big difference between the methods available. Whenever I got stuck when recently converting a lot a RC tests to WebDriver I always turned to this first. It's a great reference to nearly every situation.
I hope that helps?
For functions such as waitForPageToLoad() and clickAndWait(), which are unavailable in Selenium2, you can reproduce those functions by using try catch blocks, in conjunction with implicit waits and explicit sleeps.
So, for a function like clickAndWait(), you can define what element you are waiting for, and then check for that element's existence for a set amount of seconds. If the element doesn't exist, the try catch block will stop the error from propagating. If the element does exist, you can continue. If the element doesn't exist after the set amount of time, then bubble up the error.
I would recommend using Selenium2 and then reproducing any functionality that you feel is missing from within your framework.
EXAMPLE:
def wait_for_present(element, retry = 10, seconds = 2)
for i in 0...retry
return true if element.present?
sleep(seconds)
end
return false
end
you can try use traits to extend two different classes http://php.net/manual/en/language.oop5.traits.php
class PHPUnit_Extensions_SeleniumTestCase{
...
}
change PHPUnit_Extensions_Selenium2TestCase class to trait:
trait PHPUnit_Extensions_Selenium2TestCase {
...
}
class blabla extends PHPUnit_Extensions_SeleniumTestCase {
use PHPUnit_Extensions_Selenium2TestCase;
your tests here..
}

Glassfish - JEE6 - Use of Interceptor to measure performance

For measuring execution time of methods, I've seen suggestions to use
public class PerformanceInterceptor {
#AroundInvoke
Object measureTime(InvocationContext ctx) throws Exception {
long beforeTime = System.currentTimeMillis();
Object obj = null;
try {
obj = ctx.proceed();
return obj;
}
finally {
time = System.currentTimeMillis() - beforeTime;
// Log time
}
}
Then put
#Interceptors(PerformanceInterceptor.class)
before whatever method you want measured.
Anyway I tried this and it seems to work fine.
I also added a
public static long countCalls = 0;
to the PerformanceInterceptor class and a
countCalls++;
to the measureTime() which also seems to work o.k.
With my newby hat on, I will ask if my use of the countCalls is o.k. i.e
that Glassfish/JEE6 is o.k. with me using static variables in a Java class that is
used as an Interceptor.... in particular with regard to thread safety. I know that
normally you are supposed to synchronize setting of class variables in Java, but I
don't know what the case is with JEE6/Glassfish. Any thoughts ?
There is not any additional thread safety provided by container in this case. Each bean instance does have its own instance of interceptor. As a consequence multiple thread can access static countCalls same time.
That's why you have to guard both reads and writes to it as usual. Other possibility is to use AtomicLong:
private static final AtomicLong callCount = new AtomicLong();
private long getCallCount() {
return callCount.get();
}
private void increaseCountCall() {
callCount.getAndIncrement();
}
As expected, these solutions will work only as long as all of the instances are in same JVM, for cluster shared storage is needed.