3 Technical Testing Books to improve your test tech skills
August 13, 2020Base Test Class Testing Pattern: Why and How to use
August 31, 2020Introduction
This post exists because I had a question on Linkedin when I was sharing the following post that explains about the Implicitly and Explicitly waits: Explicit Wait and Implicit Wait in Selenium: Finally Explained!
I won’t explain the difference because there are tons of blog posts and articles about it, but I’ll give you my opinion: only use Explicitly Wait.
It’s ok if you don’t know the difference or disagree with my point of view, and I would love to discuss it with you in the comment section. ????
Manage different waiting times using Explicitly Wait
The scenario
Let’s say you have set a global timeout as 5 seconds (for me it’s a plausible waiting time for the test automation scripts. You are using the global timeout in all your waits but you also have to upload a file, and it can take more than 5 seconds. What you should do?
The solution
You can override the wait for this certain element when you are uploading a file without affecting the global timeout using the withTimeout
method only for this specific wait.
public class ExplicitlyWaitExampleTest {
private WebDriver driver;
private WebDriverWait wait;
@BeforeClass
public void preCondition() {
driver = new ChromeDriver();
}
@BeforeMethod
public void beforeEachTest() {
wait = new WebDriverWait(driver, Duration.ofSeconds(5));
}
@Test
public void usingRegularTimeout1() {
WebElement menu = driver.findElement(By.id("buger"));
wait.until(ExpectedConditions.visibilityOf(menu));
}
@Test
public void usingRegularTimeout2() {
By cpf = By.name("cpf_document");
wait.until(ExpectedConditions.presenceOfElementLocated(cpf));
}
@Test
public void overridingDefaultTimeout() {
By uploadSuccessfull = By.cssSelector(".sucess.upload");
// overriding the default timeout only for this wait
wait.
withTimeout(Duration.ofSeconds(30)).
withMessage("timeout while waiting for upload to finish").
until(ExpectedConditions.presenceOfElementLocated(uploadSuccessfull));
}
}
On lines 3 and 4 there are the WebDriver
and WebDriverWait
attributes declared as global attributes.
Lines 6 to 9 have the pre-condition that will be executed before all the tests using the @BeforeClass
annotation from TestNG. It’s creating the WebDriver
instance using the ChromeDriver
as a browser.
Lines 11 to 14 have the pre-condition for each test using the @BeforeMethod
annotation from TestNG. It will create the WebDriverWait
instance with 5 seconds of a timeout every time a @Test
runs.
Line 34 shows the timeout override using the withTimeout
method. It will increase the original timeout defined in the pre-condition for each test.
Line 35 uses the method withMessage
to show a message when the test fails. This helps you to easily understand the exception when it throws.
Real Example
You can use the code below to run a real example. Please take into consideration that this is a didactic example, but it shows a real usage.
Before you use it there’s an explanation: the priority attribute on the annotation @Test
was added to execute the tests in the given numeric order (first the number 1, followed by 2 and 3). I do not recommend this approach and I’m using it just to show you an example that I can control.
The test thisTestWillFail
, on lines 41 to 46, will fail because the current timeout is 5 seconds defined in the beforeEachTest
pre-condition method (line 17). But notice that the thisTestWillPassBecauseOfTheTimeoutOverride
, on lines 43 to 52, will pass because we have increased the timeout for this test.
public class ExplicitlyWaitExampleTest {
private WebDriver driver;
private WebDriverWait wait;
@BeforeClass
public void preCondition() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.get("https://codepen.io/eliasnogueira/full/MWywxVr");
driver.switchTo().frame("result");
}
@BeforeMethod
public void beforeEachTest() {
wait = new WebDriverWait(driver, Duration.ofSeconds(5));
}
@Test
public void thisTestWillPass() {
driver.findElement(By.id("trigger_4")).click();
By elementVisibleAfter4Seconds = By.id("after_4");
wait.until(ExpectedConditions.visibilityOfElementLocated(elementVisibleAfter4Seconds));
}
@Test(priority = 2)
public void thisTestWillPassBecauseOfTheTimeoutOverride() {
driver.findElement(By.id("trigger_13")).click();
By elementVisibleAfter13Seconds = By.id("after_13");
// overriding the default timeout only for this wait
wait.
withTimeout(Duration.ofSeconds(15)).
withMessage("timeout while waiting for upload to finish").
until(ExpectedConditions.visibilityOfElementLocated(elementVisibleAfter13Seconds));
}
@Test(priority = 3)
public void thisTestWillFail() {
driver.findElement(By.id("trigger_6")).click();
By elementVisibleAfter6Seconds = By.id("after_6");
wait.until(ExpectedConditions.visibilityOfElementLocated(elementVisibleAfter6Seconds));
}
@AfterClass
public void postCondition() {
driver.quit();
}
}