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