I have a series of pytest fixtures which are very similar to each other in nature. The fixtures are passed to tests which verify that certain CSS selectors work properly. The code within each fixture is nearly the same; this only difference is that a different URL is passed to the page.goto() function for each fixture.
Each fixture looks something like this:
import pytest
@pytest.fixture(scope="module")
def goto_pagename():
with sync_playwright() as play:
browser = play.chromium.launch()
page = browser.new_page()
page.goto(TestScrapeWebsite.address)
yield page
browser.close()
I tried to use a decorator which covers all of the code except page.goto() and yield page, which is below:
from playwright.sync_api import sync_playwright
def get_page(func):
def wrapper(*args, **kwargs):
with sync_playwright() as play:
browser = play.chromium.launch(*args, **kwargs)
page = browser.new_page()
func(page)
browser.close()
return wrapper
Then, the fixtures and tests would look something like this:
import pytest
@pytest.fixture(scope="module")
@get_page
def google_page(page):
page.goto(TestScrapeGoogle.address)
yield page
@pytest.fixture(scope="module")
@get_page
def stackoverflow_page(page):
page.goto(TestScrapeStackOverflow.address)
yield page
@pytest.fixture(scope="module")
@get_page
def github_page(page):
page.goto(TestScrapeGitHub.address)
yield page
class TestScrapeGoogle:
address = "https://google.com/"
def test_selectors(self, google_page):
assert google_page.url == self.address
class TestScrapeStackOverflow:
address = "https://stackoverflow.com/"
def test_selectors(self, stackoverflow_page):
assert stackoverflow_page.url == self.address
class TestScrapeGitHub:
address = "https://github.com/"
def test_selectors(self, github_page):
assert github_page.url == self.address
However, when running the pytest test runner, exceptions were raised concerning the fixtures:
$ pytest test_script.py
...
============================================================================================ short test summary info =============================================================================================
FAILED test_script.py::TestScrapeGoogle::test_selectors - AttributeError: 'NoneType' object has no attribute 'url'
FAILED test_script.py::TestScrapeStackOverflow::test_selectors - AttributeError: 'NoneType' object has no attribute 'url'
FAILED test_script.py::TestScrapeGitHub::test_selectors - AttributeError: 'NoneType' object has no attribute 'url'
Is there a way to modify the approach which I have taken in order to simplify each of the fixtures? Or, is what I am asking out of the capabilities of pytest, and do I just have to fully write out each fixture?
Similar Questions:
Below I added a few Stack Overflow questions which appear when the title of my question is searched. I also included a reason why the answers to for the question would not be an ideal solution for my issue.
- Multiple copies of a pytest fixture: All the copies of the
pytestfixture are for the same tests. In my case, I'm expecting to have a separate fixture for each test. - Run a test with two different pytest fixtures: While there are multiple fixtures, each test will (likely) only have one fixture decorating the test.