Skip to content

Commit 0490870

Browse files
committed
build: Run tests using Grid
1 parent 47f4ef3 commit 0490870

24 files changed

+332
-109
lines changed

.github/workflows/test.yml

+20-18
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,25 @@ jobs:
4444
python -m pip install --upgrade pip
4545
pip install tox
4646
47-
- name: Setup Firefox
48-
if: matrix.os == 'ubuntu-latest'
49-
uses: browser-actions/setup-firefox@latest
50-
with:
51-
firefox-version: latest
52-
53-
- name: Setup Geckodriver
54-
if: matrix.os == 'ubuntu-latest'
55-
uses: browser-actions/setup-geckodriver@latest
56-
57-
- name: Setup Chrome
58-
uses: browser-actions/setup-chrome@latest
59-
with:
60-
chrome-version: stable
61-
62-
- name: Setup Chromedriver
63-
uses: nanasess/setup-chromedriver@master
47+
- name: Spin up Grid
48+
run: ./start
49+
# - name: Setup Firefox
50+
# if: matrix.os == 'ubuntu-latest'
51+
# uses: browser-actions/setup-firefox@latest
52+
# with:
53+
# firefox-version: latest
54+
#
55+
# - name: Setup Geckodriver
56+
# if: matrix.os == 'ubuntu-latest'
57+
# uses: browser-actions/setup-geckodriver@latest
58+
#
59+
# - name: Setup Chrome
60+
# uses: browser-actions/setup-chrome@latest
61+
# with:
62+
# chrome-version: stable
63+
#
64+
# - name: Setup Chromedriver
65+
# uses: nanasess/setup-chromedriver@master
6466

6567
- name: Cache tox environments
6668
uses: actions/cache@v3
@@ -70,7 +72,7 @@ jobs:
7072

7173
- name: Test
7274
if: matrix.os == 'ubuntu-latest'
73-
run: tox -e ${{ matrix.tox_env }}
75+
run: tox -e ${{ matrix.tox_env }} -- --html={envlogdir}/report.html --self-contained-html
7476

7577
- name: Test (skip firefox on windows)
7678
if: matrix.os == 'windows-latest'

docker-compose.arm.yml

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# To execute this docker-compose yml file use `docker-compose -f docker-compose.intel.yml up`
2+
# Add the `-d` flag at the end for detached execution
3+
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`
4+
version: "3"
5+
6+
services:
7+
8+
chromium:
9+
image: seleniarm/node-chromium:latest
10+
container_name: selenium-chromium
11+
shm_size: 2gb
12+
ports:
13+
- "7901:7900"
14+
depends_on:
15+
- selenium-hub
16+
environment:
17+
- SE_EVENT_BUS_HOST=selenium-hub
18+
- SE_EVENT_BUS_PUBLISH_PORT=4442
19+
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
20+
networks:
21+
- grid
22+
23+
firefox:
24+
image: seleniarm/node-firefox:latest
25+
container_name: selenium-firefox
26+
shm_size: 2gb
27+
ports:
28+
- "7903:7900"
29+
depends_on:
30+
- selenium-hub
31+
environment:
32+
- SE_EVENT_BUS_HOST=selenium-hub
33+
- SE_EVENT_BUS_PUBLISH_PORT=4442
34+
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
35+
networks:
36+
- grid
37+
38+
selenium-hub:
39+
image: seleniarm/hub:latest
40+
container_name: selenium-hub
41+
ports:
42+
- "4442:4442"
43+
- "4443:4443"
44+
- "4444:4444"
45+
networks:
46+
- grid
47+
48+
webserver:
49+
container_name: webserver
50+
build:
51+
context: docker/
52+
environment:
53+
- PYTHONDONTWRITEBYTECODE=1
54+
networks:
55+
- grid
56+
depends_on:
57+
- firefox
58+
- chromium
59+
60+
networks:
61+
grid:

docker-compose.intel.yml

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# To execute this docker-compose yml file use `docker-compose -f docker-compose.intel.yml up`
2+
# Add the `-d` flag at the end for detached execution
3+
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`
4+
version: "3"
5+
6+
services:
7+
8+
chrome:
9+
image: selenium/node-chrome:latest
10+
container_name: selenium-chrome
11+
shm_size: 2gb
12+
ports:
13+
- "5901:5900"
14+
depends_on:
15+
- selenium-hub
16+
environment:
17+
- SE_EVENT_BUS_HOST=selenium-hub
18+
- SE_EVENT_BUS_PUBLISH_PORT=4442
19+
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
20+
networks:
21+
- grid
22+
23+
edge:
24+
image: selenium/node-edge:latest
25+
container_name: selenium-edge
26+
shm_size: 2gb
27+
ports:
28+
- "5902:5900"
29+
depends_on:
30+
- selenium-hub
31+
environment:
32+
- SE_EVENT_BUS_HOST=selenium-hub
33+
- SE_EVENT_BUS_PUBLISH_PORT=4442
34+
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
35+
networks:
36+
- grid
37+
38+
firefox:
39+
image: selenium/node-firefox:latest
40+
container_name: selenium-firefox
41+
shm_size: 2gb
42+
ports:
43+
- "5903:5900"
44+
depends_on:
45+
- selenium-hub
46+
environment:
47+
- SE_EVENT_BUS_HOST=selenium-hub
48+
- SE_EVENT_BUS_PUBLISH_PORT=4442
49+
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
50+
networks:
51+
- grid
52+
53+
selenium-hub:
54+
image: selenium/hub:latest
55+
container_name: selenium-hub
56+
ports:
57+
- "4442:4442"
58+
- "4443:4443"
59+
- "4444:4444"
60+
networks:
61+
- grid
62+
63+
webserver:
64+
container_name: webserver
65+
build:
66+
context: docker/
67+
environment:
68+
- PYTHONDONTWRITEBYTECODE=1
69+
networks:
70+
- grid
71+
depends_on:
72+
- firefox
73+
- chrome
74+
- edge
75+
76+
networks:
77+
grid:

