|
| 1 | +#!/usr/bin/env python |
| 2 | +# |
| 3 | +# testing.py |
| 4 | +""" |
| 5 | +Handy functions for testing code. |
| 6 | +
|
| 7 | +Requires `pytest <https://docs.pytest.org/en/stable/>`_ to be installed. |
| 8 | +""" |
| 9 | +# |
| 10 | +# Copyright © 2020 Dominic Davis-Foster <[email protected]> |
| 11 | +# |
| 12 | +# This program is free software; you can redistribute it and/or modify |
| 13 | +# it under the terms of the GNU Lesser General Public License as published by |
| 14 | +# the Free Software Foundation; either version 3 of the License, or |
| 15 | +# (at your option) any later version. |
| 16 | +# |
| 17 | +# This program is distributed in the hope that it will be useful, |
| 18 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 20 | +# GNU Lesser General Public License for more details. |
| 21 | +# |
| 22 | +# You should have received a copy of the GNU Lesser General Public License |
| 23 | +# along with this program; if not, write to the Free Software |
| 24 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
| 25 | +# MA 02110-1301, USA. |
| 26 | +# |
| 27 | + |
| 28 | +# stdlib |
| 29 | +import itertools |
| 30 | +import random |
| 31 | +from functools import lru_cache |
| 32 | +from typing import List, Sequence |
| 33 | + |
| 34 | +# 3rd party |
| 35 | +import pytest |
| 36 | +from _pytest.mark import MarkDecorator |
| 37 | + |
| 38 | +# this package |
| 39 | +from domdf_python_tools.utils import Len |
| 40 | + |
| 41 | + |
| 42 | +def testing_boolean_values( |
| 43 | + extra_truthy: Sequence = (), |
| 44 | + extra_falsy: Sequence = (), |
| 45 | + ) -> MarkDecorator: |
| 46 | + """ |
| 47 | + Returns a `pytest.mark.parametrize <https://docs.pytest.org/en/stable/parametrize.html>`_ |
| 48 | + decorator that provides a list of strings, integers and booleans, and the boolean representations of them. |
| 49 | +
|
| 50 | + The parametrized arguments are ``boolean_string`` for the input value, |
| 51 | + and ``expected_boolean`` for the expected output. |
| 52 | +
|
| 53 | + :param extra_truthy: Additional values that should be considered :py:obj:`True`. |
| 54 | + :param extra_falsy: Additional values that should be considered :py:obj:`False`. |
| 55 | + """ |
| 56 | + |
| 57 | + truthy = [ |
| 58 | + True, |
| 59 | + "True", |
| 60 | + "true", |
| 61 | + "tRUe", |
| 62 | + 'y', |
| 63 | + 'Y', |
| 64 | + "YES", |
| 65 | + "yes", |
| 66 | + "Yes", |
| 67 | + "yEs", |
| 68 | + "ON", |
| 69 | + "on", |
| 70 | + '1', |
| 71 | + 1, |
| 72 | + *extra_truthy, |
| 73 | + ] |
| 74 | + |
| 75 | + falsy = [ |
| 76 | + False, |
| 77 | + "False", |
| 78 | + "false", |
| 79 | + "falSE", |
| 80 | + 'n', |
| 81 | + 'N', |
| 82 | + "NO", |
| 83 | + "no", |
| 84 | + "nO", |
| 85 | + "OFF", |
| 86 | + "off", |
| 87 | + "oFF", |
| 88 | + '0', |
| 89 | + 0, |
| 90 | + *extra_falsy, |
| 91 | + ] |
| 92 | + |
| 93 | + boolean_strings = [ |
| 94 | + *itertools.zip_longest(truthy, [], fillvalue=True), |
| 95 | + *itertools.zip_longest(falsy, [], fillvalue=False), |
| 96 | + ] |
| 97 | + |
| 98 | + return pytest.mark.parametrize("boolean_string, expected_boolean", boolean_strings) |
| 99 | + |
| 100 | + |
| 101 | +whitespace = " \t\n\r" |
| 102 | + |
| 103 | + |
| 104 | +@lru_cache(1) |
| 105 | +def whitespace_perms_list() -> List[str]: |
| 106 | + chain = itertools.chain.from_iterable(itertools.permutations(whitespace, n) for n in Len(whitespace)) |
| 107 | + return list("".join(x) for x in chain) |
| 108 | + |
| 109 | + |
| 110 | +def whitespace_perms(ratio: float = 0.5) -> MarkDecorator: |
| 111 | + r""" |
| 112 | + Returns a `pytest.mark.parametrize <https://docs.pytest.org/en/stable/parametrize.html>`_ |
| 113 | + decorator that provides permutations of whitespace (strictly only ``␣\n\t\r``). |
| 114 | + Not all permutations are returned, as there are a lot of them; |
| 115 | + instead a random selection of the permutations is returned. |
| 116 | + By default ½ of the permutations are returned, but this can be configured using the ``ratio`` argument. |
| 117 | +
|
| 118 | + The single parametrized argument is ``char``. |
| 119 | +
|
| 120 | + :param ratio: The ratio of the number of permutations to select to the total number of permutations. |
| 121 | + """ |
| 122 | + |
| 123 | + perms = whitespace_perms_list() |
| 124 | + return pytest.mark.parametrize("char", random.sample(perms, int(len(perms) * ratio))) |
| 125 | + |
| 126 | + |
| 127 | +def count(stop: int, start: int = 0, step: int = 1) -> MarkDecorator: |
| 128 | + """ |
| 129 | + Returns a `pytest.mark.parametrize <https://docs.pytest.org/en/stable/parametrize.html>`_ |
| 130 | + decorator that provides a list of numbers between ``start`` and ``stop`` with an interval of ``step``. |
| 131 | +
|
| 132 | + The single parametrized argument is ``count``. |
| 133 | +
|
| 134 | + :param stop: The stop value passed to :class:`range`. |
| 135 | + :param start: The start value passed to :class:`range`. |
| 136 | + :param step: The step passed to :class:`range`. |
| 137 | + """ |
| 138 | + |
| 139 | + return pytest.mark.parametrize("count", range(start, stop, step)) |
0 commit comments