# -*- coding: utf-8 -*-
import os
import sys
import contextlib
import subprocess
from pathlib import Path
__version__ = "0.1.1"
[docs]@contextlib.contextmanager
def temp_cwd(path: Path):
"""
Temporarily set the current working directory (CWD) and automatically
switch back when it's done.
"""
cwd = os.getcwd()
os.chdir(str(path))
try:
yield path
finally:
os.chdir(cwd)
[docs]def run_cov_test(
script: str,
module: str,
root_dir: str,
htmlcov_dir: str,
preview: bool = False,
is_folder: bool = False,
):
"""
The pytest-cov plugin gives you the coverage for entire project. What if
I want run per-module test independently and get per-module coverage?
This is a simple wrapper around pytest + coverage cli command. Allow you to run
coverage test from Python script and set the code coverage measurement scope.
Usage example:
suppose you have a source code folder structure like this::
/dir_git_repo/
/dir_git_repo/my_library
/dir_git_repo/my_library/__init__.py
/dir_git_repo/my_library/module1.py
/dir_git_repo/my_library/module2.py
In your module 1 unit test script, you can do this:
.. code-block:: python
from my_library.module1 import func1, func2
def test_func1():
pass
def test_func2():
pass
if __name__ == "__main__":
from fixa.pytest_cov_helper import run_cov_test
run_cov_test(
script=__file__,
module="my_library.module1", # test scope is the module1.py
root_dir="/path/to/dir_git_repo",
htmlcov_dir="/path/to/dir_git_repo/htmlcov",
)
In your all modules unit test script, you can do this:
.. code-block:: python
if __name__ == "__main__":
from fixa.pytest_cov_helper import run_cov_test
run_cov_test(
script=__file__,
module="my_library", # test scope is the my_library/
root_dir="/path/to/dir_git_repo",
htmlcov_dir="/path/to/dir_git_repo/htmlcov",
is_folder=True, # my_library is a folder
)
:param script: the path to test script
:param module: the dot notation to the python module you want to calculate
coverage
:param root_dir: the dir to dump coverage results binary file
:param htmlcov_dir: the dir to dump HTML output
:param preview: whether to open the HTML output in web browser after the test
:param is_folder: whether the module is a folder
Reference:
- https://pypi.org/project/pytest-cov/
"""
bin_pytest = Path(sys.executable).parent / "pytest"
if is_folder:
script = f"{Path(script).parent}"
if module.endswith(".py"): # pragma: no cover
module = module[:-3]
args = [
f"{bin_pytest}",
"-s",
"--tb=native",
f"--rootdir={root_dir}",
f"--cov={module}",
"--cov-report",
"term-missing",
"--cov-report",
f"html:{htmlcov_dir}",
script,
]
with temp_cwd(Path(root_dir)):
subprocess.run(args)
if preview: # pragma: no cover
platform = sys.platform
if platform in ["win32", "cygwin"]:
open_command = "start"
elif platform in ["darwin", "linux"]:
open_command = "open"
else:
raise NotImplementedError
subprocess.run([open_command, f"{Path(htmlcov_dir).joinpath('index.html')}"])