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