1f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings"""Test suite for statistics module, including helper NumericTestCase and
2f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsapprox_equal function.
3f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
4f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings"""
5f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
6f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport collections
7f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport decimal
8f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport doctest
9f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport math
10f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport random
11b12cb6a5509dbaafa05706dd64861bfef9fa42d7Serhiy Storchakaimport sys
12f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport unittest
13f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
14f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsfrom decimal import Decimal
15f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsfrom fractions import Fraction
16f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
17f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
18f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# Module to be tested.
19f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsimport statistics
20f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
21f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
22f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Helper functions and class ===
23f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
24a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Apranodef sign(x):
25a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    """Return -1.0 for negatives, including -0.0, otherwise +1.0."""
26a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    return math.copysign(1, x)
27a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
28b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Apranodef _nan_equal(a, b):
29b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    """Return True if a and b are both the same kind of NAN.
30b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
31b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(Decimal('NAN'), Decimal('NAN'))
32b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    True
33b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(Decimal('sNAN'), Decimal('sNAN'))
34b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    True
35b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(Decimal('NAN'), Decimal('sNAN'))
36b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    False
37b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(Decimal(42), Decimal('NAN'))
38b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    False
39b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
40b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(float('NAN'), float('NAN'))
41b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    True
42b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(float('NAN'), 0.5)
43b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    False
44b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
45b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    >>> _nan_equal(float('NAN'), Decimal('NAN'))
46b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    False
47b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
48b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    NAN payloads are not compared.
49b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    """
50b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    if type(a) is not type(b):
51b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        return False
52b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    if isinstance(a, float):
53b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        return math.isnan(a) and math.isnan(b)
54b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    aexp = a.as_tuple()[2]
55b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    bexp = b.as_tuple()[2]
56b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    return (aexp == bexp) and (aexp in ('n', 'N'))  # Both NAN or both sNAN.
57b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
58b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
59f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsdef _calc_errors(actual, expected):
60f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """Return the absolute and relative errors between two numbers.
61f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
62f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> _calc_errors(100, 75)
63f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    (25, 0.25)
64f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> _calc_errors(100, 100)
65f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    (0, 0.0)
66f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
67f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Returns the (absolute error, relative error) between the two arguments.
68f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """
69f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    base = max(abs(actual), abs(expected))
70f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    abs_err = abs(actual - expected)
71f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    rel_err = abs_err/base if base else float('inf')
72f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    return (abs_err, rel_err)
73f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
74f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
75f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsdef approx_equal(x, y, tol=1e-12, rel=1e-7):
76f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """approx_equal(x, y [, tol [, rel]]) => True|False
77f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
78f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Return True if numbers x and y are approximately equal, to within some
79f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    margin of error, otherwise return False. Numbers which compare equal
80f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    will also compare approximately equal.
81f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
82f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    x is approximately equal to y if the difference between them is less than
83f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    an absolute error tol or a relative error rel, whichever is bigger.
84f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
85f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    If given, both tol and rel must be finite, non-negative numbers. If not
86f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    given, default values are tol=1e-12 and rel=1e-7.
87f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
88f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(1.2589, 1.2587, tol=0.0003, rel=0)
89f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    True
90f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(1.2589, 1.2587, tol=0.0001, rel=0)
91f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    False
92f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
93f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Absolute error is defined as abs(x-y); if that is less than or equal to
94f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    tol, x and y are considered approximately equal.
95f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
96f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Relative error is defined as abs((x-y)/x) or abs((x-y)/y), whichever is
97f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    smaller, provided x or y are not zero. If that figure is less than or
98f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    equal to rel, x and y are considered approximately equal.
99f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
100f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Complex numbers are not directly supported. If you wish to compare to
101f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    complex numbers, extract their real and imaginary parts and compare them
102f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    individually.
103f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
104f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    NANs always compare unequal, even with themselves. Infinities compare
105f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    approximately equal if they have the same sign (both positive or both
106f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    negative). Infinities with different signs compare unequal; so do
107f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    comparisons of infinities with finite numbers.
108f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """
109f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    if tol < 0 or rel < 0:
110f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raise ValueError('error tolerances must be non-negative')
111f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # NANs are never equal to anything, approximately or otherwise.
112f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    if math.isnan(x) or math.isnan(y):
113f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return False
114f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Numbers which compare equal also compare approximately equal.
115f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    if x == y:
116f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # This includes the case of two infinities with the same sign.
117f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return True
118f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    if math.isinf(x) or math.isinf(y):
119f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # This includes the case of two infinities of opposite sign, or
120f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # one infinity and one finite number.
121f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return False
122f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Two finite numbers.
123f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    actual_error = abs(x - y)
124f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    allowed_error = max(tol, rel*max(abs(x), abs(y)))
125f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    return actual_error <= allowed_error
126f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
127f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
128f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# This class exists only as somewhere to stick a docstring containing
129f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# doctests. The following docstring and tests were originally in a separate
130f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# module. Now that it has been merged in here, I need somewhere to hang the.
131f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# docstring. Ultimately, this class will die, and the information below will
132f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# either become redundant, or be moved into more appropriate places.
133f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass _DoNothing:
134f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """
135f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    When doing numeric work, especially with floats, exact equality is often
136f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    not what you want. Due to round-off error, it is often a bad idea to try
137f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    to compare floats with equality. Instead the usual procedure is to test
138f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    them with some (hopefully small!) allowance for error.
139f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
140f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    The ``approx_equal`` function allows you to specify either an absolute
141f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    error tolerance, or a relative error, or both.
142f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
143f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Absolute error tolerances are simple, but you need to know the magnitude
144f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    of the quantities being compared:
145f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
146f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(12.345, 12.346, tol=1e-3)
147f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    True
148f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(12.345e6, 12.346e6, tol=1e-3)  # tol is too small.
149f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    False
150f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
151f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Relative errors are more suitable when the values you are comparing can
152f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    vary in magnitude:
153f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
154f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(12.345, 12.346, rel=1e-4)
155f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    True
156f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(12.345e6, 12.346e6, rel=1e-4)
157f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    True
158f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
159f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    but a naive implementation of relative error testing can run into trouble
160f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    around zero.
161f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
162f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    If you supply both an absolute tolerance and a relative error, the
163f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    comparison succeeds if either individual test succeeds:
164f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
165f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    >>> approx_equal(12.345e6, 12.346e6, tol=1e-3, rel=1e-4)
166f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    True
167f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
168f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """
169f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    pass
170f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
171f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
172f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
173f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# We prefer this for testing numeric values that may not be exactly equal,
174f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# and avoid using TestCase.assertAlmostEqual, because it sucks :-)
175f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
176f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass NumericTestCase(unittest.TestCase):
177f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """Unit test class for numeric work.
178f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
179f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    This subclasses TestCase. In addition to the standard method
180f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    ``TestCase.assertAlmostEqual``,  ``assertApproxEqual`` is provided.
181f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """
182f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # By default, we expect exact equality, unless overridden.
183f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    tol = rel = 0
184f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
185f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def assertApproxEqual(
186f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self, first, second, tol=None, rel=None, msg=None
187f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            ):
188f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """Test passes if ``first`` and ``second`` are approximately equal.
189f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
190f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        This test passes if ``first`` and ``second`` are equal to
191f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        within ``tol``, an absolute error, or ``rel``, a relative error.
192f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
193f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        If either ``tol`` or ``rel`` are None or not given, they default to
194f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        test attributes of the same name (by default, 0).
195f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
196f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        The objects may be either numbers, or sequences of numbers. Sequences
197f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        are tested element-by-element.
198f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
199f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        >>> class MyTest(NumericTestCase):
200f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...     def test_number(self):
201f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...         x = 1.0/6
202f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...         y = sum([x]*6)
203f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...         self.assertApproxEqual(y, 1.0, tol=1e-15)
204f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...     def test_sequence(self):
205f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...         a = [1.001, 1.001e-10, 1.001e10]
206f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...         b = [1.0, 1e-10, 1e10]
207f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...         self.assertApproxEqual(a, b, rel=1e-3)
208f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        ...
209f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        >>> import unittest
210f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        >>> from io import StringIO  # Suppress test runner output.
211f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        >>> suite = unittest.TestLoader().loadTestsFromTestCase(MyTest)
212f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        >>> unittest.TextTestRunner(stream=StringIO()).run(suite)
213f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        <unittest.runner.TextTestResult run=2 errors=0 failures=0>
214f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
215f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """
216f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if tol is None:
217f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            tol = self.tol
218f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if rel is None:
219f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            rel = self.rel
220f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if (
221f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                isinstance(first, collections.Sequence) and
222f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                isinstance(second, collections.Sequence)
223f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            ):
224f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            check = self._check_approx_seq
225f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        else:
226f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            check = self._check_approx_num
227f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check(first, second, tol, rel, msg)
228f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
229f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def _check_approx_seq(self, first, second, tol, rel, msg):
230f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if len(first) != len(second):
231f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            standardMsg = (
232f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                "sequences differ in length: %d items != %d items"
233f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                % (len(first), len(second))
234f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                )
235f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            msg = self._formatMessage(msg, standardMsg)
236f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            raise self.failureException(msg)
237f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for i, (a,e) in enumerate(zip(first, second)):
238f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self._check_approx_num(a, e, tol, rel, msg, i)
239f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
240f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def _check_approx_num(self, first, second, tol, rel, msg, idx=None):
241f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if approx_equal(first, second, tol, rel):
242f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            # Test passes. Return early, we are done.
243f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            return None
244f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Otherwise we failed.
245f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        standardMsg = self._make_std_err_msg(first, second, tol, rel, idx)
246f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        msg = self._formatMessage(msg, standardMsg)
247f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raise self.failureException(msg)
248f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
249f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    @staticmethod
250f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def _make_std_err_msg(first, second, tol, rel, idx):
251f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Create the standard error message for approx_equal failures.
252f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert first != second
253f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        template = (
254f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            '  %r != %r\n'
255f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            '  values differ by more than tol=%r and rel=%r\n'
256f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            '  -> absolute error = %r\n'
257f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            '  -> relative error = %r'
258f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            )
259f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if idx is not None:
260f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            header = 'numeric sequences first differ at index %d.\n' % idx
261f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            template = header + template
262f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Calculate actual errors:
263f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        abs_err, rel_err = _calc_errors(first, second)
264f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return template % (first, second, tol, rel, abs_err, rel_err)
265f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
266f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
267f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# ========================
268f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Test the helpers ===
269f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# ========================
270f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
271a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Apranoclass TestSign(unittest.TestCase):
272a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    """Test that the helper function sign() works correctly."""
273a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def testZeroes(self):
274a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that signed zeroes report their sign correctly.
275a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(sign(0.0), +1)
276a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(sign(-0.0), -1)
277a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
278f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
279f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# --- Tests for approx_equal ---
280f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
281f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass ApproxEqualSymmetryTest(unittest.TestCase):
282f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test symmetry of approx_equal.
283f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
284f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_relative_symmetry(self):
285f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Check that approx_equal treats relative error symmetrically.
286f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # (a-b)/a is usually not equal to (a-b)/b. Ensure that this
287f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # doesn't matter.
288f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #
289f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #   Note: the reason for this test is that an early version
290f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #   of approx_equal was not symmetric. A relative error test
291f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #   would pass, or fail, depending on which value was passed
292f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #   as the first argument.
293f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #
294f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        args1 = [2456, 37.8, -12.45, Decimal('2.54'), Fraction(17, 54)]
295f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        args2 = [2459, 37.2, -12.41, Decimal('2.59'), Fraction(15, 54)]
296f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(args1) == len(args2)
297f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for a, b in zip(args1, args2):
298f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_relative_symmetry(a, b)
299f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
300f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_relative_symmetry(self, a, b):
301f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        a, b = min(a, b), max(a, b)
302f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert a < b
303f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        delta = b - a  # The absolute difference between the values.
304f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        rel_err1, rel_err2 = abs(delta/a), abs(delta/b)
305f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Choose an error margin halfway between the two.
306f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        rel = (rel_err1 + rel_err2)/2
307f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Now see that values a and b compare approx equal regardless of
308f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # which is given first.
309f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(a, b, tol=0, rel=rel))
310f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(b, a, tol=0, rel=rel))
311f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
312f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_symmetry(self):
313f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that approx_equal(a, b) == approx_equal(b, a)
314f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        args = [-23, -2, 5, 107, 93568]
315f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        delta = 2
316ad39360a025185c7402838893861728a229d7d79Christian Heimes        for a in args:
317f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for type_ in (int, float, Decimal, Fraction):
318ad39360a025185c7402838893861728a229d7d79Christian Heimes                x = type_(a)*100
319f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                y = x + delta
320f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                r = abs(delta/max(x, y))
321f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                # There are five cases to check:
322f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                # 1) actual error <= tol, <= rel
323f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=delta, rel=r)
324f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=delta+1, rel=2*r)
325f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                # 2) actual error > tol, > rel
326f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=delta-1, rel=r/2)
327f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                # 3) actual error <= tol, > rel
328f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=delta, rel=r/2)
329f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                # 4) actual error > tol, <= rel
330f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=delta-1, rel=r)
331f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=delta-1, rel=2*r)
332f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                # 5) exact equality test
333f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, x, tol=0, rel=0)
334f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_symmetry_test(x, y, tol=0, rel=0)
335f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
336f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_symmetry_test(self, a, b, tol, rel):
337f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        template = "approx_equal comparisons don't match for %r"
338f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        flag1 = approx_equal(a, b, tol, rel)
339f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        flag2 = approx_equal(b, a, tol, rel)
340f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(flag1, flag2, template.format((a, b, tol, rel)))
341f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
342f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
343f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass ApproxEqualExactTest(unittest.TestCase):
344f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test the approx_equal function with exactly equal values.
345f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Equal values should compare as approximately equal.
346f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test cases for exactly equal values, which should compare approx
347f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # equal regardless of the error tolerances given.
348f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
349f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_exactly_equal_test(self, x, tol, rel):
350f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = approx_equal(x, x, tol=tol, rel=rel)
351f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(result, 'equality failure for x=%r' % x)
352f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = approx_equal(-x, -x, tol=tol, rel=rel)
353f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(result, 'equality failure for x=%r' % -x)
354f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
355f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_ints(self):
356f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal int values are exactly equal.
357f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for n in [42, 19740, 14974, 230, 1795, 700245, 36587]:
358f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(n, 0, 0)
359f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
360f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_floats(self):
361f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal float values are exactly equal.
362f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in [0.42, 1.9740, 1497.4, 23.0, 179.5, 70.0245, 36.587]:
363f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(x, 0, 0)
364f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
365f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_fractions(self):
366f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal Fraction values are exactly equal.
367f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
368f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for f in [F(1, 2), F(0), F(5, 3), F(9, 7), F(35, 36), F(3, 7)]:
369f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(f, 0, 0)
370f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
371f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_decimals(self):
372f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal Decimal values are exactly equal.
373f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
374f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for d in map(D, "8.2 31.274 912.04 16.745 1.2047".split()):
375f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(d, 0, 0)
376f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
377f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_absolute(self):
378f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal values are exactly equal with an absolute error.
379f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for n in [16, 1013, 1372, 1198, 971, 4]:
380f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            # Test as ints.
381f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(n, 0.01, 0)
382f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            # Test as floats.
383f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(n/10, 0.01, 0)
384f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            # Test as Fractions.
385f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            f = Fraction(n, 1234)
386f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(f, 0.01, 0)
387f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
388f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_absolute_decimals(self):
389f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test equal Decimal values are exactly equal with an absolute error.
390f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_exactly_equal_test(Decimal("3.571"), Decimal("0.01"), 0)
391f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_exactly_equal_test(-Decimal("81.3971"), Decimal("0.01"), 0)
392f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
393f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_relative(self):
394f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal values are exactly equal with a relative error.
395f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in [8347, 101.3, -7910.28, Fraction(5, 21)]:
396f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(x, 0, 0.01)
397f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_exactly_equal_test(Decimal("11.68"), 0, Decimal("0.01"))
398f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
399f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_equal_both(self):
400f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that equal values are equal when both tol and rel are given.
401f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in [41017, 16.742, -813.02, Fraction(3, 8)]:
402f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_equal_test(x, 0.1, 0.01)
403f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
404f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_exactly_equal_test(D("7.2"), D("0.1"), D("0.01"))
405f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
406f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
407f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass ApproxEqualUnequalTest(unittest.TestCase):
408f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Unequal values should compare unequal with zero error tolerances.
409f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test cases for unequal values, with exact equality test.
410f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
411f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_exactly_unequal_test(self, x):
412f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for a in (x, -x):
413f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            result = approx_equal(a, a+1, tol=0, rel=0)
414f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertFalse(result, 'inequality failure for x=%r' % a)
415f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
416f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_unequal_ints(self):
417f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test unequal int values are unequal with zero error tolerance.
418f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for n in [951, 572305, 478, 917, 17240]:
419f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_unequal_test(n)
420f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
421f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_unequal_floats(self):
422f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test unequal float values are unequal with zero error tolerance.
423f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in [9.51, 5723.05, 47.8, 9.17, 17.24]:
424f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_unequal_test(x)
425f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
426f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_unequal_fractions(self):
427f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that unequal Fractions are unequal with zero error tolerance.
428f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
429f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for f in [F(1, 5), F(7, 9), F(12, 11), F(101, 99023)]:
430f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_unequal_test(f)
431f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
432f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exactly_unequal_decimals(self):
433f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that unequal Decimals are unequal with zero error tolerance.
434f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for d in map(Decimal, "3.1415 298.12 3.47 18.996 0.00245".split()):
435f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_exactly_unequal_test(d)
436f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
437f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
438f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass ApproxEqualInexactTest(unittest.TestCase):
439f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Inexact test cases for approx_error.
440f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test cases when comparing two values that are not exactly equal.
441f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
442f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # === Absolute error tests ===
443f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
444f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_approx_equal_abs_test(self, x, delta):
445f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        template = "Test failure for x={!r}, y={!r}"
446f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for y in (x + delta, x - delta):
447f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            msg = template.format(x, y)
448f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(approx_equal(x, y, tol=2*delta, rel=0), msg)
449f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertFalse(approx_equal(x, y, tol=delta/2, rel=0), msg)
450f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
451f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_absolute_ints(self):
452f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of ints with an absolute error.
453f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for n in [-10737, -1975, -7, -2, 0, 1, 9, 37, 423, 9874, 23789110]:
454f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(n, 10)
455f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(n, 2)
456f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
457f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_absolute_floats(self):
458f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of floats with an absolute error.
459f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in [-284.126, -97.1, -3.4, -2.15, 0.5, 1.0, 7.8, 4.23, 3817.4]:
460f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(x, 1.5)
461f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(x, 0.01)
462f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(x, 0.0001)
463f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
464f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_absolute_fractions(self):
465f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of Fractions with an absolute error.
466f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        delta = Fraction(1, 29)
467f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        numerators = [-84, -15, -2, -1, 0, 1, 5, 17, 23, 34, 71]
468f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for f in (Fraction(n, 29) for n in numerators):
469f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(f, delta)
470f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(f, float(delta))
471f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
472f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_absolute_decimals(self):
473f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of Decimals with an absolute error.
474f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        delta = Decimal("0.01")
475f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for d in map(Decimal, "1.0 3.5 36.08 61.79 7912.3648".split()):
476f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(d, delta)
477f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_abs_test(-d, delta)
478f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
479f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_cross_zero(self):
480f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test for the case of the two values having opposite signs.
481f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(1e-5, -1e-5, tol=1e-4, rel=0))
482f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
483f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # === Relative error tests ===
484f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
485f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_approx_equal_rel_test(self, x, delta):
486f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        template = "Test failure for x={!r}, y={!r}"
487f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for y in (x*(1+delta), x*(1-delta)):
488f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            msg = template.format(x, y)
489f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(approx_equal(x, y, tol=0, rel=2*delta), msg)
490f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertFalse(approx_equal(x, y, tol=0, rel=delta/2), msg)
491f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
492f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_relative_ints(self):
493f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of ints with a relative error.
494f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(64, 47, tol=0, rel=0.36))
495f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(64, 47, tol=0, rel=0.37))
496f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # ---
497f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(449, 512, tol=0, rel=0.125))
498f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(448, 512, tol=0, rel=0.125))
499f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertFalse(approx_equal(447, 512, tol=0, rel=0.125))
500f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
501f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_relative_floats(self):
502f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of floats with a relative error.
503f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in [-178.34, -0.1, 0.1, 1.0, 36.97, 2847.136, 9145.074]:
504f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_rel_test(x, 0.02)
505f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_rel_test(x, 0.0001)
506f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
507f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_relative_fractions(self):
508f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of Fractions with a relative error.
509f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
510f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        delta = Fraction(3, 8)
511f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for f in [F(3, 84), F(17, 30), F(49, 50), F(92, 85)]:
512f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for d in (delta, float(delta)):
513f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_approx_equal_rel_test(f, d)
514f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.do_approx_equal_rel_test(-f, d)
515f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
516f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_relative_decimals(self):
517f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test approximate equality of Decimals with a relative error.
518f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for d in map(Decimal, "0.02 1.0 5.7 13.67 94.138 91027.9321".split()):
519f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_rel_test(d, Decimal("0.001"))
520f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_approx_equal_rel_test(-d, Decimal("0.05"))
521f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
522f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # === Both absolute and relative error tests ===
523f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
524f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # There are four cases to consider:
525f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    #   1) actual error <= both absolute and relative error
526f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    #   2) actual error <= absolute error but > relative error
527f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    #   3) actual error <= relative error but > absolute error
528f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    #   4) actual error > both absolute and relative error
529f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
530f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_check_both(self, a, b, tol, rel, tol_flag, rel_flag):
531f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check = self.assertTrue if tol_flag else self.assertFalse
532f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check(approx_equal(a, b, tol=tol, rel=0))
533f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check = self.assertTrue if rel_flag else self.assertFalse
534f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check(approx_equal(a, b, tol=0, rel=rel))
535f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check = self.assertTrue if (tol_flag or rel_flag) else self.assertFalse
536f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        check(approx_equal(a, b, tol=tol, rel=rel))
537f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
538f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_both1(self):
539f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test actual error <= both absolute and relative error.
540f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_check_both(7.955, 7.952, 0.004, 3.8e-4, True, True)
541f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_check_both(-7.387, -7.386, 0.002, 0.0002, True, True)
542f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
543f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_both2(self):
544f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test actual error <= absolute error but > relative error.
545f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_check_both(7.955, 7.952, 0.004, 3.7e-4, True, False)
546f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
547f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_both3(self):
548f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test actual error <= relative error but > absolute error.
549f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_check_both(7.955, 7.952, 0.001, 3.8e-4, False, True)
550f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
551f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_approx_equal_both4(self):
552f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test actual error > both absolute and relative error.
553f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_check_both(2.78, 2.75, 0.01, 0.001, False, False)
554f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_check_both(971.44, 971.47, 0.02, 3e-5, False, False)
555f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
556f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
557f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass ApproxEqualSpecialsTest(unittest.TestCase):
558f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test approx_equal with NANs and INFs and zeroes.
559f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
560f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_inf(self):
561f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for type_ in (float, Decimal):
562f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            inf = type_('inf')
563f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(approx_equal(inf, inf))
564f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(approx_equal(inf, inf, 0, 0))
565f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(approx_equal(inf, inf, 1, 0.01))
566f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(approx_equal(-inf, -inf))
567f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertFalse(approx_equal(inf, -inf))
568f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertFalse(approx_equal(inf, 1000))
569f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
570f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_nan(self):
571f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for type_ in (float, Decimal):
572f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            nan = type_('nan')
573f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for other in (nan, type_('inf'), 1000):
574f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.assertFalse(approx_equal(nan, other))
575f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
576f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_float_zeroes(self):
577f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        nzero = math.copysign(0.0, -1)
578f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(nzero, 0.0, tol=0.1, rel=0.1))
579f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
580f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimal_zeroes(self):
581f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        nzero = Decimal("-0.0")
582f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(approx_equal(nzero, Decimal(0), tol=0.1, rel=0.1))
583f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
584f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
585f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestApproxEqualErrors(unittest.TestCase):
586f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test error conditions of approx_equal.
587f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
588f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_bad_tol(self):
589f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test negative tol raises.
590f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(ValueError, approx_equal, 100, 100, -1, 0.1)
591f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
592f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_bad_rel(self):
593f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test negative rel raises.
594f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(ValueError, approx_equal, 100, 100, 1, -0.1)
595f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
596f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
597f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# --- Tests for NumericTestCase ---
598f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
599f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# The formatting routine that generates the error messages is complex enough
600f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# that it too needs testing.
601f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
602f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestNumericTestCase(unittest.TestCase):
603f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # The exact wording of NumericTestCase error messages is *not* guaranteed,
604f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # but we need to give them some sort of test to ensure that they are
605f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # generated correctly. As a compromise, we look for specific substrings
606f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # that are expected to be found even if the overall error message changes.
607f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
608f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_test(self, args):
609f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        actual_msg = NumericTestCase._make_std_err_msg(*args)
610f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.generate_substrings(*args)
611f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for substring in expected:
612f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertIn(substring, actual_msg)
613f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
614f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_numerictestcase_is_testcase(self):
615f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Ensure that NumericTestCase actually is a TestCase.
616f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(issubclass(NumericTestCase, unittest.TestCase))
617f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
618f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_error_msg_numeric(self):
619f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test the error message generated for numeric comparisons.
620f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        args = (2.5, 4.0, 0.5, 0.25, None)
621f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_test(args)
622f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
623f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_error_msg_sequence(self):
624f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test the error message generated for sequence comparisons.
625f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        args = (3.75, 8.25, 1.25, 0.5, 7)
626f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.do_test(args)
627f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
628f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def generate_substrings(self, first, second, tol, rel, idx):
629f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """Return substrings we expect to see in error messages."""
630f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        abs_err, rel_err = _calc_errors(first, second)
631f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        substrings = [
632f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                'tol=%r' % tol,
633f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                'rel=%r' % rel,
634f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                'absolute error = %r' % abs_err,
635f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                'relative error = %r' % rel_err,
636f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                ]
637f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if idx is not None:
638f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            substrings.append('differ at index %d' % idx)
639f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return substrings
640f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
641f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
642f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# =======================================
643f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Tests for the statistics module ===
644f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# =======================================
645f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
646f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
647f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass GlobalsTest(unittest.TestCase):
648f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    module = statistics
649f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    expected_metadata = ["__doc__", "__all__"]
650f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
651f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_meta(self):
652f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test for the existence of metadata.
653f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for meta in self.expected_metadata:
654f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(hasattr(self.module, meta),
655f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                            "%s not present" % meta)
656f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
657f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_check_all(self):
658f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Check everything in __all__ exists and is public.
659f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        module = self.module
660f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for name in module.__all__:
661f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            # No private names in __all__:
662f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertFalse(name.startswith("_"),
663f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                             'private name "%s" in __all__' % name)
664f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            # And anything in __all__ must exist:
665f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(hasattr(module, name),
666f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                            'missing name "%s" in __all__' % name)
667f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
668f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
669f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass DocTests(unittest.TestCase):
670b12cb6a5509dbaafa05706dd64861bfef9fa42d7Serhiy Storchaka    @unittest.skipIf(sys.flags.optimize >= 2,
671b12cb6a5509dbaafa05706dd64861bfef9fa42d7Serhiy Storchaka                     "Docstrings are omitted with -OO and above")
672f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_doc_tests(self):
673a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        failed, tried = doctest.testmod(statistics, optionflags=doctest.ELLIPSIS)
674f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertGreater(tried, 0)
675f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(failed, 0)
676f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
677f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass StatisticsErrorTest(unittest.TestCase):
678f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_has_exception(self):
679f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        errmsg = (
680f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                "Expected StatisticsError to be a ValueError, but got a"
681f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                " subclass of %r instead."
682f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                )
683f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(hasattr(statistics, 'StatisticsError'))
684f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(
685f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                issubclass(statistics.StatisticsError, ValueError),
686f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                errmsg % statistics.StatisticsError.__base__
687f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                )
688f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
689f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
690f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Tests for private utility functions ===
691f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
692f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass ExactRatioTest(unittest.TestCase):
693f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test _exact_ratio utility.
694f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
695f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_int(self):
696f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for i in (-20, -3, 0, 5, 99, 10**20):
697f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(statistics._exact_ratio(i), (i, 1))
698f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
699f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_fraction(self):
700f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        numerators = (-5, 1, 12, 38)
701f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for n in numerators:
702f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            f = Fraction(n, 37)
703f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(statistics._exact_ratio(f), (n, 37))
704f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
705f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_float(self):
706f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(statistics._exact_ratio(0.125), (1, 8))
707f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(statistics._exact_ratio(1.125), (9, 8))
708f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(-100, 100) for _ in range(100)]
709f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in data:
710f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            num, den = statistics._exact_ratio(x)
711f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(x, num/den)
712f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
713f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimal(self):
714f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
715f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        _exact_ratio = statistics._exact_ratio
7163b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        self.assertEqual(_exact_ratio(D("0.125")), (1, 8))
7173b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        self.assertEqual(_exact_ratio(D("12.345")), (2469, 200))
7183b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        self.assertEqual(_exact_ratio(D("-1.98")), (-99, 50))
719f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
720b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_inf(self):
721b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        INF = float("INF")
722b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyFloat(float):
723b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            pass
724b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyDecimal(Decimal):
725b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            pass
726b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for inf in (INF, -INF):
727b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            for type_ in (float, MyFloat, Decimal, MyDecimal):
728b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                x = type_(inf)
729b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                ratio = statistics._exact_ratio(x)
730b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                self.assertEqual(ratio, (x, None))
731b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                self.assertEqual(type(ratio[0]), type_)
732b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                self.assertTrue(math.isinf(ratio[0]))
733b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
734b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_float_nan(self):
735b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        NAN = float("NAN")
736b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyFloat(float):
737b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            pass
738b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for nan in (NAN, MyFloat(NAN)):
739b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            ratio = statistics._exact_ratio(nan)
740b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertTrue(math.isnan(ratio[0]))
741b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertIs(ratio[1], None)
742b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(type(ratio[0]), type(nan))
743b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
744b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_decimal_nan(self):
745b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        NAN = Decimal("NAN")
746b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        sNAN = Decimal("sNAN")
747b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyDecimal(Decimal):
748b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            pass
749b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for nan in (NAN, MyDecimal(NAN), sNAN, MyDecimal(sNAN)):
750b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            ratio = statistics._exact_ratio(nan)
751b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertTrue(_nan_equal(ratio[0], nan))
752b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertIs(ratio[1], None)
753b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(type(ratio[0]), type(nan))
754b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
755f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
756f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass DecimalToRatioTest(unittest.TestCase):
7573b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano    # Test _exact_ratio private function.
758f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
759b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_infinity(self):
760b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test that INFs are handled correctly.
761b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        inf = Decimal('INF')
7623b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        self.assertEqual(statistics._exact_ratio(inf), (inf, None))
7633b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        self.assertEqual(statistics._exact_ratio(-inf), (-inf, None))
764b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
765b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_nan(self):
766b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test that NANs are handled correctly.
767b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for nan in (Decimal('NAN'), Decimal('sNAN')):
7683b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano            num, den = statistics._exact_ratio(nan)
769b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            # Because NANs always compare non-equal, we cannot use assertEqual.
770b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            # Nor can we use an identity test, as we don't guarantee anything
771b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            # about the object identity.
772b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertTrue(_nan_equal(num, nan))
773b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertIs(den, None)
774f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
7754a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan    def test_sign(self):
7764a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # Test sign is calculated correctly.
7774a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        numbers = [Decimal("9.8765e12"), Decimal("9.8765e-12")]
7784a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        for d in numbers:
7794a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            # First test positive decimals.
7804a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            assert d > 0
7813b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano            num, den = statistics._exact_ratio(d)
7824a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            self.assertGreaterEqual(num, 0)
7834a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            self.assertGreater(den, 0)
7844a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            # Then test negative decimals.
7853b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano            num, den = statistics._exact_ratio(-d)
7864a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            self.assertLessEqual(num, 0)
7874a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan            self.assertGreater(den, 0)
7884a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan
7894a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan    def test_negative_exponent(self):
7904a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # Test result when the exponent is negative.
7913b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        t = statistics._exact_ratio(Decimal("0.1234"))
7923b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        self.assertEqual(t, (617, 5000))
7934a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan
7944a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan    def test_positive_exponent(self):
7954a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # Test results when the exponent is positive.
7963b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        t = statistics._exact_ratio(Decimal("1.234e7"))
7974a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        self.assertEqual(t, (12340000, 1))
7984a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan
7994a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan    def test_regression_20536(self):
8004a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # Regression test for issue 20536.
8014a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # See http://bugs.python.org/issue20536
8023b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        t = statistics._exact_ratio(Decimal("1e2"))
8034a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        self.assertEqual(t, (100, 1))
8043b06e243527da5f4ca4dc2e3126dc9f5bbdc243cSteven D'Aprano        t = statistics._exact_ratio(Decimal("1.47e5"))
8054a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        self.assertEqual(t, (147000, 1))
8064a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan
807f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
808b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Apranoclass IsFiniteTest(unittest.TestCase):
809b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # Test _isfinite private function.
810b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
811b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_finite(self):
812b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test that finite numbers are recognised as finite.
813b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for x in (5, Fraction(1, 3), 2.5, Decimal("5.5")):
814b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertTrue(statistics._isfinite(x))
81573afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan
816b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_infinity(self):
817b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test that INFs are not recognised as finite.
818b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for x in (float("inf"), Decimal("inf")):
819b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertFalse(statistics._isfinite(x))
820b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
821b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_nan(self):
822b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test that NANs are not recognised as finite.
823b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for x in (float("nan"), Decimal("NAN"), Decimal("sNAN")):
824b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertFalse(statistics._isfinite(x))
825b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
826b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
827b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Apranoclass CoerceTest(unittest.TestCase):
828b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # Test that private function _coerce correctly deals with types.
829b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
830b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # The coercion rules are currently an implementation detail, although at
831b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # some point that should change. The tests and comments here define the
832b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # correct implementation.
833b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
834b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # Pre-conditions of _coerce:
835b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #
836b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #   - The first time _sum calls _coerce, the
837b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #   - coerce(T, S) will never be called with bool as the first argument;
838b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #     this is a pre-condition, guarded with an assertion.
839b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
840b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #
841b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #   - coerce(T, T) will always return T; we assume T is a valid numeric
842b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #     type. Violate this assumption at your own risk.
843b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #
844b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #   - Apart from as above, bool is treated as if it were actually int.
845b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #
846b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #   - coerce(int, X) and coerce(X, int) return X.
847b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    #   -
848b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_bool(self):
849b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # bool is somewhat special, due to the pre-condition that it is
850b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # never given as the first argument to _coerce, and that it cannot
851b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # be subclassed. So we test it specially.
852b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for T in (int, float, Fraction, Decimal):
853b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertIs(statistics._coerce(T, bool), T)
854b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            class MyClass(T): pass
855b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertIs(statistics._coerce(MyClass, bool), MyClass)
856b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
857b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def assertCoerceTo(self, A, B):
858b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        """Assert that type A coerces to B."""
859b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertIs(statistics._coerce(A, B), B)
860b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertIs(statistics._coerce(B, A), B)
861b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
862b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def check_coerce_to(self, A, B):
863b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        """Checks that type A coerces to B, including subclasses."""
864b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Assert that type A is coerced to B.
865b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceTo(A, B)
866b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Subclasses of A are also coerced to B.
867b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class SubclassOfA(A): pass
868b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceTo(SubclassOfA, B)
869b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # A, and subclasses of A, are coerced to subclasses of B.
870b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class SubclassOfB(B): pass
871b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceTo(A, SubclassOfB)
872b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceTo(SubclassOfA, SubclassOfB)
873b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
874b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def assertCoerceRaises(self, A, B):
875b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        """Assert that coercing A to B, or vice versa, raises TypeError."""
876b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertRaises(TypeError, statistics._coerce, (A, B))
877b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertRaises(TypeError, statistics._coerce, (B, A))
878b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
879b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def check_type_coercions(self, T):
880b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        """Check that type T coerces correctly with subclasses of itself."""
881b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        assert T is not bool
882b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Coercing a type with itself returns the same type.
883b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertIs(statistics._coerce(T, T), T)
884b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Coercing a type with a subclass of itself returns the subclass.
885b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class U(T): pass
886b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class V(T): pass
887b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class W(U): pass
888b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for typ in (U, V, W):
889b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertCoerceTo(T, typ)
890b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceTo(U, W)
891b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Coercing two subclasses that aren't parent/child is an error.
892b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceRaises(U, V)
893b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertCoerceRaises(V, W)
89473afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan
895b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_int(self):
896b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Check that int coerces correctly.
897b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_type_coercions(int)
898b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for typ in (float, Fraction, Decimal):
899b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.check_coerce_to(int, typ)
90073afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan
901b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_fraction(self):
902b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Check that Fraction coerces correctly.
903b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_type_coercions(Fraction)
904b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_coerce_to(Fraction, float)
905b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
906b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_decimal(self):
907b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Check that Decimal coerces correctly.
908b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_type_coercions(Decimal)
909b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
910b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_float(self):
911b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Check that float coerces correctly.
912b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_type_coercions(float)
913b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
914b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_non_numeric_types(self):
915b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for bad_type in (str, list, type(None), tuple, dict):
916b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            for good_type in (int, float, Fraction, Decimal):
917b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                self.assertCoerceRaises(good_type, bad_type)
918b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
919b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_incompatible_types(self):
920b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test that incompatible types raise.
921b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for T in (float, Fraction):
922b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            class MySubclass(T): pass
923b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertCoerceRaises(T, Decimal)
924b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertCoerceRaises(MySubclass, Decimal)
925b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
926b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
927b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Apranoclass ConvertTest(unittest.TestCase):
928b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # Test private _convert function.
929b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
930b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def check_exact_equal(self, x, y):
931b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        """Check that x equals y, and has the same type as well."""
932b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(x, y)
933b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertIs(type(x), type(y))
934b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
935b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_int(self):
936b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test conversions to int.
937b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(71), int)
938b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, 71)
939b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyInt(int): pass
940b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(17), MyInt)
941b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, MyInt(17))
942b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
943b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_fraction(self):
944b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test conversions to Fraction.
945b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(95, 99), Fraction)
946b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, Fraction(95, 99))
947b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyFraction(Fraction):
948b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            def __truediv__(self, other):
949b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                return self.__class__(super().__truediv__(other))
950b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(71, 13), MyFraction)
951b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, MyFraction(71, 13))
952b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
953b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_float(self):
954b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test conversions to float.
955b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(-1, 2), float)
956b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, -0.5)
957b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyFloat(float):
958b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            def __truediv__(self, other):
959b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                return self.__class__(super().__truediv__(other))
960b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(9, 8), MyFloat)
961b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, MyFloat(1.125))
962b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
963b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_decimal(self):
964b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Test conversions to Decimal.
965b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(1, 40), Decimal)
966b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, Decimal("0.025"))
967b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        class MyDecimal(Decimal):
968b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            def __truediv__(self, other):
969b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                return self.__class__(super().__truediv__(other))
970b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        x = statistics._convert(Fraction(-15, 16), MyDecimal)
971b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.check_exact_equal(x, MyDecimal("-0.9375"))
972b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
973b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_inf(self):
974b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for INF in (float('inf'), Decimal('inf')):
975b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            for inf in (INF, -INF):
976b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                x = statistics._convert(inf, type(inf))
977b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                self.check_exact_equal(x, inf)
978b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
979b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_nan(self):
980b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for nan in (float('nan'), Decimal('NAN'), Decimal('sNAN')):
981b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            x = statistics._convert(nan, type(nan))
982b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertTrue(_nan_equal(x, nan))
98373afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan
984f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
985a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Apranoclass FailNegTest(unittest.TestCase):
986a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    """Test _fail_neg private function."""
987a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
988a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_pass_through(self):
989a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that values are passed through unchanged.
990a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        values = [1, 2.0, Fraction(3), Decimal(4)]
991a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        new = list(statistics._fail_neg(values))
992a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(values, new)
993a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
994a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_negatives_raise(self):
995a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that negatives raise an exception.
996a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        for x in [1, 2.0, Fraction(3), Decimal(4)]:
997a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            seq = [-x]
998a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            it = statistics._fail_neg(seq)
999a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            self.assertRaises(statistics.StatisticsError, next, it)
1000a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1001a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_error_msg(self):
1002a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that a given error message is used.
1003a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        msg = "badness #%d" % random.randint(10000, 99999)
1004a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        try:
1005a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            next(statistics._fail_neg([-1], msg))
1006a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        except statistics.StatisticsError as e:
1007a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            errmsg = e.args[0]
1008a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        else:
1009a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            self.fail("expected exception, but it didn't happen")
1010a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(errmsg, msg)
1011a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1012a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1013f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Tests for public functions ===
1014f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1015f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass UnivariateCommonMixin:
1016f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Common tests for most univariate functions that take a data argument.
1017f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1018f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_no_args(self):
1019f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Fail if given no arguments.
1020f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func)
1021f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1022f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_empty_data(self):
1023f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Fail when the data argument (first argument) is empty.
1024f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for empty in ([], (), iter([])):
1025f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertRaises(statistics.StatisticsError, self.func, empty)
1026f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1027f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def prepare_data(self):
1028f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """Return int data for various tests."""
1029f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = list(range(10))
1030f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        while data == sorted(data):
1031f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            random.shuffle(data)
1032f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return data
1033f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1034f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_no_inplace_modifications(self):
1035f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that the function does not modify its input data.
1036f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = self.prepare_data()
1037f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data) != 1  # Necessary to avoid infinite loop.
1038f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert data != sorted(data)
1039f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        saved = data[:]
1040f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert data is not saved
1041f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        _ = self.func(data)
1042f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertListEqual(data, saved, "data has been modified")
1043f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1044f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_order_doesnt_matter(self):
1045f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that the order of data points doesn't change the result.
1046f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1047f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # CAUTION: due to floating point rounding errors, the result actually
1048f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # may depend on the order. Consider this test representing an ideal.
1049f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # To avoid this test failing, only test with exact values such as ints
1050f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # or Fractions.
1051f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, 3, 3, 3, 4, 5, 6]*100
1052f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(data)
1053f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1054f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        actual = self.func(data)
1055f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(expected, actual)
1056f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1057f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_type_of_data_collection(self):
1058f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that the type of iterable data doesn't effect the result.
1059f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        class MyList(list):
1060f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            pass
1061f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        class MyTuple(tuple):
1062f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            pass
1063f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        def generator(data):
1064f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            return (obj for obj in data)
1065f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = self.prepare_data()
1066f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(data)
1067f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for kind in (list, tuple, iter, MyList, MyTuple, generator):
1068f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            result = self.func(kind(data))
1069f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(result, expected)
1070f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1071f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_range_data(self):
1072f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that functions work with range objects.
1073f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = range(20, 50, 3)
1074f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(list(data))
1075f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), expected)
1076f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1077f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_bad_arg_types(self):
1078f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that function raises when given data of the wrong type.
1079f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1080f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Don't roll the following into a loop like this:
1081f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #   for bad in list_of_bad:
1082f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #       self.check_for_type_error(bad)
1083f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #
1084f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Since assertRaises doesn't show the arguments that caused the test
1085f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # failure, it is very difficult to debug these test failures when the
1086f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # following are in a loop.
1087f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.check_for_type_error(None)
1088f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.check_for_type_error(23)
1089f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.check_for_type_error(42.0)
1090f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.check_for_type_error(object())
1091f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1092f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def check_for_type_error(self, *args):
1093f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func, *args)
1094f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1095f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_type_of_data_element(self):
1096f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Check the type of data elements doesn't affect the numeric result.
1097f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # This is a weaker test than UnivariateTypeMixin.testTypesConserved,
1098f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # because it checks the numeric result by equality, but not by type.
1099f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        class MyFloat(float):
1100f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __truediv__(self, other):
1101f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__truediv__(other))
1102f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __add__(self, other):
1103f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__add__(other))
1104f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            __radd__ = __add__
1105f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1106f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raw = self.prepare_data()
1107f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(raw)
1108f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for kind in (float, MyFloat, Decimal, Fraction):
1109f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            data = [kind(x) for x in raw]
1110f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            result = type(expected)(self.func(data))
1111f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(result, expected)
1112f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1113f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1114f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass UnivariateTypeMixin:
1115f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """Mixin class for type-conserving functions.
1116f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1117f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    This mixin class holds test(s) for functions which conserve the type of
1118f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    individual data points. E.g. the mean of a list of Fractions should itself
1119f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    be a Fraction.
1120f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1121f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    Not all tests to do with types need go in this class. Only those that
1122f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    rely on the function returning the same type as its input data.
1123f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """
1124a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def prepare_types_for_conservation_test(self):
1125a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        """Return the types which are expected to be conserved."""
1126f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        class MyFloat(float):
1127f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __truediv__(self, other):
1128f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__truediv__(other))
1129a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            def __rtruediv__(self, other):
1130a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano                return type(self)(super().__rtruediv__(other))
1131f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __sub__(self, other):
1132f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__sub__(other))
1133f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __rsub__(self, other):
1134f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__rsub__(other))
1135f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __pow__(self, other):
1136f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__pow__(other))
1137f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            def __add__(self, other):
1138f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                return type(self)(super().__add__(other))
1139f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            __radd__ = __add__
1140a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        return (float, Decimal, Fraction, MyFloat)
1141f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1142a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_types_conserved(self):
1143a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that functions keeps the same type as their data points.
1144a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # (Excludes mixed data types.) This only tests the type of the return
1145a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # result, not the value.
1146f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = self.prepare_data()
1147a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        for kind in self.prepare_types_for_conservation_test():
1148f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            d = [kind(x) for x in data]
1149f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            result = self.func(d)
1150f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertIs(type(result), kind)
1151f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1152f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1153b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Apranoclass TestSumCommon(UnivariateCommonMixin, UnivariateTypeMixin):
1154b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # Common test cases for statistics._sum() function.
1155b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
1156b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # This test suite looks only at the numeric value returned by _sum,
1157b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # after conversion to the appropriate type.
1158b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def setUp(self):
1159b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        def simplified_sum(*args):
1160b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            T, value, n = statistics._sum(*args)
1161b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            return statistics._coerce(value, T)
1162b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.func = simplified_sum
1163b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
1164b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
1165b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Apranoclass TestSum(NumericTestCase):
1166f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test cases for statistics._sum() function.
1167f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1168b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    # These tests look at the entire three value tuple returned by _sum.
1169b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
1170f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1171f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics._sum
1172f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1173f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_empty_data(self):
1174f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Override test for empty data.
1175f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for data in ([], (), iter([])):
1176b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(self.func(data), (int, Fraction(0), 0))
1177b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(self.func(data, 23), (int, Fraction(23), 0))
1178b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(self.func(data, 2.3), (float, Fraction(2.3), 0))
1179f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1180f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_ints(self):
1181b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(self.func([1, 5, 3, -4, -8, 20, 42, 1]),
1182b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (int, Fraction(60), 8))
1183b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(self.func([4, 2, 3, -8, 7], 1000),
1184b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (int, Fraction(1008), 5))
1185f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1186f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_floats(self):
1187b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(self.func([0.25]*20),
1188b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (float, Fraction(5.0), 20))
1189b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(self.func([0.125, 0.25, 0.5, 0.75], 1.5),
1190b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (float, Fraction(3.125), 4))
1191f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1192f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_fractions(self):
1193b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(self.func([Fraction(1, 1000)]*500),
1194b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (Fraction, Fraction(1, 2), 500))
1195f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1196f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimals(self):
1197f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1198f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D("0.001"), D("5.246"), D("1.702"), D("-0.025"),
1199f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                D("3.974"), D("2.328"), D("4.617"), D("2.843"),
1200f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                ]
1201b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(self.func(data),
1202b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (Decimal, Decimal("20.686"), 8))
1203f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1204f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_compare_with_math_fsum(self):
1205f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Compare with the math.fsum function.
1206f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Ideally we ought to get the exact same result, but sometimes
1207f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # we differ by a very slight amount :-(
1208f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(-100, 1000) for _ in range(1000)]
1209b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertApproxEqual(float(self.func(data)[1]), math.fsum(data), rel=2e-16)
1210f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1211f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_start_argument(self):
1212f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that the optional start argument works correctly.
1213f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(1, 1000) for _ in range(100)]
1214b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        t = self.func(data)[1]
1215b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(t+42, self.func(data, 42)[1])
1216b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(t-23, self.func(data, -23)[1])
1217b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(t+Fraction(1e20), self.func(data, 1e20)[1])
1218f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1219f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_strings_fail(self):
1220f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Sum of strings should fail.
1221f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func, [1, 2, 3], '999')
1222f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func, [1, 2, 3, '999'])
1223f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1224f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_bytes_fail(self):
1225f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Sum of bytes should fail.
1226f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func, [1, 2, 3], b'999')
1227f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func, [1, 2, 3, b'999'])
1228f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1229f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_mixed_sum(self):
123073afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan        # Mixed input types are not (currently) allowed.
123173afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan        # Check that mixed data types fail.
1232b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertRaises(TypeError, self.func, [1, 2.0, Decimal(1)])
123373afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan        # And so does mixed start argument.
123473afe2a972e30a3e0f87401be2fa38c67e2cb964Nick Coghlan        self.assertRaises(TypeError, self.func, [1, 2.0], Decimal(1))
1235f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1236f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1237f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass SumTortureTest(NumericTestCase):
1238f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_torture(self):
1239f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Tim Peters' torture test for sum, and variants of same.
1240b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(statistics._sum([1, 1e100, 1, -1e100]*10000),
1241b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (float, Fraction(20000.0), 40000))
1242b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(statistics._sum([1e100, 1, 1, -1e100]*10000),
1243b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano                         (float, Fraction(20000.0), 40000))
1244b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        T, num, count = statistics._sum([1e-100, 1, 1e-100, -1]*10000)
1245b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertIs(T, float)
1246b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(count, 40000)
1247b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertApproxEqual(float(num), 2.0e-96, rel=5e-16)
1248f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1249f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1250f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass SumSpecialValues(NumericTestCase):
1251f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test that sum works correctly with IEEE-754 special values.
1252f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1253f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_nan(self):
1254f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for type_ in (float, Decimal):
1255f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            nan = type_('nan')
1256b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            result = statistics._sum([1, nan, 2])[1]
1257f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertIs(type(result), type_)
1258f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(math.isnan(result))
1259f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1260f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def check_infinity(self, x, inf):
1261f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """Check x is an infinity of the same type and sign as inf."""
1262f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(math.isinf(x))
1263f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertIs(type(x), type(inf))
1264f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(x > 0, inf > 0)
1265f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert x == inf
1266f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1267f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def do_test_inf(self, inf):
1268f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Adding a single infinity gives infinity.
1269b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        result = statistics._sum([1, 2, inf, 3])[1]
1270f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.check_infinity(result, inf)
1271f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Adding two infinities of the same sign also gives infinity.
1272b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        result = statistics._sum([1, 2, inf, 3, inf, 4])[1]
1273f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.check_infinity(result, inf)
1274f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1275f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_float_inf(self):
1276f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        inf = float('inf')
1277f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for sign in (+1, -1):
1278f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_test_inf(sign*inf)
1279f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1280f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimal_inf(self):
1281f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        inf = Decimal('inf')
1282f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for sign in (+1, -1):
1283f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.do_test_inf(sign*inf)
1284f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1285f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_float_mismatched_infs(self):
1286f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that adding two infinities of opposite sign gives a NAN.
1287f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        inf = float('inf')
1288b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        result = statistics._sum([1, 2, inf, 3, -inf, 4])[1]
1289f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(math.isnan(result))
1290f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1291f8c111d4d76018f35222ca7bd0ee55e20a3c154cBerker Peksag    def test_decimal_extendedcontext_mismatched_infs_to_nan(self):
1292f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test adding Decimal INFs with opposite sign returns NAN.
1293f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        inf = Decimal('inf')
1294f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, inf, 3, -inf, 4]
1295f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        with decimal.localcontext(decimal.ExtendedContext):
1296b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertTrue(math.isnan(statistics._sum(data)[1]))
1297f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1298f8c111d4d76018f35222ca7bd0ee55e20a3c154cBerker Peksag    def test_decimal_basiccontext_mismatched_infs_to_nan(self):
1299f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test adding Decimal INFs with opposite sign raises InvalidOperation.
1300f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        inf = Decimal('inf')
1301f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, inf, 3, -inf, 4]
1302f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        with decimal.localcontext(decimal.BasicContext):
1303f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertRaises(decimal.InvalidOperation, statistics._sum, data)
1304f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1305f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimal_snan_raises(self):
1306f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Adding sNAN should raise InvalidOperation.
1307f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        sNAN = Decimal('sNAN')
1308f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, sNAN, 2]
1309f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(decimal.InvalidOperation, statistics._sum, data)
1310f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1311f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1312f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Tests for averages ===
1313f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1314f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass AverageMixin(UnivariateCommonMixin):
1315f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Mixin class holding common tests for averages.
1316f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1317f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_single_value(self):
1318f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Average of a single value is the value itself.
1319f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in (23, 42.5, 1.3e15, Fraction(15, 19), Decimal('0.28')):
1320f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(self.func([x]), x)
1321f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1322a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def prepare_values_for_repeated_single_test(self):
1323a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        return (3.5, 17, 2.5e15, Fraction(61, 67), Decimal('4.9712'))
1324a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1325f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_repeated_single_value(self):
1326f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # The average of a single repeated value is the value itself.
1327a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        for x in self.prepare_values_for_repeated_single_test():
1328f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for count in (2, 5, 10, 20):
1329a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano                with self.subTest(x=x, count=count):
1330a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano                    data = [x]*count
1331a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano                    self.assertEqual(self.func(data), x)
1332f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1333f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1334f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMean(NumericTestCase, AverageMixin, UnivariateTypeMixin):
1335f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1336f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.mean
1337f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1338f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_torture_pep(self):
1339f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # "Torture Test" from PEP-450.
1340f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func([1e100, 1, 3, -1e100]), 1)
1341f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1342f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_ints(self):
1343f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mean with ints.
1344f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [0, 1, 2, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7, 7, 8, 9]
1345f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1346f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 4.8125)
1347f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1348f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_floats(self):
1349f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mean with floats.
1350f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [17.25, 19.75, 20.0, 21.5, 21.75, 23.25, 25.125, 27.5]
1351f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1352f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 22.015625)
1353f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1354f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimals(self):
1355a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test mean with Decimals.
1356f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1357f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D("1.634"), D("2.517"), D("3.912"), D("4.072"), D("5.813")]
1358f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1359f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), D("3.5896"))
1360f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1361f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_fractions(self):
1362f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mean with Fractions.
1363f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1364f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 2), F(2, 3), F(3, 4), F(4, 5), F(5, 6), F(6, 7), F(7, 8)]
1365f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1366f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), F(1479, 1960))
1367f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1368f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_inf(self):
1369f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mean with infinities.
1370f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raw = [1, 3, 5, 7, 9]  # Use only ints, to avoid TypeError later.
1371f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for kind in (float, Decimal):
1372f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for sign in (1, -1):
1373f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                inf = kind("inf")*sign
1374f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                data = raw + [inf]
1375f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                result = self.func(data)
1376f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.assertTrue(math.isinf(result))
1377f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.assertEqual(result, inf)
1378f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1379f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_mismatched_infs(self):
1380f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mean with infinities of opposite sign.
1381f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [2, 4, 6, float('inf'), 1, 3, 5, float('-inf')]
1382f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func(data)
1383f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertTrue(math.isnan(result))
1384f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1385f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_nan(self):
1386f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mean with NANs.
1387f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raw = [1, 3, 5, 7, 9]  # Use only ints, to avoid TypeError later.
1388f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for kind in (float, Decimal):
1389f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            inf = kind("nan")
1390f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            data = raw + [inf]
1391f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            result = self.func(data)
1392f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertTrue(math.isnan(result))
1393f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1394f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_big_data(self):
1395f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test adding a large constant to every data point.
1396f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        c = 1e9
1397f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4]
1398f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(data) + c
1399f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert expected != c
1400f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func([x+c for x in data])
1401f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(result, expected)
1402f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1403f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_doubled_data(self):
1404f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Mean of [a,b,c...z] should be same as for [a,a,b,b,c,c...z,z].
1405f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(-3, 5) for _ in range(1000)]
1406f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(data)
1407f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        actual = self.func(data*2)
1408f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(actual, expected)
1409f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
14104a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan    def test_regression_20561(self):
14114a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # Regression test for issue 20561.
14124a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        # See http://bugs.python.org/issue20561
14134a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        d = Decimal('1e4')
14144a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan        self.assertEqual(statistics.mean([d]), d)
14154a7668adca60a75fb41c87781caa5672871f65cfNick Coghlan
1416b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano    def test_regression_25177(self):
1417b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Regression test for issue 25177.
1418b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # Ensure very big and very small floats don't overflow.
1419b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        # See http://bugs.python.org/issue25177.
1420b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        self.assertEqual(statistics.mean(
1421b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            [8.988465674311579e+307, 8.98846567431158e+307]),
1422b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            8.98846567431158e+307)
1423b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        big = 8.98846567431158e+307
1424b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        tiny = 5e-324
1425b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano        for n in (2, 3, 5, 200):
1426b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(statistics.mean([big]*n), big)
1427b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano            self.assertEqual(statistics.mean([tiny]*n), tiny)
1428b28c3275c720b6908bebf9d545b90fc8789cf1feSteven D'Aprano
1429f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1430a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Apranoclass TestHarmonicMean(NumericTestCase, AverageMixin, UnivariateTypeMixin):
1431a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def setUp(self):
1432a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.func = statistics.harmonic_mean
1433a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1434a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def prepare_data(self):
1435a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Override mixin method.
1436a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        values = super().prepare_data()
1437a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        values.remove(0)
1438a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        return values
1439a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1440a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def prepare_values_for_repeated_single_test(self):
1441a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Override mixin method.
1442a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        return (3.5, 17, 2.5e15, Fraction(61, 67), Decimal('4.125'))
1443a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1444a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_zero(self):
1445a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that harmonic mean returns zero when given zero.
1446a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        values = [1, 0, 2]
1447a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(values), 0)
1448a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1449a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_negative_error(self):
1450a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that harmonic mean raises when given a negative value.
1451a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        exc = statistics.StatisticsError
1452a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        for values in ([-1], [1, -2, 3]):
1453a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano            with self.subTest(values=values):
1454a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano                self.assertRaises(exc, self.func, values)
1455a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1456a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_ints(self):
1457a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test harmonic mean with ints.
1458a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [2, 4, 4, 8, 16, 16]
1459a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        random.shuffle(data)
1460a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(data), 6*4/5)
1461a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1462a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_floats_exact(self):
1463a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test harmonic mean with some carefully chosen floats.
1464a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [1/8, 1/4, 1/4, 1/2, 1/2]
1465a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        random.shuffle(data)
1466a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(data), 1/4)
1467a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func([0.25, 0.5, 1.0, 1.0]), 0.5)
1468a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1469a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_singleton_lists(self):
1470a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test that harmonic mean([x]) returns (approximately) x.
1471a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        for x in range(1, 101):
1472e7fef52f9865b29785be04d1dc7d9b0b52f3c085Steven D'Aprano            self.assertEqual(self.func([x]), x)
1473a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1474a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_decimals_exact(self):
1475a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test harmonic mean with some carefully chosen Decimals.
1476a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        D = Decimal
1477a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func([D(15), D(30), D(60), D(60)]), D(30))
1478a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [D("0.05"), D("0.10"), D("0.20"), D("0.20")]
1479a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        random.shuffle(data)
1480a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(data), D("0.10"))
1481a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [D("1.68"), D("0.32"), D("5.94"), D("2.75")]
1482a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        random.shuffle(data)
1483a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(data), D(66528)/70723)
1484a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1485a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_fractions(self):
1486a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test harmonic mean with Fractions.
1487a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        F = Fraction
1488a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [F(1, 2), F(2, 3), F(3, 4), F(4, 5), F(5, 6), F(6, 7), F(7, 8)]
1489a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        random.shuffle(data)
1490a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(data), F(7*420, 4029))
1491a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1492a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_inf(self):
1493a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test harmonic mean with infinity.
1494a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        values = [2.0, float('inf'), 1.0]
1495a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(self.func(values), 2.0)
1496a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1497a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_nan(self):
1498a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test harmonic mean with NANs.
1499a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        values = [2.0, float('nan'), 1.0]
1500a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertTrue(math.isnan(self.func(values)))
1501a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1502a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_multiply_data_points(self):
1503a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Test multiplying every data point by a constant.
1504a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        c = 111
1505a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4]
1506a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        expected = self.func(data)*c
1507a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        result = self.func([x*c for x in data])
1508a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertEqual(result, expected)
1509a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1510a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano    def test_doubled_data(self):
1511a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        # Harmonic mean of [a,b...z] should be same as for [a,a,b,b...z,z].
1512a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        data = [random.uniform(1, 5) for _ in range(1000)]
1513a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        expected = self.func(data)
1514a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        actual = self.func(data*2)
1515a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano        self.assertApproxEqual(actual, expected)
1516a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1517a474afdddc9282fedd63035b5973c88270c99ee8Steven D'Aprano
1518f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMedian(NumericTestCase, AverageMixin):
1519f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Common tests for median and all median.* functions.
1520f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1521f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.median
1522f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1523f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def prepare_data(self):
1524f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """Overload method from UnivariateCommonMixin."""
1525f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = super().prepare_data()
1526f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        if len(data)%2 != 1:
1527f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            data.append(2)
1528f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return data
1529f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1530f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_ints(self):
1531f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median with an even number of int data points.
1532f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, 3, 4, 5, 6]
1533f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1534f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 3.5)
1535f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1536f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_odd_ints(self):
1537f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median with an odd number of int data points.
1538f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, 3, 4, 5, 6, 9]
1539f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1540f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 4)
1541f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1542f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_odd_fractions(self):
1543f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median works with an odd number of Fractions.
1544f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1545f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7)]
1546f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1547f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1548f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), F(3, 7))
1549f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1550f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_fractions(self):
1551f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median works with an even number of Fractions.
1552f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1553f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)]
1554f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1555f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1556f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), F(1, 2))
1557f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1558f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_odd_decimals(self):
1559f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median works with an odd number of Decimals.
1560f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1561f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('2.5'), D('3.1'), D('4.2'), D('5.7'), D('5.8')]
1562f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1563f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1564f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), D('4.2'))
1565f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1566f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_decimals(self):
1567f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median works with an even number of Decimals.
1568f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1569f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('1.2'), D('2.5'), D('3.1'), D('4.2'), D('5.7'), D('5.8')]
1570f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1571f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1572f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), D('3.65'))
1573f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1574f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1575f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMedianDataType(NumericTestCase, UnivariateTypeMixin):
1576f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test conservation of data element type for median.
1577f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1578f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.median
1579f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1580f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def prepare_data(self):
1581f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = list(range(15))
1582f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1583f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        while data == sorted(data):
1584f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            random.shuffle(data)
1585f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return data
1586f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1587f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1588f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMedianLow(TestMedian, UnivariateTypeMixin):
1589f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1590f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.median_low
1591f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1592f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_ints(self):
1593f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_low with an even number of ints.
1594f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, 3, 4, 5, 6]
1595f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1596f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 3)
1597f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1598f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_fractions(self):
1599f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_low works with an even number of Fractions.
1600f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1601f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)]
1602f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1603f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1604f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), F(3, 7))
1605f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1606f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_decimals(self):
1607f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_low works with an even number of Decimals.
1608f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1609f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('1.1'), D('2.2'), D('3.3'), D('4.4'), D('5.5'), D('6.6')]
1610f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1611f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1612f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), D('3.3'))
1613f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1614f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1615f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMedianHigh(TestMedian, UnivariateTypeMixin):
1616f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1617f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.median_high
1618f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1619f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_ints(self):
1620f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_high with an even number of ints.
1621f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 2, 3, 4, 5, 6]
1622f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1623f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 4)
1624f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1625f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_fractions(self):
1626f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_high works with an even number of Fractions.
1627f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1628f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)]
1629f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1630f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1631f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), F(4, 7))
1632f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1633f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_decimals(self):
1634f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_high works with an even number of Decimals.
1635f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1636f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('1.1'), D('2.2'), D('3.3'), D('4.4'), D('5.5'), D('6.6')]
1637f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1638f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1639f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), D('4.4'))
1640f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1641f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1642f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMedianGrouped(TestMedian):
1643f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test median_grouped.
1644f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Doesn't conserve data element types, so don't use TestMedianType.
1645f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1646f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.median_grouped
1647f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1648f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_odd_number_repeated(self):
1649f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median.grouped with repeated median values.
1650f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [12, 13, 14, 14, 14, 15, 15]
1651f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1652f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 14)
1653f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1654f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [12, 13, 14, 14, 14, 14, 15]
1655f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1656f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 13.875)
1657f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1658f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [5, 10, 10, 15, 20, 20, 20, 20, 25, 25, 30]
1659f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1660f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data, 5), 19.375)
1661f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1662f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [16, 18, 18, 18, 18, 20, 20, 20, 22, 22, 22, 24, 24, 26, 28]
1663f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1664f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(self.func(data, 2), 20.66666667, tol=1e-8)
1665f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1666f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_number_repeated(self):
1667f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median.grouped with repeated median values.
1668f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [5, 10, 10, 15, 20, 20, 20, 25, 25, 30]
1669f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1670f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(self.func(data, 5), 19.16666667, tol=1e-8)
1671f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1672f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [2, 3, 4, 4, 4, 5]
1673f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1674f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(self.func(data), 3.83333333, tol=1e-8)
1675f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1676f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6]
1677f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1678f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 4.5)
1679f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1680f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [3, 4, 4, 4, 5, 5, 5, 5, 6, 6]
1681f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1682f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 4.75)
1683f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1684f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_repeated_single_value(self):
1685f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Override method from AverageMixin.
1686f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Yet again, failure of median_grouped to conserve the data type
1687f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # causes me headaches :-(
1688f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in (5.3, 68, 4.3e17, Fraction(29, 101), Decimal('32.9714')):
1689f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for count in (2, 5, 10, 20):
1690f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                data = [x]*count
1691f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.assertEqual(self.func(data), float(x))
1692f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1693f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_odd_fractions(self):
1694f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_grouped works with an odd number of Fractions.
1695f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1696f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(5, 4), F(9, 4), F(13, 4), F(13, 4), F(17, 4)]
1697f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1698f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1699f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 3.0)
1700f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1701f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_fractions(self):
1702f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_grouped works with an even number of Fractions.
1703f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1704f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(5, 4), F(9, 4), F(13, 4), F(13, 4), F(17, 4), F(17, 4)]
1705f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1706f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1707f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 3.25)
1708f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1709f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_odd_decimals(self):
1710f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_grouped works with an odd number of Decimals.
1711f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1712f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('5.5'), D('6.5'), D('6.5'), D('7.5'), D('8.5')]
1713f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 1
1714f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1715f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 6.75)
1716f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1717f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_even_decimals(self):
1718f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_grouped works with an even number of Decimals.
1719f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1720f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('5.5'), D('5.5'), D('6.5'), D('6.5'), D('7.5'), D('8.5')]
1721f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1722f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1723f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 6.5)
1724f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        #---
1725f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D('5.5'), D('5.5'), D('6.5'), D('7.5'), D('7.5'), D('8.5')]
1726f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert len(data)%2 == 0
1727f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1728f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 7.0)
1729f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1730f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_interval(self):
1731f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test median_grouped with interval argument.
1732f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [2.25, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0, 3.25, 3.5, 3.75]
1733f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data, 0.25), 2.875)
1734f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [2.25, 2.5, 2.5, 2.75, 2.75, 2.75, 3.0, 3.0, 3.25, 3.5, 3.75]
1735f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(self.func(data, 0.25), 2.83333333, tol=1e-8)
1736f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [220, 220, 240, 260, 260, 260, 260, 280, 280, 300, 320, 340]
1737f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data, 20), 265.0)
1738f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
17398c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano    def test_data_type_error(self):
17408c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        # Test median_grouped with str, bytes data types for data and interval
17418c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        data = ["", "", ""]
17428c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        self.assertRaises(TypeError, self.func, data)
17438c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        #---
17448c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        data = [b"", b"", b""]
17458c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        self.assertRaises(TypeError, self.func, data)
17468c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        #---
17478c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        data = [1, 2, 3]
17488c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        interval = ""
17498c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        self.assertRaises(TypeError, self.func, data, interval)
17508c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        #---
17518c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        data = [1, 2, 3]
17528c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        interval = b""
17538c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano        self.assertRaises(TypeError, self.func, data, interval)
17548c115a46e7c608d96b090d2bfd719cf028dbcd4fSteven D'Aprano
1755f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1756f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestMode(NumericTestCase, AverageMixin, UnivariateTypeMixin):
1757f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Test cases for the discrete version of mode.
1758f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1759f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.mode
1760f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1761f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def prepare_data(self):
1762f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        """Overload method from UnivariateCommonMixin."""
1763f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Make sure test data has exactly one mode.
1764f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        return [1, 1, 1, 1, 3, 4, 7, 9, 0, 8, 2]
1765f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1766f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_range_data(self):
1767f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Override test from UnivariateCommonMixin.
1768f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = range(20, 50, 3)
1769f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(statistics.StatisticsError, self.func, data)
1770f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1771f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_nominal_data(self):
1772f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mode with nominal data.
1773f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = 'abcbdb'
1774f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 'b')
1775f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = 'fe fi fo fum fi fi'.split()
1776f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), 'fi')
1777f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1778f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_discrete_data(self):
1779f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mode with discrete numeric data.
1780f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = list(range(10))
1781f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for i in range(10):
1782f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            d = data + [i]
1783f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            random.shuffle(d)
1784f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(self.func(d), i)
1785f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1786f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_bimodal_data(self):
1787f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mode with bimodal data.
1788f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8, 9, 9]
1789f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert data.count(2) == data.count(6) == 4
1790f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Check for an exception.
1791f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(statistics.StatisticsError, self.func, data)
1792f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1793f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_unique_data_failure(self):
1794f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test mode exception when data points are all unique.
1795f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = list(range(10))
1796f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(statistics.StatisticsError, self.func, data)
1797f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1798f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_none_data(self):
1799f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that mode raises TypeError if given None as data.
1800f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1801f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # This test is necessary because the implementation of mode uses
1802f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # collections.Counter, which accepts None and returns an empty dict.
1803f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertRaises(TypeError, self.func, None)
1804f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1805bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan    def test_counter_data(self):
1806bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan        # Test that a Counter is treated like any other iterable.
1807bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan        data = collections.Counter([1, 1, 1, 2])
1808bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan        # Since the keys of the counter are treated as data points, not the
1809bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan        # counts, this should raise.
1810bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan        self.assertRaises(statistics.StatisticsError, self.func, data)
1811bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan
1812bfd68bf4ac6661bf0fab51178583bee88840a8e6Nick Coghlan
1813f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1814f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Tests for variances and standard deviations ===
1815f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1816f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass VarianceStdevMixin(UnivariateCommonMixin):
1817f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Mixin class holding common tests for variance and std dev.
1818f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1819f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Subclasses should inherit from this before NumericTestClass, in order
1820f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # to see the rel attribute below. See testShiftData for an explanation.
1821f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1822f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    rel = 1e-12
1823f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1824f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_single_value(self):
1825f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Deviation of a single value is zero.
1826f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in (11, 19.8, 4.6e14, Fraction(21, 34), Decimal('8.392')):
1827f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertEqual(self.func([x]), 0)
1828f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1829f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_repeated_single_value(self):
1830f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # The deviation of a single repeated value is zero.
1831f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in (7.2, 49, 8.1e15, Fraction(3, 7), Decimal('62.4802')):
1832f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            for count in (2, 3, 5, 15):
1833f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                data = [x]*count
1834f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings                self.assertEqual(self.func(data), 0)
1835f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1836f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_domain_error_regression(self):
1837f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Regression test for a domain error exception.
1838f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # (Thanks to Geremy Condra.)
1839f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [0.123456789012345]*10000
1840f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # All the items are identical, so variance should be exactly zero.
1841f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # We allow some small round-off error, but not much.
1842f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func(data)
1843f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(result, 0.0, tol=5e-17)
1844f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertGreaterEqual(result, 0)  # A negative result must fail.
1845f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1846f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_shift_data(self):
1847f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that shifting the data by a constant amount does not affect
1848f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # the variance or stdev. Or at least not much.
1849f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1850f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Due to rounding, this test should be considered an ideal. We allow
1851f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # some tolerance away from "no change at all" by setting tol and/or rel
1852f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # attributes. Subclasses may set tighter or looser error tolerances.
1853f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raw = [1.03, 1.27, 1.94, 2.04, 2.58, 3.14, 4.75, 4.98, 5.42, 6.78]
1854f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(raw)
1855f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Don't set shift too high, the bigger it is, the more rounding error.
1856f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        shift = 1e5
1857f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [x + shift for x in raw]
1858f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertApproxEqual(self.func(data), expected)
1859f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1860f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_shift_data_exact(self):
1861f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Like test_shift_data, but result is always exact.
1862f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        raw = [1, 3, 3, 4, 5, 7, 9, 10, 11, 16]
1863f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        assert all(x==int(x) for x in raw)
1864f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(raw)
1865f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        shift = 10**9
1866f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [x + shift for x in raw]
1867f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), expected)
1868f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1869f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_iter_list_same(self):
1870f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that iter data and list data give the same result.
1871f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1872f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # This is an explicit test that iterators and lists are treated the
1873f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # same; justification for this test over and above the similar test
1874f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # in UnivariateCommonMixin is that an earlier design had variance and
1875f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # friends swap between one- and two-pass algorithms, which would
1876f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # sometimes give different results.
1877f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(-3, 8) for _ in range(1000)]
1878f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = self.func(data)
1879f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(iter(data)), expected)
1880f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1881f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1882f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestPVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin):
1883f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Tests for population variance.
1884f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1885f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.pvariance
1886f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1887f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_exact_uniform(self):
1888f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test the variance against an exact result for uniform data.
1889f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = list(range(10000))
1890f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        random.shuffle(data)
1891f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = (10000**2 - 1)/12  # Exact value.
1892f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), expected)
1893f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1894f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_ints(self):
1895f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test population variance with int data.
1896f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [4, 7, 13, 16]
1897f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        exact = 22.5
1898f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), exact)
1899f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1900f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_fractions(self):
1901f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test population variance with Fraction data.
1902f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1903f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 4), F(1, 4), F(3, 4), F(7, 4)]
1904f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        exact = F(3, 8)
1905f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func(data)
1906f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(result, exact)
1907f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertIsInstance(result, Fraction)
1908f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1909f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimals(self):
1910f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test population variance with Decimal data.
1911f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1912f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D("12.1"), D("12.2"), D("12.5"), D("12.9")]
1913f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        exact = D('0.096875')
1914f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func(data)
1915f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(result, exact)
1916f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertIsInstance(result, Decimal)
1917f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1918f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1919f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin):
1920f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Tests for sample variance.
1921f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1922f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.variance
1923f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1924f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_single_value(self):
1925f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Override method from VarianceStdevMixin.
1926f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in (35, 24.7, 8.2e15, Fraction(19, 30), Decimal('4.2084')):
1927f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertRaises(statistics.StatisticsError, self.func, [x])
1928f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1929f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_ints(self):
1930f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test sample variance with int data.
1931f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [4, 7, 13, 16]
1932f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        exact = 30
1933f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), exact)
1934f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1935f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_fractions(self):
1936f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test sample variance with Fraction data.
1937f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        F = Fraction
1938f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [F(1, 4), F(1, 4), F(3, 4), F(7, 4)]
1939f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        exact = F(1, 2)
1940f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func(data)
1941f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(result, exact)
1942f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertIsInstance(result, Fraction)
1943f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1944f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_decimals(self):
1945f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test sample variance with Decimal data.
1946f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        D = Decimal
1947f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [D(2), D(2), D(7), D(9)]
1948f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        exact = 4*D('9.5')/D(3)
1949f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        result = self.func(data)
1950f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(result, exact)
1951f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertIsInstance(result, Decimal)
1952f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1953f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1954f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestPStdev(VarianceStdevMixin, NumericTestCase):
1955f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Tests for population standard deviation.
1956f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1957f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.pstdev
1958f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1959f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_compare_to_variance(self):
1960f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that stdev is, in fact, the square root of variance.
1961f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(-17, 24) for _ in range(1000)]
1962f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = math.sqrt(statistics.pvariance(data))
1963f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), expected)
1964f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1965f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1966f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsclass TestStdev(VarianceStdevMixin, NumericTestCase):
1967f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    # Tests for sample standard deviation.
1968f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def setUp(self):
1969f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.func = statistics.stdev
1970f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1971f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_single_value(self):
1972f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Override method from VarianceStdevMixin.
1973f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        for x in (81, 203.74, 3.9e14, Fraction(5, 21), Decimal('35.719')):
1974f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings            self.assertRaises(statistics.StatisticsError, self.func, [x])
1975f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1976f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    def test_compare_to_variance(self):
1977f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        # Test that stdev is, in fact, the square root of variance.
1978f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        data = [random.uniform(-2, 9) for _ in range(1000)]
1979f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        expected = math.sqrt(statistics.variance(data))
1980f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings        self.assertEqual(self.func(data), expected)
1981f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1982f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1983f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings# === Run tests ===
1984f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1985f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsdef load_tests(loader, tests, ignore):
1986f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    """Used for doctest/unittest integration."""
1987f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    tests.addTests(doctest.DocTestSuite())
1988f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    return tests
1989f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1990f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings
1991f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastingsif __name__ == "__main__":
1992f5e987bbe64156ebeae5eea730962c209fbb9d74Larry Hastings    unittest.main()
1993