In Appium, waiting is an essential concept to handle synchronization issues between the automation script and the web application being tested. The primary purpose of waiting is to ensure that the script does not attempt to interact with elements before they are properly loaded or become available. There are two main types of waiting in Appium: Implicit Wait and Explicit Wait.
An implicit wait instructs the WebDriver to wait for a certain amount of time before throwing an exception. It is set globally for the entire script execution.
In the following example the implicit wait ensures that the WebDriver waits up to 30 seconds for an element to be present before throwing an exception. This wait is applied for every finding element operation throughout the script.
Java
C#
Python
Javascript
Kotlin
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformName("Android");
options.setDeviceName("Pixel_4_Emulator");
options.setAutomationName("UiAutomator2");
options.setApp("/path/to/your/app.apk");
URL appiumServerUrl = new URL("http://localhost:4723");
AndroidDriver driver = new AndroidDriver<>(appiumServerUrl, options);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
//Click on the login button
driver.findElement(By.id("loginButton")).click();
driver.quit();
AppiumOptions options = new AppiumOptions();
options.PlatformName = "Android";
options.DeviceName = "Pixel_4_Emulator";
options.AutomationName = "UiAutomator2";
options.App = "/path/to/your/app.apk";
var serverUri = new Uri("http://localhost:4723");
AndroidDriver driver = new AndroidDriver(serverUri, options);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(90);
//Click on the login button
driver.FindElement(By.Id("loginButton")).Click();
driver.Quit();
options = UiAutomator2Options()
options.platform_name = "Android"
options.platformVersion = '15'
options.device_name = "YourDeviceName"
options.app_activity = ".MainActivity"
options.App = "/path/to/your/app.apk"
driver = webdriver.Remote('http://localhost:4723', options=options)
driver.implicitly_wait(30)
driver.quit()
const { remote } = require('webdriverio');
// Define Desired Capabilities
const capabilities = {
platformName: 'Android',
'appium:automationName': 'UiAutomator2',
'appium:deviceName': 'Pixel 7 API 34',
'appium:platformVersion':'14',
'app' : '/path/to/my.app',
'appium:appActivity': '.MainActivity',
};
// Define Server Configuration
const wdOpts = {
hostname: 'localhost',
port: 4723,
logLevel: 'info',
capabilities,
};
const driver = await remote({capabilities : wdOpts});
await driver.setTimeouts({ implicit: 5000 });
//Click on the login button
await driver.$("#loginButton").click();
// Pause briefly for visibility and close session
await driver.pause(2000);
await driver.deleteSession();
val options = UiAutomator2Options()
options.setPlatformName("Android")
options.setDeviceName("Pixel_4_Emulator") // Replace with the name of your device/emulator
options.setAutomationName("UiAutomator2")
options.setApp("/path/to/your/app.apk") // Path to your APK file
// Initialize the AndroidDriver
val serverUrl = URI.create("http://localhost:4723").toURL()
val driver: RemoteWebDriver = AndroidDriver(serverUrl, options)
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30))
//Click on the login button
driver.findElement(By.id("loginButton")).click()
driver.quit()
An explicit wait is more targeted and allows the script to wait for a specific condition to be met before proceeding. It is applied to a particular element or a certain condition. The explicit wait in the following example is applied only to the specific Element ie element with id welcomelabel. The script waits up to 10 seconds for the element to be visible before throwing an exception.
Java
C#
Python
Javascript
Kotlin
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformName("Android");
options.setDeviceName("Pixel_4_Emulator");
options.setAutomationName("UiAutomator2");
options.setApp("/path/to/your/app.apk");
URL appiumServerUrl = new URL("http://localhost:4723");
AndroidDriver driver = new AndroidDriver(appiumServerUrl, options);
//Click on the login button
driver.findElement(By.id("loginButton")).click();
// Initialize WebDriverWait with a 10-second timeout
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Wait until the element is visible before interacting
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("myElementId")));
element.click();
driver.quit();
AppiumOptions options = new AppiumOptions();
options.PlatformName = "Android";
options.DeviceName = "Pixel_4_Emulator";
options.AutomationName = "UiAutomator2";
options.App = "/path/to/your/app.apk";
var serverUri = new Uri("http://localhost:4723");
AndroidDriver driver = new AndroidDriver(serverUri, options);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(90);
//Click on the login button
driver.FindElement(By.Id("loginButton")).Click();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
// Wait until an element is visible and return it
IWebElement element = wait.Until(d => {
var e = d.FindElement(By.Id("myElementId"));
return e.Displayed ? e : null;
});
element.Click();
driver.Quit();
options = UiAutomator2Options()
options.platform_name = "Android"
options.platformVersion = '15'
options.device_name = "YourDeviceName"
options.app_activity = ".MainActivity"
options.App = "/path/to/your/app.apk"
driver = webdriver.Remote('http://localhost:4723', options=options)
driver.implicitly_wait(30)
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "element_id"))
)
element.click()
driver.quit()
const { remote } = require('webdriverio');
// Define Desired Capabilities
const capabilities = {
platformName: 'Android',
'appium:automationName': 'UiAutomator2',
'appium:deviceName': 'Pixel 7 API 34',
'appium:platformVersion':'14',
'app' : '/path/to/my.app',
'appium:appActivity': '.MainActivity',
};
// Define Server Configuration
const wdOpts = {
hostname: 'localhost',
port: 4723,
logLevel: 'info',
capabilities,
};
async function runTest()
{
const driver = await remote({capabilities : wdOpts});
try
{
// Implicit wait for 3 seconds
await driver.setTimeouts({ implicit: 3000 });
const loginButton = await driver.$('~login_button');
// Example: Waiting for an element to exist and be displayed
await driver.waitUntil(
async () => (await loginButton.isDisplayed()),
{
timeout: 5000,
timeoutMsg: 'Element did not appear within 10 seconds'
}
);
await loginButton.click();
console.log('Clicked login button');
}
finally
{
await driver.deleteSession();
}
}
runTest();
val options = UiAutomator2Options()
options.setPlatformName("Android")
options.setDeviceName("Pixel_4_Emulator") // Replace with the name of your device/emulator
options.setAutomationName("UiAutomator2")
options.setApp("/path/to/your/app.apk") // Path to your APK file
// Initialize the AndroidDriver
val serverUrl = URI.create("http://localhost:4723").toURL()
val driver: RemoteWebDriver = AndroidDriver(serverUrl, options)
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30))
//Click on the login button
driver.findElement(By.id("loginButton")).click()
val wait: Wait<WebDriver> = WebDriverWait(driver, Duration.ofSeconds(10))
val element = wait.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("element")))
element.click();
driver.quit()
Fluent Wait is an advanced type of Explicit Wait in Appium that allows you to customize various parameters that will change how the conditions are evaluated. You can define custom polling intervals and exceptions to wait for a certain condition to be met. It is more flexible than the regular WebDriverWait by providing a mechanism for defining the maximum amount of time to wait for a condition and the frequency with which to check the condition.
Java
C#
Python
Javascript
Kotlin
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformName("Android");
options.setDeviceName("Pixel_4_Emulator");
options.setAutomationName("UiAutomator2");
options.setApp("/path/to/your/app.apk");
URL appiumServerUrl = new URL("http://localhost:4723");
AndroidDriver driver = new AndroidDriver(appiumServerUrl, options);
//Click on the login button
driver.findElement(By.id("loginButton")).click();
// Define the Fluent Wait
FluentWait<AndroidDriver> wait = new FluentWait<>(driver);
wait.withTimeout(Duration.ofSeconds(30)) // Maximum wait time
.pollingEvery(Duration.ofSeconds(5)) // Frequency of checking
.ignoring(NoSuchElementException.class) // Exceptions to ignore
.withMessage("Element not found after 30 seconds"); // Custom error message
// Use the wait for a specific condition
WebElement element = wait.until((Function<AppiumDriver, WebElement>) d -> d.findElement(By.id("element_id")));
driver.quit();
AppiumOptions options = new AppiumOptions();
options.PlatformName = "Android";
options.DeviceName = "Pixel_4_Emulator";
options.AutomationName = "UiAutomator2";
options.App = "/path/to/your/app.apk";
var serverUri = new Uri("http://localhost:4723");
AndroidDriver driver = new AndroidDriver(serverUri, options);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(90);
// Define the Fluent Wait
DefaultWait<AppiumDriver> fluentWait = new DefaultWait<AppiumDriver>(driver)
{
Timeout = TimeSpan.FromSeconds(30),
PollingInterval = TimeSpan.FromMilliseconds(500),
Message = "Element was not found within the timeout period."
};
// Ignore specific exceptions during polling
fluentWait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(StaleElementReferenceException));
// Wait until the condition is met
AppiumElement element = fluentWait.Until(d =>
{
var e = d.FindElement(MobileBy.Id("com.example:id/login_button"));
return e.Displayed ? e : null;
});
element.Click();
driver.Quit();
options = UiAutomator2Options()
options.platform_name = "Android"
options.platformVersion = '15'
options.device_name = "YourDeviceName"
options.app_activity = ".MainActivity"
options.App = "/path/to/your/app.apk"
driver = webdriver.Remote('http://localhost:4723', options=options)
driver.implicitly_wait(30)
# Define the Fluent Wait
wait = WebDriverWait(
driver,
timeout=10,
poll_frequency=1,
ignored_exceptions=[NoSuchElementException, ElementNotVisibleException]
)
# Use it to wait for an element
element = wait.until(EC.presence_of_element_located((By.ID, "com.example:id/login_button")))
element.click()
driver.quit()
const { remote } = require('webdriverio');
// Define Desired Capabilities
const capabilities = {
platformName: 'Android',
'appium:automationName': 'UiAutomator2',
'appium:deviceName': 'Pixel 7 API 34',
'appium:platformVersion':'14',
'app' : '/path/to/my.app',
'appium:appActivity': '.MainActivity',
};
// Define Server Configuration
const wdOpts = {
hostname: 'localhost',
port: 4723,
logLevel: 'info',
capabilities,
};
async function runTest()
{
const driver = await remote({capabilities : wdOpts});
try
{
// Implicit wait for 3 seconds
await driver.setTimeouts({ implicit: 3000 });
const loginButton = await driver.$('~login_button');
// Example: Waiting for an element to exist and be displayed
await driver.waitUntil(
async () => (await loginButton.isDisplayed()),
{
timeout: 5000,
timeoutMsg: 'Element did not appear within 10 seconds',
interval: 500 // Poll every 500ms
}
);
await loginButton.click();
console.log('Clicked login button');
}
finally
{
await driver.deleteSession();
}
}
runTest();
val options = UiAutomator2Options()
options.setPlatformName("Android")
options.setDeviceName("Pixel_4_Emulator") // Replace with the name of your device/emulator
options.setAutomationName("UiAutomator2")
options.setApp("/path/to/your/app.apk") // Path to your APK file
// Initialize the AndroidDriver
val serverUrl = URI.create("http://localhost:4723").toURL()
val driver: RemoteWebDriver = AndroidDriver(serverUrl, options)
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30))
// --- Fluent Wait Setup ---
val wait: FluentWait<RemoteWebDriver> = FluentWait(driver)
.withTimeout(Duration.ofSeconds(50)) // Maximum wait time
.pollingEvery(Duration.ofSeconds(2)) // Frequency to check
.ignoring(NoSuchElementException::class.java) // Ignore specific errors
.ignoring(org.openqa.selenium.TimeoutException::class.java) // Also ignore timeout
// --- Usage ---
val element = wait.until { d ->
d.findElement(By.id("com.example:id/submit_button"))
}
// Alternatively, using ExpectedConditions for better readability
val visibleElement = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("com.example:id/submit_button"))
)
visibleElement.click()
driver.quit()
In the above example, the script waits up to 10 seconds for the element with the ID welcomelabel to be displayed. It checks for the element's presence every 500 milliseconds. The NoSuchElementException is ignored during the polling.