When I run the
pytests for my website, they run against
whatever hugo server I have running. While writing a post, this is usually the
same machine I’m writing from. When I commit changes, the CI pipeline
automatically runs the tests on my gitlab CI
runner node. The IP address of the server
to test is determined by a BASE_URL
constant variable defined in my
constants.py
file.
Changing the variable in this file, and not accidentally pushing it in git
is
super annoying. So, I finally sat down one night and moved this variable out of
the constants file, converting it to an optional pytest argument.
Steps
While this might not the best approach, it was easy enough to implement in a very short period of time, and seems to be working great so far. Here are the steps I took to convert my tests from using a constant variable to the optional argument.
- Add
pytest_addoption()
function to the conftest.py file
def pytest_addoption(parser):
parser.addoption(
"--base-url", action="store", default="http://ci-runner.website.net"
)
First, I added a pytest_addoption()
function definition to my conftest.py
file. This function allows me to add command line options to pytest. I added a single
option for now, --base-url
, with it’s action set to "store"
. Additionally,
I set the default value to the address of my CI runner node. This way, if I don’t
provide a value it defaults to using my CI runner.
- Add
base_url
fixture to theconftest.py
file
@pytest.fixture()
def base_url(request):
return request.config.getoption("--base-url")
Next, I added a new fixture (base_url
) to replace my old constant variable
(BASE_URL
) with. This fixture simply returns the value of the --base-url
option just added.
- Update other fixtures to reference the
base_url
fixture
## Example Before
@pytest.fixture(params=POST_NAMES)
def post_url(request):
"""Returns the post urls for testing."""
return BASE_URL + "/post/" + request.param.lower()
## Example After
@pytest.fixture(params=POST_NAMES)
def post_url(request, base_url):
"""Returns the post urls for testing."""
return base_url + "/post/" + request.param.lower()
Next, I had to update any other fixtures in the conftest.py
file to use the
base_url
fixture, instead of the old constant variable. I just added
base_url
to the parameter list, and replaced the variable name in the fixture
definitions.
- Update test functions to use
base_url
fixture
## Example Before
@flaky
def test_md_links(post_md_link):
"""Checks that the markdown links are not broken."""
if post_md_link in SKIP_LINKS:
pytest.skip(f"{post_md_link} in skip list")
elif post_md_link.startswith("http") or post_md_link.startswith("https"):
url = post_md_link
else:
url = BASE_URL + post_md_link.lower()
response = requests.get(url)
assert response.status_code != 404, f"The link {post_md_link} is not found."
assert response.status_code != 403, f"The link {post_md_link} is forbidden."
## Example After
@flaky
def test_md_links(base_url, post_md_link):
"""Checks that the markdown links are not broken."""
if post_md_link in SKIP_LINKS:
pytest.skip(f"{post_md_link} in skip list")
elif post_md_link.startswith("http") or post_md_link.startswith("https"):
url = post_md_link
else:
url = base_url + post_md_link.lower()
response = requests.get(url)
assert response.status_code != 404, f"The link {post_md_link} is not found."
assert response.status_code != 403, f"The link {post_md_link} is forbidden."
Just like the fixtures, I had to update the test functions to use
the base_url
fixture, instead of the BASE_URL
constant. Again, this was
done by adding the fixture name as a parameter to the test function, and swapping
out the references in the code.
- Remove
BASE_URL
fromconstants.py
, and imports of it in other files.
Lastly, I did some cleanup and removed the BASE_URL
definition from the
constants.py
file, along with any import
s of that variable in the other
files.
Results
With those changes, what are the results? Well, I can still run my test execution command the same as before, and it will default to running the tests against my CI server:
pipenv run pytest --workers 10 -v .
However, if I want to point the tests at a hugo server different from the
default, I can now define it with the --base-url
flag:
pipenv run pytest --workers 10 -v --base-url "http://10.0.9.104:1313" .
Conclusion
The best part of this change is that I don’t have to worry about forgetting to switch that config back and forth when pushing to my repo. I simply set the variable when running the tests. Done. I should have made this change years ago.
Using gTile Custom Resolutions in Gnome Wayland