Managing Chromedriver for Android Chrome and Webview Testing
Appium supports automation of all kinds of Android apps---not just native apps. You can use Appium to automate websites using the Chrome browser on Android, and also to automate webview-based portions of hybrid apps. On iOS Appium has to implement a bunch of custom logic to attach to Safari or hybrid apps, but on Android, our life is made much easier by the existence of Chromedriver. Chromedriver is an implementation of the WebDriver protocol by Google, which can control Chrome browsers on both desktop and Android platforms.
How Chromedriver works
When you request a context switch into a webview, or when you start an Appium session using the
browserName capability set to
Chrome, Appium starts up Chromedriver for you automatically as a subprocess. Any standard commands your test client sends to Appium while Chromedriver is active get passed directly onto Chromedriver at that point, so that Chromedriver is effectively the component which is driving the automation of the website within the browser or webview.
All of this works transparently to you as the Appium user because both Appium and Chromedriver expose the W3C WebDriver protocol! This fact even allows Appium to do clever things like decide not to pass certain commands to Chromedriver and instead execute its own implementation of them. This is why you can still run certain
mobile: commands while in a webview or browser context, for example. From the Appium developers' perspective, Chromedriver is also nice because it makes our job a lot simpler; rather than figure out how to implement fundamental automation of Chrome ourselves, we can rely on the tool that Google has provided (and Google is the producer of Chrome, so they are in the best position to make the most robust and stable tool!).
There is one downside of relying on Chromedriver, however, which is that new versions of Chromedriver are not compatible with older versions of Chrome. Starting with version 73, Chromedriver updated its versioning scheme to match the version of Chrome. Nowadays, what you want to ensure is that if you have version
XX of Chrome on your device, you are using version
XX of Chromedriver with Appium. But Appium releases contain only one version of Chromedriver--typically the latest version of Chromedriver which is out in the wild at the time of an Appium release. (So Appium 1.15.1, for example, comes bundled with Chromedriver
76.0.3809.126). This is because we don't want Appium users to have to download their own version of Chromedriver and manage it separately--that'd be too many moving parts!
But what if you've upgraded to Appium 1.15.1, but the version of Chrome on your device is only at 75? Well, then you'll abruptly encounter an error that looks like this:
An unknown server-side error occurred while processing the command. Original error: unknown error: Chrome version must be >= 76
Uh oh! How do you resolve this error? There are a few different strategies.
Strategy 1: Update Chrome
The first strategy is pretty obvious. Don't you want Chrome to be at the latest version, too? If so, just update Chrome (you can usually find x86-based APKs for emulators with a bit of judicious Googling), and you'll be good to go. But if you want to make sure you're at an older version of Chrome, or if you can't update, or are automating a webview targeting a different version of Chrome, then read on...
Strategy 2: Tell Appium to use a different Chrome
Appium downloads and installs the version of Chrome which it was published with, if you don't tell it otherwise. But you can tell it otherwise! There is a command-line flag you can pass to the Appium install process that allows you to install any version of Chrome you like:
npm install appium --chromedriver_version="75.0.3770.140"
When you run this command, you'll see Appium downloading the version you specified instead of the default. Of course, this version must exist at the Chromedriver downloads site in the expected location!
Strategy 3: Use your own Chromedriver(s)
If you are responsible for automating different devices with different versions of Chrome, you might want the Appium server not to use just one version of Chromedriver, but to use a number of versions, based on the automation scenario. If you're in this situation, you can maintain your own local repository of Chromedriver executables, and pass the path to one of them in when you start the Appium server:
appium --chromedriver-executable /path/to/my/chromedriver
Strategy 4: Let Appium download new Chromedrivers on the fly
By far the easiest of all the strategies is to just let Appium decide what version of Chromedriver works with your browser or webview, and download it when necessary for you. To make this work, you need to use a couple desired capabilities:
chromedriverExecutableDir: the path to a writable directory on the Appium server's host, where new Chromedriver binaries can be downloaded and executed from
chromedriverChromeMappingFile: the path to a JSON file on the Appium server's host, where a mapping will be stored of Chromedriver versions to Chrome support.
Now, because Appium is downloading executables to the machine from the Internet, there's a potential security risk here (even though Appium does verify the Google-provided checksum of the downloaded files). What this means is to use this feature, you need to enable it as an "insecure" feature when you start the Appium server:
appium --allow-insecure chromedriver_autodownload
(If you have other insecure features to allow, like
execute_driver_script, you can simply separate them with the
When you put all of this together, Appium will automatically download a Chromedriver to work with your webview or browser, and keep it in the directory specified, so that future requests for automating the same version of Chrome don't trigger a new download. So if you wind up in a case where you can't or don't want to upgrade Chrome, or are dealing with a potentially large number of devices with varying versions of Chrome on them, this strategy might be the key to some momentary sanity.