Skip to content

Commit d328246

Browse files
rnestlerElSnoMan
andauthored
Use pathlib instead of string formatting (#249)
Co-authored-by: Carlos Kidman <ckcarlosdesign@gmail.com>
1 parent c9e3972 commit d328246

File tree

3 files changed

+32
-51
lines changed

3 files changed

+32
-51
lines changed

conftest.py

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ def test_go_to_google(py):
2121
import copy
2222
import json
2323
import logging
24-
import os
2524
import shutil
2625
import sys
2726
from pathlib import Path
@@ -71,56 +70,56 @@ def rp_logger(request):
7170

7271

7372
@pytest.fixture(scope="session", autouse=True)
74-
def project_root() -> str:
73+
def project_root() -> Path:
7574
"""The Project (or Workspace) root as a filepath.
7675
7776
* This conftest.py file should be in the Project Root if not already.
7877
"""
79-
return os.path.dirname(os.path.abspath(__file__))
78+
return Path(__file__).absolute().parent
8079

8180

8281
@pytest.fixture(scope="session", autouse=True)
83-
def test_run(project_root, request) -> str:
82+
def test_run(project_root: Path, request) -> Path:
8483
"""Creates the `/test_results` directory to store the results of the Test Run.
8584
8685
Returns:
8786
The `/test_results` directory as a filepath (str).
8887
"""
8988
session = request.node
90-
test_results_dir = f"{project_root}/test_results"
89+
test_results_dir = project_root.joinpath("test_results")
9190

92-
if os.path.exists(test_results_dir):
91+
if test_results_dir.exists():
9392
# delete /test_results from previous Test Run
9493
shutil.rmtree(test_results_dir, ignore_errors=True)
9594

9695
try:
9796
# race condition can occur between checking file existence and
9897
# creating the file when using pytest with multiple workers
99-
Path(test_results_dir).mkdir(parents=True, exist_ok=True)
98+
test_results_dir.mkdir(parents=True, exist_ok=True)
10099
except FileExistsError:
101100
pass
102101

103102
for test in session.items:
104103
try:
105104
# make the test_result directory for each test
106-
Path(f"{test_results_dir}/{test.name}").mkdir(parents=True, exist_ok=True)
105+
test_results_dir.joinpath(test.name).mkdir(parents=True, exist_ok=True)
107106
except FileExistsError:
108107
pass
109108

110109
return test_results_dir
111110

112111

113-
@pytest.fixture(scope="session")
114-
def _py_config(project_root, request) -> PyleniumConfig:
115-
"""Read the PyleniumConfig for the test session
112+
@pytest.fixture(scope="function")
113+
def py_config(project_root: Path, request) -> PyleniumConfig:
114+
"""Initialize a PyleniumConfig for each test
116115
117116
1. This starts by deserializing the user-created pylenium.json from the Project Root.
118117
2. If that file is not found, then proceed with Pylenium Defaults.
119118
3. Then any CLI arguments override their respective key/values.
120119
"""
121120
try:
122121
# 1. Load pylenium.json in Project Root, if available
123-
with open(f"{project_root}/pylenium.json") as file:
122+
with project_root.joinpath("pylenium.json").open() as file:
124123
_json = json.load(file)
125124
config = PyleniumConfig(**_json)
126125
except FileNotFoundError:
@@ -171,16 +170,7 @@ def _py_config(project_root, request) -> PyleniumConfig:
171170

172171

173172
@pytest.fixture(scope="function")
174-
def py_config(_py_config) -> PyleniumConfig:
175-
"""Get a fresh copy of the PyleniumConfig for each test
176-
177-
See _py_config for how the initial configuration is read.
178-
"""
179-
return copy.deepcopy(_py_config)
180-
181-
182-
@pytest.fixture(scope="function")
183-
def test_case(test_run, py_config, request) -> TestCase:
173+
def test_case(test_run: Path, py_config, request) -> TestCase:
184174
"""Manages data pertaining to the currently running Test Function or Case.
185175
186176
* Creates the test-specific logger.
@@ -192,13 +182,13 @@ def test_case(test_run, py_config, request) -> TestCase:
192182
An instance of TestCase.
193183
"""
194184
test_name = request.node.name
195-
test_result_path = f"{test_run}/{test_name}"
185+
test_result_path = test_run.joinpath(test_name)
196186
py_config.driver.capabilities.update({"name": test_name})
197187
return TestCase(name=test_name, file_path=test_result_path)
198188

199189

200190
@pytest.fixture(scope="function")
201-
def py(test_case, py_config, request, rp_logger):
191+
def py(test_case: TestCase, py_config, request, rp_logger):
202192
"""Initialize a Pylenium driver for each test.
203193
204194
Pass in this `py` fixture into the test function.
@@ -214,7 +204,7 @@ def test_go_to_google(py):
214204
if request.node.report.failed:
215205
# if the test failed, execute code in this block
216206
if py_config.logging.screenshots_on:
217-
screenshot = py.screenshot(f"{test_case.file_path}/test_failed.png")
207+
screenshot = py.screenshot(str(test_case.file_path.joinpath("test_failed.png")))
218208
with open(screenshot, "rb") as image_file:
219209
rp_logger.info(
220210
"Test Failed - Attaching Screenshot",

pylenium/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from pathlib import Path
12
from typing import List, Dict
23

34
from pydantic import BaseModel
@@ -46,7 +47,7 @@ class PyleniumConfig(BaseModel):
4647

4748
class TestCase(BaseModel):
4849
name: str
49-
file_path: str
50+
file_path: Path
5051

5152
class Config:
5253
arbitrary_types_allowed = True

pylenium/scripts/conftest.py

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ def test_go_to_google(py):
2121
import copy
2222
import json
2323
import logging
24-
import os
2524
import shutil
2625
import sys
2726
from pathlib import Path
@@ -71,56 +70,56 @@ def rp_logger(request):
7170

7271

7372
@pytest.fixture(scope="session", autouse=True)
74-
def project_root() -> str:
73+
def project_root() -> Path:
7574
"""The Project (or Workspace) root as a filepath.
7675
7776
* This conftest.py file should be in the Project Root if not already.
7877
"""
79-
return os.path.dirname(os.path.abspath(__file__))
78+
return Path(__file__).absolute().parent
8079

8180

8281
@pytest.fixture(scope="session", autouse=True)
83-
def test_run(project_root, request) -> str:
82+
def test_run(project_root: Path, request) -> Path:
8483
"""Creates the `/test_results` directory to store the results of the Test Run.
8584
8685
Returns:
8786
The `/test_results` directory as a filepath (str).
8887
"""
8988
session = request.node
90-
test_results_dir = f"{project_root}/test_results"
89+
test_results_dir = project_root.joinpath("test_results")
9190

92-
if os.path.exists(test_results_dir):
91+
if test_results_dir.exists():
9392
# delete /test_results from previous Test Run
9493
shutil.rmtree(test_results_dir, ignore_errors=True)
9594

9695
try:
9796
# race condition can occur between checking file existence and
9897
# creating the file when using pytest with multiple workers
99-
Path(test_results_dir).mkdir(parents=True, exist_ok=True)
98+
test_results_dir.mkdir(parents=True, exist_ok=True)
10099
except FileExistsError:
101100
pass
102101

103102
for test in session.items:
104103
try:
105104
# make the test_result directory for each test
106-
Path(f"{test_results_dir}/{test.name}").mkdir(parents=True, exist_ok=True)
105+
test_results_dir.joinpath(test.name).mkdir(parents=True, exist_ok=True)
107106
except FileExistsError:
108107
pass
109108

110109
return test_results_dir
111110

112111

113-
@pytest.fixture(scope="session")
114-
def _py_config(project_root, request) -> PyleniumConfig:
115-
"""Read the PyleniumConfig for the test session
112+
@pytest.fixture(scope="function")
113+
def py_config(project_root: Path, request) -> PyleniumConfig:
114+
"""Initialize a PyleniumConfig for each test
116115
117116
1. This starts by deserializing the user-created pylenium.json from the Project Root.
118117
2. If that file is not found, then proceed with Pylenium Defaults.
119118
3. Then any CLI arguments override their respective key/values.
120119
"""
121120
try:
122121
# 1. Load pylenium.json in Project Root, if available
123-
with open(f"{project_root}/pylenium.json") as file:
122+
with project_root.joinpath("pylenium.json").open() as file:
124123
_json = json.load(file)
125124
config = PyleniumConfig(**_json)
126125
except FileNotFoundError:
@@ -171,16 +170,7 @@ def _py_config(project_root, request) -> PyleniumConfig:
171170

172171

173172
@pytest.fixture(scope="function")
174-
def py_config(_py_config) -> PyleniumConfig:
175-
"""Get a fresh copy of the PyleniumConfig for each test
176-
177-
See _py_config for how the initial configuration is read.
178-
"""
179-
return copy.deepcopy(_py_config)
180-
181-
182-
@pytest.fixture(scope="function")
183-
def test_case(test_run, py_config, request) -> TestCase:
173+
def test_case(test_run: Path, py_config, request) -> TestCase:
184174
"""Manages data pertaining to the currently running Test Function or Case.
185175
186176
* Creates the test-specific logger.
@@ -192,13 +182,13 @@ def test_case(test_run, py_config, request) -> TestCase:
192182
An instance of TestCase.
193183
"""
194184
test_name = request.node.name
195-
test_result_path = f"{test_run}/{test_name}"
185+
test_result_path = test_run.joinpath(test_name)
196186
py_config.driver.capabilities.update({"name": test_name})
197187
return TestCase(name=test_name, file_path=test_result_path)
198188

199189

200190
@pytest.fixture(scope="function")
201-
def py(test_case, py_config, request, rp_logger):
191+
def py(test_case: TestCase, py_config, request, rp_logger):
202192
"""Initialize a Pylenium driver for each test.
203193
204194
Pass in this `py` fixture into the test function.
@@ -214,7 +204,7 @@ def test_go_to_google(py):
214204
if request.node.report.failed:
215205
# if the test failed, execute code in this block
216206
if py_config.logging.screenshots_on:
217-
screenshot = py.screenshot(f"{test_case.file_path}/test_failed.png")
207+
screenshot = py.screenshot(str(test_case.file_path.joinpath("test_failed.png")))
218208
with open(screenshot, "rb") as image_file:
219209
rp_logger.info(
220210
"Test Failed - Attaching Screenshot",

0 commit comments

Comments
 (0)