Run two simple Selenium tests in parallel on CI
Preconditions (4)
✅ Expected Result: Both Selenium tests run simultaneously in the CI environment and pass, confirming parallel execution works.
import pytest from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options @pytest.fixture def driver(): options = Options() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') service = Service() driver = webdriver.Chrome(service=service, options=options) yield driver driver.quit() def test_example_domain_title_1(driver): driver.get('https://example.com') assert driver.title == 'Example Domain' def test_example_domain_title_2(driver): driver.get('https://example.com') assert driver.title == 'Example Domain' # To run in parallel, use the command: # pytest -n 2 test_parallel.py
The driver fixture creates a new Chrome WebDriver instance for each test, ensuring tests do not share browser sessions.
Both test_example_domain_title_1 and test_example_domain_title_2 open https://example.com and assert the page title is exactly 'Example Domain'.
Running pytest -n 2 test_parallel.py uses pytest-xdist to run the two tests in parallel with 2 workers.
This setup is ideal for CI environments where parallel execution speeds up test runs.
Headless Chrome options are used to run browsers without UI, suitable for CI servers.
Now add data-driven testing with 3 different URLs and verify their titles in parallel
from concurrent.futures import ThreadPoolExecutor
import time
def test_func(name):
time.sleep(1)
return f"Test {name} done"
with ThreadPoolExecutor(max_workers=3) as executor:
results = list(executor.map(test_func, ['A', 'B', 'C', 'D']))
print(results)RuntimeError: cannot schedule new futures after shutdown. What is the likely cause?
from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=2) executor.shutdown() executor.submit(test_function)
Pass the test and this pattern moves unknown