If you need to find out what went wrong during an end-to-end test, a recorded video of the browser with all its interactions can be a time saver. Let’s look at how we can create these videos with a dynamic Selenium Grid.
This post is part of my journey to learn Python. You can find the other parts of this series here. You find the code for this post in my PythonFriday repository on GitHub.
Ask for a video
In our browser definition we need to ask for the capability se:recordVideo to tell our grid that it should create a video:
1 2 3 4 5 6 |
firefox_options = webdriver.FirefoxOptions() firefox_options.set_capability("se:recordVideo","True") driver = webdriver.Remote( command_executor='http://localhost:4444', options=firefox_options ) |
As soon as we get the driver, we should ask for the session_id:
1 |
session_id = driver.session_id |
Inside the assets folder (next to the docker-compose file) you will find a folder named after the session_id that contains the video.
Create a video fixture
We can create a new fixture for pytest to create a video for our Selenium based test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@pytest.fixture() def video_grid(request): firefox_options = webdriver.FirefoxOptions() firefox_options.set_capability("se:recordVideo","True") driver = webdriver.Remote( command_executor='http://localhost:4444', options=firefox_options ) testname = request.node.name session_id = driver.session_id print(f"{testname}->./assets/{session_id}/video.mp4") yield driver #driver.close() -> keeps session open for 5 minutes! driver.quit() |
Attention: If you close the browser with driver.close() the session in Selenium Grid will continue for 5 minutes. Therefore, always use driver.quit()!
Use the video fixture
We can use our video fixture in our tests:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import pytest from selenium_pytest_fixture import video_grid @pytest.mark.usefixtures("video_grid") def test_duckduckgo_video(video_grid): video_grid.get("https://duckduckgo.com/?t=ha&va=j") assert "DuckDuckGo — Privacy, simplified." == video_grid.title @pytest.mark.usefixtures("video_grid") def test_blog_video(video_grid): video_grid.get("https://improveandrepeat.com/") assert "Improve & Repeat" == video_grid.title |
If we run pytest with the -s option, we should see the test name and the session id:
…
collected 2 itemstest_duckduckgo_video->./assets/12d1855f-***/video.mp4
test_blog_video->./assets/a0c34ebd-***/video.mp4
…
(The session id changes with every run)
We now can take that session id and watch the matching video. So far, I have not found a nice test report that already integrates the video into the report. Please post a comment if you know about a solution for that.
Create screenshots
We can take screenshots with the method get_screenshot_as_file() on the driver:
1 |
driver.get_screenshot_as_file(f"./my/path/image.png") |
That works inside a (dynamic) Selenium Grid and when you run the browser directly on your machine.
Parting thoughts
We now have everything in place to use Selenium to automate a web browser. If we want to run a single browser to scrap data from JavaScript-heavy pages (like WordPress) or check that our application keeps working with end-to-end tests, Selenium covers it. Tools like Selenium Grid are a great help, but it takes a lot of time to figure out all the necessary details.
I hope you can skip the errors I made and quickly reach a running solution. Please let me know if you miss something or have ideas to create test reports that include the videos.