diff --git a/CHANGELOG.md b/CHANGELOG.md index e348ee7..1e6186b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Make `nftest run` exit with the number of failed tests - Use `shell=False` for subprocess - Capture Nextflow logs via syslog rather than console +- Format all code with ruff ### Fixed - Make `nftest` with no arguments print usage and exit diff --git a/nftest/NFTestAssert.py b/nftest/NFTestAssert.py index 32f837b..07fc100 100644 --- a/nftest/NFTestAssert.py +++ b/nftest/NFTestAssert.py @@ -1,4 +1,5 @@ -""" NF Test assert """ +"""NF Test assert""" + import datetime import errno import os @@ -6,17 +7,19 @@ from typing import Callable from logging import getLogger, DEBUG -from nftest.common import calculate_checksum, resolve_single_path, \ - popen_with_logger +from nftest.common import calculate_checksum, resolve_single_path, popen_with_logger from nftest.NFTestENV import NFTestENV -class NFTestAssert(): - """ Defines how nextflow test results are asserted. """ - def __init__(self, actual:str, expect:str, method:str='md5', script:str=None): - """ Constructor """ +class NFTestAssert: + """Defines how nextflow test results are asserted.""" + + def __init__( + self, actual: str, expect: str, method: str = "md5", script: str = None + ): + """Constructor""" self._env = NFTestENV() - self._logger = getLogger('NFTest') + self._logger = getLogger("NFTest") self.actual = actual self.expect = expect self.method = method @@ -25,68 +28,71 @@ def __init__(self, actual:str, expect:str, method:str='md5', script:str=None): self.startup_time = datetime.datetime.now(tz=datetime.timezone.utc) def identify_assertion_files(self) -> None: - """ Resolve actual and expected paths """ + """Resolve actual and expected paths""" self.actual = resolve_single_path(self.actual) self.expect = resolve_single_path(self.expect) def assert_exists(self) -> None: "Assert that the expected and actual files exist." if not self.actual.exists(): - self._logger.error('Actual file not found: %s', self.actual) - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), - self.actual) + self._logger.error("Actual file not found: %s", self.actual) + raise FileNotFoundError( + errno.ENOENT, os.strerror(errno.ENOENT), self.actual + ) if not self.expect.exists(): - self._logger.error('Expect file not found: %s', self.expect) - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), - self.expect) + self._logger.error("Expect file not found: %s", self.expect) + raise FileNotFoundError( + errno.ENOENT, os.strerror(errno.ENOENT), self.expect + ) def assert_updated(self) -> None: "Assert that the actual file was updated during this test run." file_mod_time = datetime.datetime.fromtimestamp( - self.actual.stat().st_mtime, - tz=datetime.timezone.utc + self.actual.stat().st_mtime, tz=datetime.timezone.utc ) self._logger.debug("Test creation time: %s", self.startup_time) self._logger.debug("Actual mod time: %s", file_mod_time) - assert file_mod_time > self.startup_time, \ - f"{str(self.actual)} was not modified by this pipeline" + assert ( + file_mod_time > self.startup_time + ), f"{str(self.actual)} was not modified by this pipeline" def assert_expected(self) -> None: "Assert the results match with the expected values." assert_method = self.get_assert_method() try: assert assert_method(self.actual, self.expect) - self._logger.debug('Assertion passed') + self._logger.debug("Assertion passed") except AssertionError as error: - self._logger.error('Assertion failed') - self._logger.error('Actual: %s', self.actual) - self._logger.error('Expect: %s', self.expect) + self._logger.error("Assertion failed") + self._logger.error("Actual: %s", self.actual) + self._logger.error("Expect: %s", self.expect) raise error def get_assert_method(self) -> Callable: - """ Get the assert method """ + """Get the assert method""" # pylint: disable=E0102 if self.script is not None: + def func(actual, expect): cmd = [self.script, actual, expect] self._logger.debug(subprocess.list2cmdline(cmd)) process = popen_with_logger( - cmd, - logger=self._logger, - stdout_level=DEBUG + cmd, logger=self._logger, stdout_level=DEBUG ) return process.returncode == 0 return func - if self.method == 'md5': + if self.method == "md5": + def func(actual, expect): self._logger.debug("md5 %s %s", actual, expect) actual_value = calculate_checksum(actual) expect_value = calculate_checksum(expect) return actual_value == expect_value + return func - self._logger.error('assert method %s unknown.', self.method) - raise ValueError(f'assert method {self.method} unknown.') + self._logger.error("assert method %s unknown.", self.method) + raise ValueError(f"assert method {self.method} unknown.") diff --git a/nftest/NFTestCase.py b/nftest/NFTestCase.py index 5bb720b..5b134bf 100644 --- a/nftest/NFTestCase.py +++ b/nftest/NFTestCase.py @@ -1,4 +1,5 @@ -""" NF Test case """ +"""NF Test case""" + from __future__ import annotations import logging @@ -23,23 +24,36 @@ from nftest.NFTestAssert import NFTestAssert -class NFTestCase(): - """ Defines the NF test case """ +class NFTestCase: + """Defines the NF test case""" + # pylint: disable=R0902 # pylint: disable=R0913 - def __init__(self, name:str=None, message:str=None, nf_script:str=None, - nf_configs:List[str]=None, profiles:List[str]=None, params_file:str=None, - reference_params:List[Tuple[str,str]]=None, - output_directory_param_name:str='output_dir', - asserts:List[NFTestAssert]=None, temp_dir:str=None, - remove_temp:bool=None, clean_logs:bool=None, - skip:bool=False, verbose:bool=False): - """ Constructor """ + def __init__( + self, + name: str = None, + message: str = None, + nf_script: str = None, + nf_configs: List[str] = None, + profiles: List[str] = None, + params_file: str = None, + reference_params: List[Tuple[str, str]] = None, + output_directory_param_name: str = "output_dir", + asserts: List[NFTestAssert] = None, + temp_dir: str = None, + remove_temp: bool = None, + clean_logs: bool = None, + skip: bool = False, + verbose: bool = False, + ): + """Constructor""" self._env = NFTestENV() - self._logger = logging.getLogger('NFTest') + self._logger = logging.getLogger("NFTest") self._nflogger = logging.getLogger("console") self.name = name - self.name_for_output = re.sub(r'[^a-zA-Z0-9_\-.]', '', self.name.replace(' ', '-')) + self.name_for_output = re.sub( + r"[^a-zA-Z0-9_\-.]", "", self.name.replace(" ", "-") + ) self.message = message self.nf_script = nf_script self.nf_configs = nf_configs or [] @@ -54,20 +68,22 @@ def __init__(self, name:str=None, message:str=None, nf_script:str=None, self.skip = skip self.verbose = verbose - def resolve_actual(self, asserts:List[NFTestAssert]=None): - """ Resolve the file path for actual file """ + def resolve_actual(self, asserts: List[NFTestAssert] = None): + """Resolve the file path for actual file""" if not asserts: return [] for assertion in asserts: assertion.actual = str( - Path(self._env.NFT_OUTPUT)/self.name_for_output/assertion.actual) + Path(self._env.NFT_OUTPUT) / self.name_for_output / assertion.actual + ) return asserts # pylint: disable=E0213 def test_wrapper(func: Callable): - """ Wrap tests with additional logging and cleaning. """ + """Wrap tests with additional logging and cleaning.""" + def wrapper(self): # pylint: disable=E1102 self.print_prolog() @@ -83,14 +99,14 @@ def wrapper(self): @test_wrapper def test(self) -> bool: - """ Run test cases. """ + """Run test cases.""" if self.skip: - self._logger.info(' [ skipped ]') + self._logger.info(" [ skipped ]") return True nextflow_succeeded = self.submit() if not nextflow_succeeded: - self._logger.error(' [ failed ]') + self._logger.error(" [ failed ]") return False for ass in self.asserts: @@ -101,13 +117,13 @@ def test(self) -> bool: ass.assert_expected() except Exception as error: self._logger.error(error.args) - self._logger.error(' [ failed ]') + self._logger.error(" [ failed ]") raise error - self._logger.info(' [ succeed ]') + self._logger.info(" [ succeed ]") return True def submit(self) -> sp.CompletedProcess: - """ Submit a nextflow run """ + """Submit a nextflow run""" # Use ExitStack to handle the multiple nested context managers with ExitStack() as stack: # Create a server with a random port to accept syslogs from @@ -123,7 +139,7 @@ def submit(self) -> sp.CompletedProcess: threading.Thread( name="SyslogThread", target=syslog_server.serve_forever, - kwargs={"poll_interval": 1} + kwargs={"poll_interval": 1}, ).start() syslog_address = ":".join( @@ -133,9 +149,10 @@ def submit(self) -> sp.CompletedProcess: nextflow_command = [ "nextflow", "-quiet", - "-syslog", syslog_address, + "-syslog", + syslog_address, "run", - self.nf_script + self.nf_script, ] if self.profiles: @@ -152,30 +169,26 @@ def submit(self) -> sp.CompletedProcess: nextflow_command.extend([ f"--{self.output_directory_param_name}", - Path(self._env.NFT_OUTPUT, self.name_for_output) + Path(self._env.NFT_OUTPUT, self.name_for_output), ]) - envmod = { - "NXF_WORK": self.temp_dir - } + envmod = {"NXF_WORK": self.temp_dir} # Log the shell equivalent of this command self._logger.info( "%s %s", " ".join([f"{k}={shlex.quote(v)}" for k, v in envmod.items()]), - sp.list2cmdline(nextflow_command) + sp.list2cmdline(nextflow_command), ) process = popen_with_logger( - nextflow_command, - env={**os.environ, **envmod}, - logger=self._nflogger + nextflow_command, env={**os.environ, **envmod}, logger=self._nflogger ) return process def combine_global(self, _global: NFTestGlobal) -> None: - """ Combine test case configs with the global configs. """ + """Combine test case configs with the global configs.""" if _global.nf_config: self.nf_configs.insert(0, _global.nf_config) @@ -192,6 +205,6 @@ def combine_global(self, _global: NFTestGlobal) -> None: self.clean_logs = _global.clean_logs def print_prolog(self): - """ Print prolog message """ - prolog = f'{self.name}: {self.message}' + """Print prolog message""" + prolog = f"{self.name}: {self.message}" self._logger.info(prolog) diff --git a/nftest/NFTestENV.py b/nftest/NFTestENV.py index d6145bd..7a27e07 100644 --- a/nftest/NFTestENV.py +++ b/nftest/NFTestENV.py @@ -1,15 +1,17 @@ -""" Environment variables """ +"""Environment variables""" + import os import datetime from dataclasses import dataclass, field from dotenv import load_dotenv from nftest.Singleton import Singleton + # pylint: disable=C0103 @dataclass class NFTestENV(metaclass=Singleton): - """ Class for initializng and holding environment variables. - """ + """Class for initializng and holding environment variables.""" + NFT_OUTPUT: str = field(init=False) NFT_TEMP: str = field(init=False) NFT_INIT: str = field(init=False) @@ -17,27 +19,32 @@ class NFTestENV(metaclass=Singleton): NFT_LOG: str = field(init=False) def __post_init__(self): - """ Post-init set env variables """ + """Post-init set env variables""" NFTestENV.load_env() - self.NFT_OUTPUT = os.getenv('NFT_OUTPUT', default='./') - self.NFT_TEMP = os.getenv('NFT_TEMP', default='./') - self.NFT_INIT = os.getenv('NFT_INIT', default=str(os.getcwd())) - self.NFT_LOG_LEVEL = os.getenv('NFT_LOG_LEVEL', default='INFO') - self.NFT_LOG = os.getenv('NFT_LOG', default=os.path.join(self.NFT_OUTPUT, \ - f'log-nftest-{datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")}.log')) + self.NFT_OUTPUT = os.getenv("NFT_OUTPUT", default="./") + self.NFT_TEMP = os.getenv("NFT_TEMP", default="./") + self.NFT_INIT = os.getenv("NFT_INIT", default=str(os.getcwd())) + self.NFT_LOG_LEVEL = os.getenv("NFT_LOG_LEVEL", default="INFO") + self.NFT_LOG = os.getenv( + "NFT_LOG", + default=os.path.join( + self.NFT_OUTPUT, + f'log-nftest-{datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")}.log', + ), + ) @staticmethod def load_env(): - """ Load and set env variables """ + """Load and set env variables""" dirs_to_check = [] dirs_to_check.append(os.getcwd()) - dirs_to_check.append(os.path.expanduser('~')) + dirs_to_check.append(os.path.expanduser("~")) for adir in dirs_to_check: - if not load_dotenv(os.path.join(adir, '.env')): - print(f'LOG: .env not found in {adir}.', flush=True) + if not load_dotenv(os.path.join(adir, ".env")): + print(f"LOG: .env not found in {adir}.", flush=True) else: - print(f'LOG: Loaded .env from {adir}', flush=True) + print(f"LOG: Loaded .env from {adir}", flush=True) return - print('WARN: unable to find .env. Default values will be used.', flush=True) + print("WARN: unable to find .env. Default values will be used.", flush=True) diff --git a/nftest/NFTestGlobal.py b/nftest/NFTestGlobal.py index c3c9a98..f6b59cb 100644 --- a/nftest/NFTestGlobal.py +++ b/nftest/NFTestGlobal.py @@ -1,13 +1,21 @@ -""" Global settings """ +"""Global settings""" + import os from nftest.NFTestENV import NFTestENV -class NFTestGlobal(): - """ Test global settings """ + +class NFTestGlobal: + """Test global settings""" + # pylint: disable=R0903 - def __init__(self, temp_dir:str, nf_config:str, - remove_temp:bool=True, clean_logs:bool=True): - """ constructor """ + def __init__( + self, + temp_dir: str, + nf_config: str, + remove_temp: bool = True, + clean_logs: bool = True, + ): + """constructor""" self._env = NFTestENV() self.temp_dir = os.path.join(self._env.NFT_TEMP, temp_dir) self.nf_config = os.path.join(self._env.NFT_INIT, nf_config) diff --git a/nftest/NFTestRunner.py b/nftest/NFTestRunner.py index f868d37..80238c4 100644 --- a/nftest/NFTestRunner.py +++ b/nftest/NFTestRunner.py @@ -1,4 +1,5 @@ -""" Test runner """ +"""Test runner""" + import shutil from logging import getLogger from typing import List @@ -9,33 +10,37 @@ from nftest.NFTestENV import NFTestENV from nftest.common import validate_yaml, validate_reference -class NFTestRunner(): - """ This holds all test cases and global settings from a single yaml file. - """ - def __init__(self, cases:List[NFTestCase]=None): - """ Constructor """ + +class NFTestRunner: + """This holds all test cases and global settings from a single yaml file.""" + + def __init__(self, cases: List[NFTestCase] = None): + """Constructor""" self._global = None self._env = NFTestENV() - self._logger = getLogger('NFTest') + self._logger = getLogger("NFTest") self.cases = cases or [] - def load_from_config(self, config_yaml:str, target_cases:List[str]): - """ Load test info from config file. """ + def load_from_config(self, config_yaml: str, target_cases: List[str]): + """Load test info from config file.""" validate_yaml(config_yaml) - with open(config_yaml, 'rt', encoding='utf-8') as handle: + with open(config_yaml, "rt", encoding="utf-8") as handle: config = yaml.safe_load(handle) - self._global = NFTestGlobal(**config['global']) - for case in config['cases']: - if 'asserts' in case: - asserts = [NFTestAssert(**ass) \ - for ass in case['asserts']] + self._global = NFTestGlobal(**config["global"]) + for case in config["cases"]: + if "asserts" in case: + asserts = [NFTestAssert(**ass) for ass in case["asserts"]] else: asserts = [] - case['asserts'] = asserts - case['nf_configs'] = [case.pop('nf_config')] if case.get('nf_config', None) else [] - if 'reference_files' in case: - case['reference_params'] = [validate_reference(**reference_file) - for reference_file in case.pop('reference_files')] + case["asserts"] = asserts + case["nf_configs"] = ( + [case.pop("nf_config")] if case.get("nf_config", None) else [] + ) + if "reference_files" in case: + case["reference_params"] = [ + validate_reference(**reference_file) + for reference_file in case.pop("reference_files") + ] test_case = NFTestCase(**case) test_case.combine_global(self._global) if target_cases: @@ -46,7 +51,7 @@ def load_from_config(self, config_yaml:str, target_cases:List[str]): self.cases.append(test_case) def main(self): - """ Main entrance """ + """Main entrance""" self.print_prolog() failure_count = 0 @@ -62,11 +67,15 @@ def main(self): return failure_count def print_prolog(self): - """ Print prolog """ - prolog = '' + """Print prolog""" + prolog = "" terminal_width = shutil.get_terminal_size().columns - header = ' NFTEST STARTS ' - half_width = int((terminal_width - len(header))/2) - prolog = '=' * half_width + header + '=' * (terminal_width - len(header) - half_width) + header = " NFTEST STARTS " + half_width = int((terminal_width - len(header)) / 2) + prolog = ( + "=" * half_width + + header + + "=" * (terminal_width - len(header) - half_width) + ) print(prolog, flush=True) - self._logger.info('Beginning tests...') + self._logger.info("Beginning tests...") diff --git a/nftest/Singleton.py b/nftest/Singleton.py index fdb8155..4d17d6f 100644 --- a/nftest/Singleton.py +++ b/nftest/Singleton.py @@ -1,7 +1,9 @@ -""" Module containg Singleton metaclass """ +"""Module containg Singleton metaclass""" + class Singleton(type): - """ Singleton metaclass """ + """Singleton metaclass""" + _instances = {} def __call__(cls, *args, **kwargs): diff --git a/nftest/__init__.py b/nftest/__init__.py index 559b50e..dde3ce6 100644 --- a/nftest/__init__.py +++ b/nftest/__init__.py @@ -1,3 +1,3 @@ -""" nftest module """ +"""nftest module""" -__version__ = '1.0.1' +__version__ = "1.0.1" diff --git a/nftest/__main__.py b/nftest/__main__.py index af426b6..4318f57 100644 --- a/nftest/__main__.py +++ b/nftest/__main__.py @@ -1,4 +1,5 @@ -""" Test NF-pipelines """ +"""Test NF-pipelines""" + from __future__ import annotations import argparse import sys @@ -12,18 +13,13 @@ def parse_args() -> argparse.Namespace: - """ Parse args """ - parser = argparse.ArgumentParser( - prog='nftest' - ) + """Parse args""" + parser = argparse.ArgumentParser(prog="nftest") parser.add_argument( - '-V', '--version', - help='Version', - action='store_true', - default=False + "-V", "--version", help="Version", action="store_true", default=False ) - subparsers = parser.add_subparsers(dest='command') + subparsers = parser.add_subparsers(dest="command") add_subparser_init(subparsers) add_subparser_run(subparsers) @@ -38,93 +34,96 @@ def parse_args() -> argparse.Namespace: return args + # pylint: disable=W0212 -def add_subparser_init(subparsers:argparse._SubParsersAction): - """ Add subparser for init """ - parser:argparse.ArgumentParser = subparsers.add_parser( - name='init', - help='Initialize nftest.', - description='Initialize nftest by creating a nftest.yaml template.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter +def add_subparser_init(subparsers: argparse._SubParsersAction): + """Add subparser for init""" + parser: argparse.ArgumentParser = subparsers.add_parser( + name="init", + help="Initialize nftest.", + description="Initialize nftest by creating a nftest.yaml template.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.set_defaults(func=init) -def add_subparser_run(subparsers:argparse._SubParsersAction): - """ Add subparser for run """ - parser:argparse.ArgumentParser = subparsers.add_parser( - name='run', - help='Run nextflow tests.', - description='Run nextflow tests.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter + +def add_subparser_run(subparsers: argparse._SubParsersAction): + """Add subparser for run""" + parser: argparse.ArgumentParser = subparsers.add_parser( + name="run", + help="Run nextflow tests.", + description="Run nextflow tests.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument( - '-c', '--config-file', + "-c", + "--config-file", type=Path, - help='Path to the nextflow test config YAML file. If not given, it' - ' looks for nftest.yaml or nftest.yml', + help="Path to the nextflow test config YAML file. If not given, it" + " looks for nftest.yaml or nftest.yml", default=None, - nargs='?' + nargs="?", ) parser.add_argument( - 'TEST_CASES', - type=str, - help='Exact test case to run.', - nargs='*' + "TEST_CASES", type=str, help="Exact test case to run.", nargs="*" ) parser.set_defaults(func=run) + def run(args): - """ Run """ + """Run""" find_config_yaml(args) setup_loggers() runner = NFTestRunner() runner.load_from_config(args.config_file, args.TEST_CASES) sys.exit(runner.main()) + def init(_): - """ Set up nftest """ + """Set up nftest""" _env = NFTestENV() setup_loggers() - _logger = getLogger('NFTestInit') + _logger = getLogger("NFTestInit") working_dir = Path(_env.NFT_INIT) if not working_dir.exists(): try: - _logger.warning('%s does not exist, attempting to create it...', working_dir) + _logger.warning( + "%s does not exist, attempting to create it...", working_dir + ) working_dir.mkdir(parents=True) except (OSError, PermissionError) as file_error: - raise RuntimeError(f'Failed to create {working_dir}. ' \ - 'Please ensure proper permissions are set.') \ - from file_error + raise RuntimeError( + f"Failed to create {working_dir}. " + "Please ensure proper permissions are set." + ) from file_error # copy over the nftest.yaml - nftest_yaml = pkg_resources.resource_filename( - 'nftest', 'data/nftest.yml' - ) - if not (working_dir/'nftest.yml').exists(): + nftest_yaml = pkg_resources.resource_filename("nftest", "data/nftest.yml") + if not (working_dir / "nftest.yml").exists(): test_yaml = shutil.copy2(nftest_yaml, working_dir) - _logger.info('%s created', test_yaml) + _logger.info("%s created", test_yaml) else: - _logger.info('%s/nftest.yml already exists', working_dir) + _logger.info("%s/nftest.yml already exists", working_dir) # copy global.config over - global_config = pkg_resources.resource_filename( - 'nftest', 'data/global.config' - ) - test_dir = working_dir/'test' + global_config = pkg_resources.resource_filename("nftest", "data/global.config") + test_dir = working_dir / "test" test_dir.mkdir(exist_ok=True) - if not (test_dir/'global.config').exists(): - global_config = shutil.copy2(global_config, test_dir/'global.config') - _logger.info('%s created', global_config) + if not (test_dir / "global.config").exists(): + global_config = shutil.copy2(global_config, test_dir / "global.config") + _logger.info("%s created", global_config) else: - _logger.info('%s/global.config already exists', test_dir) + _logger.info("%s/global.config already exists", test_dir) + def main(): - """ main entrance """ + """main entrance""" args = parse_args() args.func(args) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/nftest/common.py b/nftest/common.py index d03942c..4f36126 100644 --- a/nftest/common.py +++ b/nftest/common.py @@ -1,4 +1,5 @@ -""" Common functions """ +"""Common functions""" + import argparse import re from typing import Tuple @@ -18,33 +19,39 @@ from nftest.NFTestENV import NFTestENV from nftest.syslog import syslog_filter + # pylint: disable=W0613 -def validate_yaml(path:Path): - """ Validate the yaml. Potentially use yaml schema +def validate_yaml(path: Path): + """Validate the yaml. Potentially use yaml schema https://rx.codesimply.com/ """ return True + def remove_nextflow_logs() -> None: - """ Remove log files generated by nextflow """ - files = glob.glob('./.nextflow*') + """Remove log files generated by nextflow""" + files = glob.glob("./.nextflow*") for file in files: if Path(file).is_dir(): shutil.rmtree(file, ignore_errors=True) else: os.remove(file) -def resolve_single_path(path:str) -> Path: - """ Resolve wildcards in path and ensure only a single path is identified """ + +def resolve_single_path(path: str) -> Path: + """Resolve wildcards in path and ensure only a single path is identified""" expanded_paths = glob.glob(path) if 1 != len(expanded_paths): - raise ValueError(f"Path `{path}` resolved to 0 or more than 1 file: {expanded_paths}." \ - " Assertion failed.") + raise ValueError( + f"Path `{path}` resolved to 0 or more than 1 file: {expanded_paths}." + " Assertion failed." + ) return Path(expanded_paths[0]) -def calculate_checksum(path:Path) -> str: - """ Calculate checksum recursively. + +def calculate_checksum(path: Path) -> str: + """Calculate checksum recursively. Args: path (Path): The path to the directory. stdout (bool): If true, the result is printed to stdout. @@ -56,46 +63,54 @@ def calculate_checksum(path:Path) -> str: sum_val = sum_val.hexdigest() return sum_val + def validate_reference( - reference_parameter_name:str, - reference_parameter_path:str, - reference_checksum:str, - reference_checksum_type:str) -> Tuple[str, str]: - """ Validate reference file and checksum """ - if not re.match(r'[a-zA-Z0-9_\-.]+$', reference_parameter_name): - raise ValueError(f'Reference parameter name: `{reference_parameter_name}` is invalid. ' - f'Please use only alphanumeric, _, -, and . characters in parameter names.') + reference_parameter_name: str, + reference_parameter_path: str, + reference_checksum: str, + reference_checksum_type: str, +) -> Tuple[str, str]: + """Validate reference file and checksum""" + if not re.match(r"[a-zA-Z0-9_\-.]+$", reference_parameter_name): + raise ValueError( + f"Reference parameter name: `{reference_parameter_name}` is invalid. " + f"Please use only alphanumeric, _, -, and . characters in parameter names." + ) _logger = logging.getLogger("NFTest") actual_checksum = calculate_checksum(Path(reference_parameter_path)) if actual_checksum != reference_checksum: - _logger.warning('Checksum for reference file: %s' - '=%s - `%s` does not match expected checksum of `%s`', + _logger.warning( + "Checksum for reference file: %s" + "=%s - `%s` does not match expected checksum of `%s`", reference_parameter_name, reference_parameter_path, actual_checksum, - reference_checksum) + reference_checksum, + ) return (reference_parameter_name, reference_parameter_path) -def find_config_yaml(args:argparse.Namespace): - """ Find the test config yaml """ + +def find_config_yaml(args: argparse.Namespace): + """Find the test config yaml""" if args.config_file is None: - if Path('./nftest.yaml').exists(): - args.config_file = Path('./nftest.yaml') - elif Path('./nftest.yml').exists(): - args.config_file = Path('./nftest.yml') + if Path("./nftest.yaml").exists(): + args.config_file = Path("./nftest.yaml") + elif Path("./nftest.yml").exists(): + args.config_file = Path("./nftest.yml") + def print_version_and_exist(): - """ print version and exist """ + """print version and exist""" print(__version__, file=sys.stdout) sys.exit() def setup_loggers(): - """ Initialize loggers for both init and run """ + """Initialize loggers for both init and run""" # Always log times in UTC logging.Formatter.converter = time.gmtime @@ -106,12 +121,12 @@ def setup_loggers(): file_handler = logging.FileHandler(_env.NFT_LOG) file_handler.setLevel(logging.DEBUG) except (FileNotFoundError, PermissionError) as file_error: - raise RuntimeError(f'Unable to create log file: {_env.NFT_LOG}') from file_error + raise RuntimeError(f"Unable to create log file: {_env.NFT_LOG}") from file_error # Make a stream handler with the requested verbosity stream_handler = logging.StreamHandler(sys.stdout) try: - stream_handler.setLevel(logging._checkLevel(_env.NFT_LOG_LEVEL)) # pylint: disable=W0212 + stream_handler.setLevel(logging._checkLevel(_env.NFT_LOG_LEVEL)) # pylint: disable=W0212 except ValueError: stream_handler.setLevel(logging.INFO) @@ -121,30 +136,27 @@ def setup_loggers(): # This is a little sneaky: hide any tracebacks emitted via Nextflow's # syslog handler from the console. They will still be recorded in the log # file. - stream_handler.addFilter( - lambda record: record.threadName != "traceback" - ) + stream_handler.addFilter(lambda record: record.threadName != "traceback") # Set up different formats for the stream and file handlers # The key difference is that the file handler will contain the thread name - stream_handler.setFormatter(logging.Formatter( - '%(asctime)s - %(name)s - %(levelname)s - %(message)s', - )) - file_handler.setFormatter(logging.Formatter( - '%(asctime)s - %(name)s - %(threadName)s - %(levelname)s - %(message)s', - )) - - logging.basicConfig( - level=logging.DEBUG, - handlers=(file_handler, stream_handler) + stream_handler.setFormatter( + logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s", + ) ) + file_handler.setFormatter( + logging.Formatter( + "%(asctime)s - %(name)s - %(threadName)s - %(levelname)s - %(message)s", + ) + ) + + logging.basicConfig(level=logging.DEBUG, handlers=(file_handler, stream_handler)) -def popen_with_logger(*args, - logger=None, - stdout_level=logging.INFO, - stderr_level=logging.ERROR, - **kwargs) -> subprocess.CompletedProcess: +def popen_with_logger( + *args, logger=None, stdout_level=logging.INFO, stderr_level=logging.ERROR, **kwargs +) -> subprocess.CompletedProcess: """ Run a subprocess and stream the console outputs to a logger. """ @@ -158,21 +170,17 @@ def popen_with_logger(*args, kwargs.update({ "stdout": subprocess.PIPE, "stderr": subprocess.PIPE, - "universal_newlines": True + "universal_newlines": True, }) with subprocess.Popen(*args, **kwargs) as process: # Route stdout to INFO and stderr to ERROR in real-time with selectors.DefaultSelector() as selector: selector.register( - fileobj=process.stdout, - events=selectors.EVENT_READ, - data=stdout_level + fileobj=process.stdout, events=selectors.EVENT_READ, data=stdout_level ) selector.register( - fileobj=process.stderr, - events=selectors.EVENT_READ, - data=stderr_level + fileobj=process.stderr, events=selectors.EVENT_READ, data=stderr_level ) while process.poll() is None: @@ -182,9 +190,6 @@ def popen_with_logger(*args, if line: # The only case in which this won't be true is when # the pipe is closed - logger.log( - level=key.data, - msg=line.rstrip() - ) + logger.log(level=key.data, msg=line.rstrip()) return process diff --git a/nftest/syslog.py b/nftest/syslog.py index 32205f5..c9f06ab 100644 --- a/nftest/syslog.py +++ b/nftest/syslog.py @@ -1,11 +1,13 @@ """ Module for a system to capture Nextflow logs via syslog. """ + import logging import re import socketserver +# fmt: off LEVELS = [ logging.CRITICAL, # 0 = Emergency logging.CRITICAL, # 1 = Alert @@ -16,8 +18,10 @@ logging.INFO, # 6 = Info logging.DEBUG, # 7 = Debug ] +# fmt: on -SYSLOG_RE = re.compile(r""" +SYSLOG_RE = re.compile( + r""" ^ # Start of line <(?P\d+)> # Priority (?P\w{3})\s # Month @@ -26,7 +30,9 @@ (?P\S+)\s # Hostname (?P.*) # Message $ # End of line - """, re.VERBOSE | re.DOTALL) + """, + re.VERBOSE | re.DOTALL, +) MESSAGE_RE = re.compile(r"^nextflow:\s+\w+\s+\[(?P.+?)\] \S+ - ") @@ -80,31 +86,28 @@ def syslog_filter(record): class SyslogServer(socketserver.ThreadingUDPServer): "A UDPServer that logs itself starting up and shutting down." + @classmethod def make_server(cls): "Create a server with a random port to handle syslogs." - return cls( - server_address=("127.0.0.1", 0), - RequestHandlerClass=SyslogHandler - ) + return cls(server_address=("127.0.0.1", 0), RequestHandlerClass=SyslogHandler) def serve_forever(self, poll_interval=0.5): logging.getLogger(__name__).debug( - "Syslog server at %s:%d starting up", - *self.server_address + "Syslog server at %s:%d starting up", *self.server_address ) return super().serve_forever(poll_interval) def shutdown(self): logging.getLogger(__name__).debug( - "Syslog server at %s:%d shutting down", - *self.server_address + "Syslog server at %s:%d shutting down", *self.server_address ) return super().shutdown() class SyslogHandler(socketserver.BaseRequestHandler): "A simple syslog-like server to capture formatted logs from Nextflow." + def handle(self): # This is a syslog message from Nextflow logging.getLogger("nextflow").info(self.request[0]) diff --git a/setup.py b/setup.py index 106f96b..3460076 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ -""" setup """ +"""setup""" + from setuptools import setup setup() diff --git a/test/unit/test_NFTestAssert.py b/test/unit/test_NFTestAssert.py index 857dc7d..badb614 100644 --- a/test/unit/test_NFTestAssert.py +++ b/test/unit/test_NFTestAssert.py @@ -1,5 +1,6 @@ # pylint: disable=W0212 -''' Test module for NFTestAssert ''' +"""Test module for NFTestAssert""" + import datetime import mock @@ -7,10 +8,11 @@ from nftest.NFTestAssert import NFTestAssert -@mock.patch('nftest.NFTestAssert.NFTestAssert', wraps=NFTestAssert) + +@mock.patch("nftest.NFTestAssert.NFTestAssert", wraps=NFTestAssert) def test_get_assert_method_value_error(mock_assert): - ''' Tests value error from get_assert_method when given `method` is not supported ''' - assert_method = 'nomethod' + """Tests value error from get_assert_method when given `method` is not supported""" + assert_method = "nomethod" mock_assert.return_value.script = None mock_assert.return_value.method = assert_method mock_assert.return_value._logger.error = lambda x, y: None @@ -18,30 +20,32 @@ def test_get_assert_method_value_error(mock_assert): with pytest.raises(ValueError) as val_error: mock_assert.get_assert_method(mock_assert()) - assert str(val_error.value) == f'assert method {assert_method} unknown.' + assert str(val_error.value) == f"assert method {assert_method} unknown." + -@mock.patch('nftest.NFTestAssert.NFTestAssert', wraps=NFTestAssert) +@mock.patch("nftest.NFTestAssert.NFTestAssert", wraps=NFTestAssert) def test_get_assert_method_script(mock_assert): - ''' Tests getting script function from get_assert_method ''' - script_method = 'path/to/test/script.sh' + """Tests getting script function from get_assert_method""" + script_method = "path/to/test/script.sh" mock_assert.return_value.script = script_method mock_assert.return_value._logger.error = lambda x, y: None assert callable(mock_assert.get_assert_method(mock_assert())) -@mock.patch('nftest.NFTestAssert.NFTestAssert', wraps=NFTestAssert) + +@mock.patch("nftest.NFTestAssert.NFTestAssert", wraps=NFTestAssert) def test_get_assert_method_method(mock_assert): - ''' Tests getting method function from get_assert_method ''' + """Tests getting method function from get_assert_method""" mock_assert.return_value.script = None - mock_assert.return_value.method = 'md5' + mock_assert.return_value.method = "md5" mock_assert.return_value._logger.error = lambda x, y: None assert callable(mock_assert.get_assert_method(mock_assert())) -@mock.patch('nftest.NFTestAssert.NFTestAssert', wraps=NFTestAssert) +@mock.patch("nftest.NFTestAssert.NFTestAssert", wraps=NFTestAssert) def test_assert_exists(mock_assert): - '''Tests the functionality of the assert_exists method''' + """Tests the functionality of the assert_exists method""" # assert_exists() should raise an AssertionError if either or both of # actual and expect do not exist. # Tuples of (actual.exists(), expect.exists(), raises AssertionError) @@ -63,14 +67,13 @@ def test_assert_exists(mock_assert): NFTestAssert.assert_exists(mock_assert()) -@mock.patch('nftest.NFTestAssert.NFTestAssert', wraps=NFTestAssert) +@mock.patch("nftest.NFTestAssert.NFTestAssert", wraps=NFTestAssert) def test_assert_updated(mock_assert): - ''' Tests for failing assertion ''' + """Tests for failing assertion""" timestamp = 1689805542.4275217 mock_assert.return_value.startup_time = datetime.datetime.fromtimestamp( - timestamp, - tz=datetime.timezone.utc + timestamp, tz=datetime.timezone.utc ) # Test expected to fail with a time before the start time @@ -88,9 +91,9 @@ def test_assert_updated(mock_assert): NFTestAssert.assert_updated(mock_assert()) -@mock.patch('nftest.NFTestAssert.NFTestAssert', wraps=NFTestAssert) +@mock.patch("nftest.NFTestAssert.NFTestAssert", wraps=NFTestAssert) def test_assert_expected(mock_assert): - ''' Tests for passing assertion ''' + """Tests for passing assertion""" mock_assert.return_value._logger.error = lambda x, y=None: None # A passing test should not raise an error @@ -102,30 +105,23 @@ def test_assert_expected(mock_assert): with pytest.raises(AssertionError): NFTestAssert.assert_expected(mock_assert()) + @pytest.mark.parametrize( - 'glob_return_value,case_pass', - [ - ([], False), - (['a', 'b'], False), - (['a'], True) - ] + "glob_return_value,case_pass", [([], False), (["a", "b"], False), (["a"], True)] ) -@mock.patch('glob.glob') -@mock.patch('nftest.NFTestAssert.NFTestENV') -@mock.patch('logging.getLogger') +@mock.patch("glob.glob") +@mock.patch("nftest.NFTestAssert.NFTestENV") +@mock.patch("logging.getLogger") def test_identify_assertions_files( - mock_getlogger, - mock_env, - mock_glob, - glob_return_value, - case_pass): - ''' Tests for proper file identification ''' + mock_getlogger, mock_env, mock_glob, glob_return_value, case_pass +): + """Tests for proper file identification""" mock_glob.return_value = glob_return_value mock_env.return_value = None mock_getlogger.return_value = lambda x: None - test_assert = NFTestAssert('', '') + test_assert = NFTestAssert("", "") if case_pass: test_assert.identify_assertion_files() diff --git a/test/unit/test_NFTestCase.py b/test/unit/test_NFTestCase.py index bbd3001..a249604 100644 --- a/test/unit/test_NFTestCase.py +++ b/test/unit/test_NFTestCase.py @@ -1,14 +1,16 @@ # pylint: disable=W0212 -''' Test module for NFTestCase ''' +"""Test module for NFTestCase""" + from types import SimpleNamespace import mock from nftest.NFTestCase import NFTestCase -@mock.patch('nftest.NFTestCase.NFTestCase', wraps=NFTestCase) + +@mock.patch("nftest.NFTestCase.NFTestCase", wraps=NFTestCase) def test_combine_global(mock_case): - ''' Tests for using global config parameters ''' + """Tests for using global config parameters""" test_remove_temp = True - test_temp_directory = 'global_temp_dir' + test_temp_directory = "global_temp_dir" test_clean_logs = True mock_case.return_value.remove_temp = None mock_case.return_value.temp_dir = None @@ -24,23 +26,26 @@ def test_combine_global(mock_case): assert case.temp_dir == test_temp_directory assert case.clean_logs == test_clean_logs -@mock.patch('nftest.common.selectors') -@mock.patch('nftest.common.subprocess.Popen') -@mock.patch('nftest.NFTestCase.NFTestCase', wraps=NFTestCase) + +@mock.patch("nftest.common.selectors") +@mock.patch("nftest.common.subprocess.Popen") +@mock.patch("nftest.NFTestCase.NFTestCase", wraps=NFTestCase) def test_submit(mock_case, mock_sp, mock_selectors): - ''' Tests for submission step ''' - test_stdout = 'hello world' + """Tests for submission step""" + test_stdout = "hello world" - mock_sp.return_value.__enter__ = lambda x: SimpleNamespace( - **{'stdout': test_stdout, 'stderr': '', 'poll': lambda: True} - ) + mock_sp.return_value.__enter__ = lambda x: SimpleNamespace(**{ + "stdout": test_stdout, + "stderr": "", + "poll": lambda: True, + }) mock_selectors.DefaultSelector.register.return_value = lambda x, y, z: None - mock_case.return_value.params_file = '' - mock_case.return_value.output_directory_param_name = '' - mock_case.return_value._env.NFT_OUTPUT = '' - mock_case.return_value.temp_dir = '' - mock_case.return_value.nf_script = '' + mock_case.return_value.params_file = "" + mock_case.return_value.output_directory_param_name = "" + mock_case.return_value._env.NFT_OUTPUT = "" + mock_case.return_value.temp_dir = "" + mock_case.return_value.nf_script = "" mock_case.return_value.submit = NFTestCase.submit case = mock_case() diff --git a/test/unit/test_NFTestEnv.py b/test/unit/test_NFTestEnv.py index 157c638..433fc79 100644 --- a/test/unit/test_NFTestEnv.py +++ b/test/unit/test_NFTestEnv.py @@ -1,19 +1,21 @@ -''' Test module for NFTestENV ''' +"""Test module for NFTestENV""" + from nftest.NFTestENV import NFTestENV + def test_nftest_env_load(monkeypatch): - ''' Tests loading of values from environment ''' - test_out_directory = 'random/directory_output' - test_temp_directory = 'random/directory_temp' - test_init_directory = 'random/directory_init' - test_log_level = 'random_log_level' - test_log_file = 'random/log.log' - - monkeypatch.setenv('NFT_OUTPUT', test_out_directory) - monkeypatch.setenv('NFT_TEMP', test_temp_directory) - monkeypatch.setenv('NFT_INIT', test_init_directory) - monkeypatch.setenv('NFT_LOG_LEVEL', test_log_level) - monkeypatch.setenv('NFT_LOG', test_log_file) + """Tests loading of values from environment""" + test_out_directory = "random/directory_output" + test_temp_directory = "random/directory_temp" + test_init_directory = "random/directory_init" + test_log_level = "random_log_level" + test_log_file = "random/log.log" + + monkeypatch.setenv("NFT_OUTPUT", test_out_directory) + monkeypatch.setenv("NFT_TEMP", test_temp_directory) + monkeypatch.setenv("NFT_INIT", test_init_directory) + monkeypatch.setenv("NFT_LOG_LEVEL", test_log_level) + monkeypatch.setenv("NFT_LOG", test_log_file) nftest_env = NFTestENV() @@ -23,8 +25,9 @@ def test_nftest_env_load(monkeypatch): assert nftest_env.NFT_LOG_LEVEL == test_log_level assert nftest_env.NFT_LOG == test_log_file + def test_singleton(): - ''' Tests singleton pattern ''' + """Tests singleton pattern""" nftest_env1 = NFTestENV() nftest_env2 = NFTestENV() diff --git a/test/unit/test_NFTestRunner.py b/test/unit/test_NFTestRunner.py index 8646f74..d218d8e 100644 --- a/test/unit/test_NFTestRunner.py +++ b/test/unit/test_NFTestRunner.py @@ -1,45 +1,46 @@ -''' Test module for NFTestRunner ''' +"""Test module for NFTestRunner""" + from dataclasses import dataclass from unittest.mock import mock_open import mock from nftest.NFTestRunner import NFTestRunner + @dataclass -class RunnerData(): - """ Basic dataclass for holding runner data """ +class RunnerData: + """Basic dataclass for holding runner data""" + _global = None cases = [] + # pylint: disable=W0613 -@mock.patch('nftest.NFTestRunner.NFTestCase') -@mock.patch('nftest.NFTestRunner.yaml.safe_load') -@mock.patch('nftest.NFTestRunner.validate_yaml') -@mock.patch('nftest.NFTestRunner.NFTestGlobal') -@mock.patch('nftest.NFTestRunner.open', new_callable=mock_open) -@mock.patch('nftest.NFTestRunner.NFTestRunner', wraps=NFTestRunner) -def test_load_from_config(mock_runner, - mock_runner_open, - mock_global, - mock_validate_yaml, - mock_yaml, - mock_case): - ''' Tests for loading from config file ''' +@mock.patch("nftest.NFTestRunner.NFTestCase") +@mock.patch("nftest.NFTestRunner.yaml.safe_load") +@mock.patch("nftest.NFTestRunner.validate_yaml") +@mock.patch("nftest.NFTestRunner.NFTestGlobal") +@mock.patch("nftest.NFTestRunner.open", new_callable=mock_open) +@mock.patch("nftest.NFTestRunner.NFTestRunner", wraps=NFTestRunner) +def test_load_from_config( + mock_runner, mock_runner_open, mock_global, mock_validate_yaml, mock_yaml, mock_case +): + """Tests for loading from config file""" mock_validate_yaml.return_value = lambda x: True mock_global.return_value = lambda: None mock_runner.return_value.NFTestGlobal = lambda: None mock_yaml.return_value = { - 'global': {}, - 'cases': [ - {'name': 'case1', 'nf_config': None}, - {'name': 'case2', 'nf_config': None} - ] + "global": {}, + "cases": [ + {"name": "case1", "nf_config": None}, + {"name": "case2", "nf_config": None}, + ], } - mock_case.return_value = lambda **kwargs: kwargs['name'] + mock_case.return_value = lambda **kwargs: kwargs["name"] mock_case.return_value.combine_global = lambda x: None mock_runner.return_value.load_from_config = NFTestRunner.load_from_config runner = mock_runner() runner_data = RunnerData() - runner.load_from_config(runner_data, 'None', None) + runner.load_from_config(runner_data, "None", None) assert len(runner_data.cases) == 2 diff --git a/test/unit/test_common.py b/test/unit/test_common.py index 4ff2860..293d6e3 100644 --- a/test/unit/test_common.py +++ b/test/unit/test_common.py @@ -1,5 +1,5 @@ # pylint: disable=W0212 -''' Test module for common functions ''' +"""Test module for common functions""" import logging import mock @@ -7,18 +7,14 @@ from nftest.common import resolve_single_path, validate_reference + @pytest.mark.parametrize( - 'glob_return_value,case_pass', - [ - ([], False), - (['a', 'b'], False), - (['a'], True) - ] + "glob_return_value,case_pass", [([], False), (["a", "b"], False), (["a"], True)] ) -@mock.patch('glob.glob') +@mock.patch("glob.glob") def test_resolve_single_path(mock_glob, glob_return_value, case_pass): - ''' Tests for proper file identification ''' - test_path = '/some/path' + """Tests for proper file identification""" + test_path = "/some/path" mock_glob.return_value = glob_return_value if case_pass: @@ -27,70 +23,65 @@ def test_resolve_single_path(mock_glob, glob_return_value, case_pass): with pytest.raises(ValueError): resolve_single_path(test_path) + @pytest.mark.parametrize( - 'param_name,valid_name', + "param_name,valid_name", [ - ('bad name', False), - ('good_name', True), - ('bad#name', False), - ('validparam', True) - ] + ("bad name", False), + ("good_name", True), + ("bad#name", False), + ("validparam", True), + ], ) -@mock.patch('nftest.common.calculate_checksum') +@mock.patch("nftest.common.calculate_checksum") def test_param_names_validate_reference( - mock_calculate_checksum, - param_name, - valid_name): - ''' Tests for proper parameter name check ''' - mock_calculate_checksum.return_value = '' + mock_calculate_checksum, param_name, valid_name +): + """Tests for proper parameter name check""" + mock_calculate_checksum.return_value = "" if valid_name: - validate_reference(param_name, '', '', '') + validate_reference(param_name, "", "", "") else: with pytest.raises(ValueError): - validate_reference(param_name, '', '', '') - -@mock.patch('nftest.common.calculate_checksum') -def test_warning_with_bad_checksum_validate_reference( - mock_calculate_checksum, - caplog): - ''' Tests for warning message printed with bad checksum ''' - test_bad_checksum = 'bad_checksum' - test_param_name = 'name' - test_param_path = 'path' - test_checksum = 'checksum' - test_checksum_type = 'md5' + validate_reference(param_name, "", "", "") - mock_calculate_checksum.return_value = test_bad_checksum +@mock.patch("nftest.common.calculate_checksum") +def test_warning_with_bad_checksum_validate_reference(mock_calculate_checksum, caplog): + """Tests for warning message printed with bad checksum""" + test_bad_checksum = "bad_checksum" + test_param_name = "name" + test_param_path = "path" + test_checksum = "checksum" + test_checksum_type = "md5" + + mock_calculate_checksum.return_value = test_bad_checksum with caplog.at_level(logging.DEBUG): validate_reference( - test_param_name, - test_param_path, - test_checksum, - test_checksum_type + test_param_name, test_param_path, test_checksum, test_checksum_type ) - assert f'Checksum for reference file: ' \ - f'{test_param_name}={test_param_path} - `' \ - f'{test_bad_checksum}` does not match expected ' \ - f'checksum of `{test_checksum}`' in caplog.text + assert ( + f"Checksum for reference file: " + f"{test_param_name}={test_param_path} - `" + f"{test_bad_checksum}` does not match expected " + f"checksum of `{test_checksum}`" in caplog.text + ) + -@mock.patch('nftest.common.calculate_checksum') +@mock.patch("nftest.common.calculate_checksum") def test_returns_correct_tuple_validate_reference(mock_calculate_checksum): - ''' Tests for correct return tuple after validation ''' - test_param_name = 'name' - test_param_path = 'path' - test_checksum = 'checksum' - test_checksum_type = 'md5' + """Tests for correct return tuple after validation""" + test_param_name = "name" + test_param_path = "path" + test_checksum = "checksum" + test_checksum_type = "md5" mock_calculate_checksum.return_value = test_checksum validated_reference = validate_reference( - test_param_name, - test_param_path, - test_checksum, - test_checksum_type + test_param_name, test_param_path, test_checksum, test_checksum_type ) assert validated_reference == (test_param_name, test_param_path) diff --git a/test/unit/test_syslog.py b/test/unit/test_syslog.py index cce5964..ae757a5 100644 --- a/test/unit/test_syslog.py +++ b/test/unit/test_syslog.py @@ -1,4 +1,5 @@ """Test module for the syslog filter.""" + import logging from nftest.syslog import syslog_filter, LEVELS @@ -37,8 +38,7 @@ def test_syslog_filter(caplog): assert 130 % 8 == 2 assert LEVELS[2] == logging.CRITICAL - assert caplog.record_tuples[-1] == \ - ("nextflow", logging.CRITICAL, "Unable...") + assert caplog.record_tuples[-1] == ("nextflow", logging.CRITICAL, "Unable...") def test_syslog_filter_multline(caplog):