My code Thread.sleep works but not Implicit Wait?

1.7k views Asked by At

So I understood fluent and explicit waits but I could never get the implicit statements to work in the past. I managed to not deal with them using explicits but I then designed a test that was fairly simple but it would only work with Thread.sleep and I absolutely HATE that method and try to avoid it at all costs. So I attempted the implicit wait function again... fail.

The code below with Thread.Sleep works as intended and is great

package myPackages;

import java.util.concurrent.TimeUnit;

//  Unit test testing the Main User Drop Down Menu
//  This tests the following:
//      - changing status to Online, Away, Busy, Invisible via Left menu 
//      - Going to Settings
//      - Logging out

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class statusTest {

  private static WebDriver driver = new SafariDriver();

  public static String HOME_URL = "http://localhost:3000";
  public static String currentUserStatus;

  private static By usernameOrEmailFieldLocator = By.id("emailOrUsername");
  private static By passwordFieldLocator = By.id("pass");
  private static By loginButtonLocator = By.cssSelector("button.button.primary.login");

  private static By openMenuLocator = By.cssSelector("span.arrow.bottom");

  private static By onlineButtonLocator = By.cssSelector("button.status.online");
  private static By awayButtonLocator = By.cssSelector("button.status.away");
  private static By busyButtonLocator = By.cssSelector("button.status.busy");
  private static By invisibleButtonLocator = By.cssSelector("button.status.offline");
  private static By userStatus = By.className("thumb");


  @BeforeClass
  public static void beforeClass() {
    driver.get(HOME_URL);
    driver.findElement(usernameOrEmailFieldLocator).sendKeys("adrian");
    driver.findElement(passwordFieldLocator).sendKeys("adrian");
    driver.findElement(loginButtonLocator).click();
  }

  @Before
  public void before() throws Exception {
    Thread.sleep(100);
    new WebDriverWait(driver, 3).until(ExpectedConditions.presenceOfElementLocated(openMenuLocator)).click();
    Thread.sleep(100);
    new WebDriverWait(driver, 3).until(ExpectedConditions.presenceOfElementLocated(onlineButtonLocator)).click();
  }

  @AfterClass
  public static void doEnd() {
    driver.quit();
  }

  private static void changeStatusTo(By statusLocator) throws Exception {
    Thread.sleep(100);
    new WebDriverWait(driver, 3).until(ExpectedConditions.presenceOfElementLocated(statusLocator)).click();
    Thread.sleep(100);
    currentUserStatus = driver.findElement(userStatus).getAttribute("data-status");
  }

  @Test
  public void setAway() throws Exception {
    changeStatusTo(awayButtonLocator);
    Assert.assertEquals("away", currentUserStatus);
  }

  @Test
  public void setOnline() throws Exception {
    changeStatusTo(onlineButtonLocator);
    Assert.assertEquals("online", currentUserStatus);
  }

  @Test
  public void setBusy() throws Exception {
    changeStatusTo(busyButtonLocator);
    Assert.assertEquals("busy", currentUserStatus);
  }

  @Test
  public void setInvisible() throws Exception {
    changeStatusTo(invisibleButtonLocator);
    Assert.assertEquals("invisible", currentUserStatus);
  }

}

but when I end up trying to use the implicit (such as below) it doesn't work. I ensure to declare it once (in this case the @beforeclass) right after the driver is declared. The tests would fail within the Before class. I included the trace stack at the very bottom on this page:

package myPackages;

import java.util.concurrent.TimeUnit;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class statusTest {

    private static WebDriver driver = new SafariDriver();

    public static String HOME_URL = "http://localhost:3000";
    public static String currentUserStatus;

    private static By usernameOrEmailFieldLocator = By.id("emailOrUsername");
    private static By passwordFieldLocator = By.id("pass");
    private static By loginButtonLocator = By.cssSelector("button.button.primary.login");

    private static By openMenuLocator = By.cssSelector("span.arrow.bottom");

    private static By onlineButtonLocator = By.cssSelector("button.status.online");
    private static By awayButtonLocator = By.cssSelector("button.status.away");
    private static By busyButtonLocator = By.cssSelector("button.status.busy");
    private static By invisibleButtonLocator = By.cssSelector("button.status.offline");
    private static By userStatus = By.className("thumb");


    @BeforeClass
    public static void beforeClass(){
        driver.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
        driver.get(HOME_URL);
        driver.findElement(usernameOrEmailFieldLocator).sendKeys("adrian");
        driver.findElement(passwordFieldLocator).sendKeys("adrian");
        driver.findElement(loginButtonLocator).click();
    }

    @Before
    public void before() throws Exception {
        driver.findElement(openMenuLocator).click();
        driver.findElement(onlineButtonLocator).click();
    }

    @AfterClass
    public static void doEnd() {
        driver.quit();
    }

    private static void changeStatusTo(By statusLocator) {
        driver.findElement(statusLocator).click();
        currentUserStatus = driver.findElement(userStatus).getAttribute("data-status");

    }

    @Test
    public void setAway() {
        changeStatusTo(awayButtonLocator);
        Assert.assertEquals("away", currentUserStatus);
    }

    @Test
    public void setOnline() {
        changeStatusTo(onlineButtonLocator);
        Assert.assertEquals("online", currentUserStatus);
    }

    @Test
    public void setBusy() {
        changeStatusTo(busyButtonLocator);
        Assert.assertEquals("busy", currentUserStatus);
    }

    @Test
    public void setInvisible() {
        changeStatusTo(invisibleButtonLocator);
        Assert.assertEquals("invisible", currentUserStatus);
    }

}

org.openqa.selenium.NoSuchElementException: An element could not be located on the page using the given search parameters. (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 999 milliseconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html Build info: version: 'unknown', revision: '1969d75', time: '2016-10-18 09:43:45 -0700' System info: host: 'Adrians-iMac.local', ip: '10.0.2.15', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.12.1', java.version: '1.8.0_111' Driver info: org.openqa.selenium.safari.SafariDriver Capabilities [{applicationCacheEnabled=true, rotatable=false, databaseEnabled=true, handlesAlerts=true, version=12602.2.14.0.5, cleanSession=true, platform=MAC, nativeEvents=true, locationContextEnabled=false, webStorageEnabled=true, browserName=safari, javascriptEnabled=true, cssSelectorsEnabled=true}] Session ID: DADE0351-039B-4C06-BC65-05FB90E08202 *** Element info: {Using=css selector, value=span.arrow.bottom} at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:216) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:168) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:635) at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:368) at org.openqa.selenium.remote.RemoteWebDriver.findElementByCssSelector(RemoteWebDriver.java:465) at org.openqa.selenium.By$ByCssSelector.findElement(By.java:430) at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:360) at myPackages.statusTest.before(statusTest.java:53) 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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

1

There are 1 answers

7
prithvi394 On

Use TimeUnit.SECONDS in your implicit waits instead of milliseconds. Quick glance through your code indicates that you have used 100 milliseconds in implicit wait which is very nominal compared to 3 seconds assigned in explicit wait.

 driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//waits for 3 seconds

Note:unit for explicit wait is in seconds.

 new WebDriverWait(driver, 10) //will wait for 10 seconds 

1000ms=1s

You should be using 3000ms in implicit wait if timeunit HAS to be in milliseconds.