Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f071c5c

Browse files
committedDec 10, 2023
feat: settings to use remote webdrivers on containers
1 parent 478b210 commit f071c5c

File tree

5 files changed

+161
-8
lines changed

5 files changed

+161
-8
lines changed
 

‎Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
# shell colors
3+
COLOUR_GREEN=\033[0;32m
4+
COLOUR_RED=\033[0;31m
5+
COLOUR_BLUE=\033[0;34m
6+
COLOUR_END=\033[0m
7+
8+
se-docker-up: #starts the docker containers set by containers/compose.yaml file:
9+
@echo "$(COLOUR_GREEN)UP Docker containers set by compose file ...$(COLOUR_END)"
10+
docker compose -f containers/compose.yaml up -d
11+
12+
se-docker-down: #terminates the docker containers set by containers/compose.yaml file:
13+
@echo "$(COLOUR_RED)DOWN Docker containers set by compose file ...$(COLOUR_END)"
14+
docker compose -f containers/compose.yaml down
15+
16+
se-docker-run-tests: #Running tests for Firefox, Chrome and Edge browsers from docker containers
17+
@echo "$(COLOUR_BLUE)Running tests for Firefox, Chrome and Edge browsers from docker containers ...$(COLOUR_END)"
18+
docker compose -f containers/compose.yaml exec python sh -c "SELENIUM_HOST=chrome pytest -vx --use-browser remote & SELENIUM_HOST=firefox pytest -vx --use-browser remote & SELENIUM_HOST=edge pytest -vx --use-browser remote"
19+
20+
se-docker-run-tests-firefox: #Running tests for Firefox browser from docker containers
21+
@echo "$(COLOUR_BLUE)Running tests for Firefox browser from docker containers ...$(COLOUR_END)"
22+
docker compose -f containers/compose.yaml exec python sh -c "SELENIUM_HOST=firefox pytest -vx --use-browser remote"
23+
24+
se-docker-run-tests-chrome: #Running tests for Chrome browser from docker containers
25+
@echo "$(COLOUR_BLUE)Running tests for Chrome browser from docker containers ...$(COLOUR_END)"
26+
docker compose -f containers/compose.yaml exec python sh -c "SELENIUM_HOST=chrome pytest -vx --use-browser remote "
27+
28+
se-docker-run-tests-edge: #Running tests for Edge browser from docker containers
29+
@echo "$(COLOUR_BLUE)Running tests for Edge browser from docker containers ...$(COLOUR_END)"
30+
docker compose -f containers/compose.yaml exec python sh -c "SELENIUM_HOST=edge pytest -vx --use-browser remote"
31+
32+
33+
#: #########################################
34+
#: ############ Help - Makefile ############
35+
#: #########################################
36+
37+
help: # list all Makefile commands
38+
@echo "$(COLOUR_BLUE)These are all the avalaible commands ...$(COLOUR_END)"
39+
@echo ""
40+
@grep ': #' Makefile

‎README.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Automated tests using Python flavor of the Selenium framework.
1010
- [Expected output of test run](#expected-output-of-test-run)
1111
- [Selecting a specific browser](#selecting-a-specific-browser)
1212
- [Set a default browser to run a specific test](#set-a-default-browser-to-run-a-specific-test)
13+
- [Using `pytest` parametrize option to repeat test on different browsers](#using-pytest-parametrize-option-to-repeat-test-on-different-browsers)
14+
- [Using containers to run tests](#using-containers-to-run-tests)
1315

1416

1517
# How to install
@@ -87,4 +89,40 @@ def test_successfully_run_with_firefox(...):
8789
...
8890
```
8991

90-
The test above will be run using the Firefox browser and this mark takes precedence over the CLI argument `--use-browser`, if it is passed.
92+
The test above will be run using the Firefox browser and this mark takes precedence over the CLI argument `--use-browser`, if it is passed.
93+
94+
## Using `pytest` parametrize option to repeat test on different browsers
95+
96+
It's useful to use the powers of `pytest` framework to handle situations where the specific test case should be run against a variety of different browsers. A way to make it works it's by using `pytest.mark.parametrize` fixture, as the example below:
97+
98+
```python
99+
@pytest.mark.parametrize(
100+
(""), [
101+
pytest.param(id="default"),
102+
pytest.param(id="firefox", marks=pytest.mark.FORCE_BROWSER("edge")),
103+
pytest.param(id="firefox", marks=pytest.mark.FORCE_BROWSER("chrome"))
104+
]
105+
)
106+
def test_successfully_run_with_edge_chrome_and_default_config(...):
107+
...
108+
```
109+
The way the example above works is by only applying:
110+
- an _ID_: to be displayed on the pytest output;
111+
- the custom `FORCE_BROWSER` mark: to force the use of the specified browser.
112+
113+
## Using containers to run tests
114+
115+
To rapidly set a development environment, using Docker to run containers is a valid alternative. Documentation for `docker-selenium` is set on the [project official repository](https://github.com/SeleniumHQ/docker-selenium) and it might be a good idea to take some time to read it.
116+
117+
The first steps are condensed on this [Makefile](Makefile), and you could start with the `make help` command to see the basics to: put containers UP or DOWN with Docker, then execute the tests on this infrastructure. All containers configuration are disposed on [compose.yaml](containers/compose.yaml)
118+
119+
```sh
120+
make help
121+
# > These are all the avalaible commands ...
122+
123+
make se-docker-up # starts the docker containers set by containers/compose.yaml file
124+
125+
make se-docker-run-tests #Running tests for Firefox, Chrome and Edge browsers from docker containers
126+
127+
make se-docker-down # terminates the docker containers set by containers/compose.yaml file
128+
```

‎conftest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ def use_browser_option(request):
2626
"""Fixture to handle the use of argument --use-browser to select"""
2727

2828
force_browser = request.node.get_closest_marker("FORCE_BROWSER")
29+
selected_browser = request.config.getoption("--use-browser")
30+
2931
if force_browser is None:
30-
selected_browser = request.config.getoption("--use-browser")
3132
return selected_browser
33+
34+
elif selected_browser.lower() == "remote":
35+
pytest.skip(reason="Test to be run on specific browser locally")
3236

3337
return force_browser.args[0]
3438

‎containers/compose.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
version: '3'
2+
3+
services:
4+
5+
firefox:
6+
image: selenium/standalone-firefox:4.15.0-20231129
7+
shm_size: '2gb'
8+
ports:
9+
- 4444:4444 # Selenium service
10+
- 5900:5900 # VNC server
11+
- 7900:7900 # VNC browser client
12+
environment:
13+
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
14+
- SE_NODE_MAX_SESSIONS=15
15+
- SE_NODE_SESSION_TIMEOUT=30
16+
17+
chrome:
18+
image: selenium/standalone-chrome:4.15.0-20231129
19+
shm_size: '2gb'
20+
ports:
21+
- 4441:4444 # Selenium service
22+
- 5901:5900 # VNC server
23+
- 7901:7900 # VNC browser client
24+
environment:
25+
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
26+
- SE_NODE_MAX_SESSIONS=15
27+
- SE_NODE_SESSION_TIMEOUT=30
28+
29+
edge:
30+
image: selenium/standalone-edge:4.15.0-20231129
31+
shm_size: '2gb'
32+
ports:
33+
- 4442:4444 # Selenium service
34+
- 5902:5900 # VNC server
35+
- 7902:7900 # VNC browser client
36+
environment:
37+
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
38+
- SE_NODE_MAX_SESSIONS=15
39+
- SE_NODE_SESSION_TIMEOUT=30
40+
41+
python:
42+
image: python:3.11.7-alpine3.18
43+
volumes:
44+
- ./../:/test
45+
working_dir: /test
46+
command: sh -c "pip install -r requirements-lock.txt && sh"
47+
tty: true

‎tests/pages/BasePageObject.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
import os
2+
13
from selenium import webdriver
2-
from selenium.webdriver.firefox.options import Options
4+
from selenium.webdriver.firefox.options import Options as FirefoxOptions
5+
from selenium.webdriver.chrome.options import Options as ChromeOptions
6+
from selenium.webdriver.edge.options import Options as EdgeOptions
7+
from selenium.webdriver.safari.options import Options as SafariOptions
38

49

510
class BasePageObject:
@@ -16,25 +21,44 @@ def __init__(self, driver = None):
1621

1722
match driver:
1823
case None:
19-
new_driver_options = Options()
24+
new_driver_options = FirefoxOptions()
2025
new_driver_options.add_argument("-headless")
2126
self.driver = webdriver.Firefox(new_driver_options)
27+
case "remote":
28+
hostname = os.environ.get("SELENIUM_HOST", "selenium")
29+
30+
match hostname.lower():
31+
case "chrome":
32+
new_driver_options = ChromeOptions()
33+
case "firefox":
34+
new_driver_options = FirefoxOptions()
35+
case "edge":
36+
new_driver_options = EdgeOptions()
37+
case _:
38+
new_driver_options = FirefoxOptions()
39+
40+
self.driver = webdriver.Remote(
41+
command_executor="http://{}:4444".format(hostname),
42+
options=new_driver_options,
43+
keep_alive=True,
44+
)
45+
2246
case "firefox":
2347
self.driver = webdriver.Firefox()
2448
case "headless-firefox":
25-
new_driver_options = Options()
49+
new_driver_options = FirefoxOptions()
2650
new_driver_options.add_argument("-headless")
2751
self.driver = webdriver.Firefox(new_driver_options)
2852
case "chrome":
2953
self.driver = webdriver.Chrome()
3054
case "headless-chrome":
31-
new_driver_options = Options()
55+
new_driver_options = ChromeOptions()
3256
new_driver_options.add_argument("-headless")
3357
self.driver = webdriver.Chrome(new_driver_options)
3458
case "safari":
3559
self.driver = webdriver.Safari()
36-
case "headless-firefox":
37-
new_driver_options = Options()
60+
case "headless-safari":
61+
new_driver_options = SafariOptions()
3862
new_driver_options.add_argument("-headless")
3963
self.driver = webdriver.Firefox(new_driver_options)
4064
case _:

0 commit comments

Comments
 (0)
Please sign in to comment.