docker/Dockerfile

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM python:3.10-slim-buster
2+
3+
WORKDIR /usr/src/app
4+
5+
ENV FLASK_APP=webserver.py
6+
ENV FLASK_RUN_HOST=0.0.0.0
7+
ENV FLASK_RUN_PORT=80
8+
9+
RUN python -m pip install --upgrade pip && \
10+
pip install flask
11+
12+
COPY webserver.py .
13+
14+
CMD ["flask", "run"]

docker/webserver.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from flask import Flask
2+
3+
app = Flask(__name__)
4+
5+
6+
@app.route("/")
7+
def home():
8+
return """<h1>Success!</h1><a href="#">Link</a><p>Ё</p>"""

pyproject.toml

-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ black = ">=22.1.0"
6161
flake8 = ">=4.0.1"
6262
tox = ">=3.24.5"
6363
pre-commit = ">=2.17.0"
64-
pytest-localserver = ">=0.5.0"
6564
pytest-xdist = ">=2.4.0"
6665
pytest-mock = ">=3.6.1"
6766

src/pytest_selenium/drivers/browserstack.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def job_access(self):
4848
return field
4949

5050

51-
@pytest.mark.optionalhook
51+
@pytest.hookimpl(optionalhook=True)
5252
def pytest_selenium_runtest_makereport(item, report, summary, extra):
5353
provider = BrowserStack()
5454
if not provider.uses_driver(item.config.getoption("driver")):

src/pytest_selenium/drivers/crossbrowsertesting.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def key(self):
3333
)
3434

3535

36-
@pytest.mark.optionalhook
36+
@pytest.hookimpl(optionalhook=True)
3737
def pytest_selenium_capture_debug(item, report, extra):
3838
provider = CrossBrowserTesting()
3939
if not provider.uses_driver(item.config.getoption("driver")):
@@ -57,7 +57,7 @@ def pytest_selenium_capture_debug(item, report, extra):
5757
extra.append(pytest_html.extras.html(_video_html(videos[0])))
5858

5959

60-
@pytest.mark.optionalhook
60+
@pytest.hookimpl(optionalhook=True)
6161
def pytest_selenium_runtest_makereport(item, report, summary, extra):
6262
provider = CrossBrowserTesting()
6363
if not provider.uses_driver(item.config.getoption("driver")):

src/pytest_selenium/drivers/remote.py

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import os
66

7+
# from selenium.webdriver.chrome.options import Options
8+
79
HOST = os.environ.get("SELENIUM_HOST", "localhost")
810
PORT = os.environ.get("SELENIUM_PORT", 4444)
911

@@ -12,8 +14,13 @@ def driver_kwargs(capabilities, host, port, **kwargs):
1214
host = host if host.startswith("http") else f"http://{host}"
1315
executor = f"{host}:{port}/wd/hub"
1416

17+
# options = Options()
18+
# options.add_argument("--log-path=foo.log")
19+
# print(options.to_capabilities())
20+
1521
kwargs = {
1622
"command_executor": executor,
1723
"desired_capabilities": capabilities,
24+
# "options": options,
1825
}
1926
return kwargs

