Appearance
Selenium
A tried and true tool for creating end-to-end (e2e) tests.
Useful for automated testing and data retrieval.
Installation
Get the WebDriver installed for the browser(s) you want to test with.
IMPORTANT: If using the snap based version of chromium on linux, the chromedriver is included there. It's important to use that version, otherwise the chromedriver will have trouble accessing the isolated instance of the browser.
In snap, the chrome driver is available /snap/bin/chromium.chromedriver
https://stackoverflow.com/a/61980562
Some of the steps I found necessary to get this working
vi ~/.profile
PATH="/snap/bin:$PATH"
source ~/.profile
vi ~/.profile
PATH="/snap/bin:$PATH"
source ~/.profile
Chrome Driver
If not using the snap version of Chrome, you may need to download the chrome driver separately
https://chromedriver.chromium.org/getting-started
Check your version of Chrome (Menu -> About Chromium). Download the right version of the driver.
https://chromedriver.chromium.org/downloads
Extract the driver
Help WebDriver find the downloaded ChromeDriver executable Any of these steps should do the trick:
include the ChromeDriver location in your PATH environment variable
env
mv ~/Downloads/chromedriver /usr/local/bin/
sudo chown account: /usr/local/bin/chromedriver
env
mv ~/Downloads/chromedriver /usr/local/bin/
sudo chown account: /usr/local/bin/chromedriver
Language Bindings
The selenium-webdriver has bindings for many languages.
Python
pip install selenium
pip install selenium
via
https://selenium-python.readthedocs.io/installation.html#installing-python-bindings-for-selenium
- Installation — Selenium Python Bindings 2 documentation
https://selenium-python.readthedocs.io/
Selenium with Python — Selenium Python Bindings 2 documentation
Try out the getting started script:
python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element(By.NAME, "q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element(By.NAME, "q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()
https://selenium-python.readthedocs.io/getting-started.html
2. Getting Started — Selenium Python Bindings 2 documentation
Then run it
python get_data.py
python get_data.py
If all goes well, a browser should pop up, go to the python.org
site, and then close.
If you want to interact with the browser before it closes, comment out driver.close()
in the script and then run python interactively
python -i get_data.py
python -i get_data.py
This is a good point to update the script to go to any login page so you can do that step manually. Automating logins is often difficult and opens up the risk of exposing credentials.
From here create a helpers.py
script that you can import and subsequently reload your module without needing to restart your active browser context (and consequently, re-login).
Note: this approach is more useful for data retrieval than it is for testing. Tests should not have side effects
For python3, the import module functionality has moved
import importlib
importlib.reload(module)
import importlib
importlib.reload(module)
An example starter helper.py
could look something like:
from selenium.webdriver.common.by import By
def get_list(driver):
driver.get("https://python.org")
from selenium.webdriver.common.by import By
def get_list(driver):
driver.get("https://python.org")
Locating content
The By
wrapper helps
from selenium.webdriver.common.by import By
from selenium.webdriver.common.by import By
Use the browser markup inspector to find the right way to select the element.
https://selenium-python.readthedocs.io/locating-elements.html
From here, refine the child elements that you want, or work with the related markup directly
element.get_attribute('innerHTML')
element.get_attribute('innerHTML')
Node Javascript
https://www.npmjs.com/package/selenium-webdriver
cd ~/projects
mkdir selenium-shared
cd selenium-shared
yarn init
yarn add --dev selenium-webdriver
cd ~/projects
mkdir selenium-shared
cd selenium-shared
yarn init
yarn add --dev selenium-webdriver
Now the tests can live locally or in your project directory.
Create a test script (e.g. init.js
) and add the following to try it out
const {Builder, By, Key, until} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('chrome').build();
try {
await driver.get('http://www.google.com/ncr');
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
} finally {
await driver.quit();
}
})();
const {Builder, By, Key, until} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('chrome').build();
try {
await driver.get('http://www.google.com/ncr');
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
} finally {
await driver.quit();
}
})();
then run with
node init.js
node init.js
Local Testing
Some settings may be necessary to handle "Connection Is Not Private"
UI Testing
One benefit over Cypress is that Selenium works when testing remote services. One downside when compared with Cypress is that Selenium does not offer tight integration with the node application.
It may be possible to get some of the nice testing integration by using Selenium with Mocha and Chai.
https://nehalist.io/selenium-tests-with-mocha-and-chai-in-javascript/