src/pytest_selenium/drivers/saucelabs.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def uses_driver(self, driver):
5252
return driver.lower() == self.name.lower()
5353

5454

55-
@pytest.mark.optionalhook
55+
@pytest.hookimpl(optionalhook=True)
5656
def pytest_selenium_capture_debug(item, report, extra):
5757
provider = SauceLabs(item.config.getini("saucelabs_data_center"))
5858
if not provider.uses_driver(item.config.getoption("driver")):
@@ -62,7 +62,7 @@ def pytest_selenium_capture_debug(item, report, extra):
6262
extra.append(pytest_html.extras.html(_video_html(item._driver.session_id)))
6363

6464

65-
@pytest.mark.optionalhook
65+
@pytest.hookimpl(optionalhook=True)
6666
def pytest_selenium_runtest_makereport(item, report, summary, extra):
6767
provider = SauceLabs(item.config.getini("saucelabs_data_center"))
6868
if not provider.uses_driver(item.config.getoption("driver")):

src/pytest_selenium/drivers/testingbot.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def secret(self):
4242
return self.get_credential("secret", ["TESTINGBOT_SECRET", "TESTINGBOT_PSW"])
4343

4444

45-
@pytest.mark.optionalhook
45+
@pytest.hookimpl(optionalhook=True)
4646
def pytest_selenium_capture_debug(item, report, extra):
4747
provider = TestingBot()
4848
if not provider.uses_driver(item.config.getoption("driver")):
@@ -56,7 +56,7 @@ def pytest_selenium_capture_debug(item, report, extra):
5656
extra.append(pytest_html.extras.html(_video_html(auth_url, session_id)))
5757

5858

59-
@pytest.mark.optionalhook
59+
@pytest.hookimpl(optionalhook=True)
6060
def pytest_selenium_runtest_makereport(item, report, summary, extra):
6161
provider = TestingBot()
6262
if not provider.uses_driver(item.config.getoption("driver")):

src/pytest_selenium/pytest_selenium.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ def pytest_report_header(config, startdir):
253253
return "driver: {0}".format(driver)
254254

255255

256-
@pytest.mark.hookwrapper
256+
@pytest.hookimpl(hookwrapper=True)
257257
def pytest_runtest_makereport(item, call):
258258
outcome = yield
259259
report = outcome.get_result()

start

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
if [[ $(uname -m) == "arm64" ]]; then
6+
arch="arm"
7+
else
8+
arch="intel"
9+
fi
10+
11+
docker-compose -f "docker-compose.${arch}.yml" up -d

stop

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
if [[ $(uname -m) == "arm64" ]]; then
6+
arch="arm"
7+
else
8+
arch="intel"
9+
fi
10+
11+
docker-compose -f "docker-compose.${arch}.yml" down

testing/conftest.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
pytest_plugins = "pytester"
1010

1111

12-
def base_url(httpserver):
13-
return httpserver.url
12+
def base_url():
13+
return "http://webserver"
1414

1515

1616
@pytest.fixture
17-
def httpserver_base_url(httpserver):
18-
return "--base-url={0}".format(base_url(httpserver))
17+
def httpserver_base_url():
18+
return "--base-url={0}".format(base_url())
1919

2020

2121
@pytest.fixture(autouse=True)
@@ -59,21 +59,36 @@ def chrome_options(chrome_options):
5959

6060
def runpytestqa(*args, **kwargs):
6161
return testdir.runpytest(
62-
httpserver_base_url, "--driver", "Firefox", *args, **kwargs
62+
httpserver_base_url,
63+
"--driver",
64+
"remote",
65+
"--capability",
66+
"browserName",
67+
"firefox",
68+
*args,
69+
**kwargs,
6370
)
6471

6572
testdir.runpytestqa = runpytestqa
6673

6774
def inline_runqa(*args, **kwargs):
6875
return testdir.inline_run(
69-
httpserver_base_url, "--driver", "Firefox", *args, **kwargs
76+
httpserver_base_url,
77+
"--driver",
78+
"remote",
79+
"--capability",
80+
"browserName",
81+
"firefox",
82+
*args,
83+
**kwargs,
7084
)
7185

7286
testdir.inline_runqa = inline_runqa
7387

7488
def quick_qa(*args, **kwargs):
7589
reprec = inline_runqa(*args)
7690
outcomes = reprec.listoutcomes()
91+
print(f"outcomes: {outcomes}")
7792
names = ("passed", "skipped", "failed")
7893
for name, val in zip(names, outcomes):
7994
wantlen = kwargs.get(name)

0 commit comments

Comments
 (0)