# Python code coverage for Lib/test/test_statistics.py

# | count | content |
---|---|---|

1 | n/a | """Test suite for statistics module, including helper NumericTestCase and |

2 | n/a | approx_equal function. |

3 | n/a | |

4 | n/a | """ |

5 | n/a | |

6 | n/a | import collections |

7 | n/a | import decimal |

8 | n/a | import doctest |

9 | n/a | import math |

10 | n/a | import random |

11 | n/a | import sys |

12 | n/a | import unittest |

13 | n/a | |

14 | n/a | from decimal import Decimal |

15 | n/a | from fractions import Fraction |

16 | n/a | |

17 | n/a | |

18 | n/a | # Module to be tested. |

19 | n/a | import statistics |

20 | n/a | |

21 | n/a | |

22 | n/a | # === Helper functions and class === |

23 | n/a | |

24 | n/a | def sign(x): |

25 | n/a | """Return -1.0 for negatives, including -0.0, otherwise +1.0.""" |

26 | n/a | return math.copysign(1, x) |

27 | n/a | |

28 | n/a | def _nan_equal(a, b): |

29 | n/a | """Return True if a and b are both the same kind of NAN. |

30 | n/a | |

31 | n/a | >>> _nan_equal(Decimal('NAN'), Decimal('NAN')) |

32 | n/a | True |

33 | n/a | >>> _nan_equal(Decimal('sNAN'), Decimal('sNAN')) |

34 | n/a | True |

35 | n/a | >>> _nan_equal(Decimal('NAN'), Decimal('sNAN')) |

36 | n/a | False |

37 | n/a | >>> _nan_equal(Decimal(42), Decimal('NAN')) |

38 | n/a | False |

39 | n/a | |

40 | n/a | >>> _nan_equal(float('NAN'), float('NAN')) |

41 | n/a | True |

42 | n/a | >>> _nan_equal(float('NAN'), 0.5) |

43 | n/a | False |

44 | n/a | |

45 | n/a | >>> _nan_equal(float('NAN'), Decimal('NAN')) |

46 | n/a | False |

47 | n/a | |

48 | n/a | NAN payloads are not compared. |

49 | n/a | """ |

50 | n/a | if type(a) is not type(b): |

51 | n/a | return False |

52 | n/a | if isinstance(a, float): |

53 | n/a | return math.isnan(a) and math.isnan(b) |

54 | n/a | aexp = a.as_tuple()[2] |

55 | n/a | bexp = b.as_tuple()[2] |

56 | n/a | return (aexp == bexp) and (aexp in ('n', 'N')) # Both NAN or both sNAN. |

57 | n/a | |

58 | n/a | |

59 | n/a | def _calc_errors(actual, expected): |

60 | n/a | """Return the absolute and relative errors between two numbers. |

61 | n/a | |

62 | n/a | >>> _calc_errors(100, 75) |

63 | n/a | (25, 0.25) |

64 | n/a | >>> _calc_errors(100, 100) |

65 | n/a | (0, 0.0) |

66 | n/a | |

67 | n/a | Returns the (absolute error, relative error) between the two arguments. |

68 | n/a | """ |

69 | n/a | base = max(abs(actual), abs(expected)) |

70 | n/a | abs_err = abs(actual - expected) |

71 | n/a | rel_err = abs_err/base if base else float('inf') |

72 | n/a | return (abs_err, rel_err) |

73 | n/a | |

74 | n/a | |

75 | n/a | def approx_equal(x, y, tol=1e-12, rel=1e-7): |

76 | n/a | """approx_equal(x, y [, tol [, rel]]) => True|False |

77 | n/a | |

78 | n/a | Return True if numbers x and y are approximately equal, to within some |

79 | n/a | margin of error, otherwise return False. Numbers which compare equal |

80 | n/a | will also compare approximately equal. |

81 | n/a | |

82 | n/a | x is approximately equal to y if the difference between them is less than |

83 | n/a | an absolute error tol or a relative error rel, whichever is bigger. |

84 | n/a | |

85 | n/a | If given, both tol and rel must be finite, non-negative numbers. If not |

86 | n/a | given, default values are tol=1e-12 and rel=1e-7. |

87 | n/a | |

88 | n/a | >>> approx_equal(1.2589, 1.2587, tol=0.0003, rel=0) |

89 | n/a | True |

90 | n/a | >>> approx_equal(1.2589, 1.2587, tol=0.0001, rel=0) |

91 | n/a | False |

92 | n/a | |

93 | n/a | Absolute error is defined as abs(x-y); if that is less than or equal to |

94 | n/a | tol, x and y are considered approximately equal. |

95 | n/a | |

96 | n/a | Relative error is defined as abs((x-y)/x) or abs((x-y)/y), whichever is |

97 | n/a | smaller, provided x or y are not zero. If that figure is less than or |

98 | n/a | equal to rel, x and y are considered approximately equal. |

99 | n/a | |

100 | n/a | Complex numbers are not directly supported. If you wish to compare to |

101 | n/a | complex numbers, extract their real and imaginary parts and compare them |

102 | n/a | individually. |

103 | n/a | |

104 | n/a | NANs always compare unequal, even with themselves. Infinities compare |

105 | n/a | approximately equal if they have the same sign (both positive or both |

106 | n/a | negative). Infinities with different signs compare unequal; so do |

107 | n/a | comparisons of infinities with finite numbers. |

108 | n/a | """ |

109 | n/a | if tol < 0 or rel < 0: |

110 | n/a | raise ValueError('error tolerances must be non-negative') |

111 | n/a | # NANs are never equal to anything, approximately or otherwise. |

112 | n/a | if math.isnan(x) or math.isnan(y): |

113 | n/a | return False |

114 | n/a | # Numbers which compare equal also compare approximately equal. |

115 | n/a | if x == y: |

116 | n/a | # This includes the case of two infinities with the same sign. |

117 | n/a | return True |

118 | n/a | if math.isinf(x) or math.isinf(y): |

119 | n/a | # This includes the case of two infinities of opposite sign, or |

120 | n/a | # one infinity and one finite number. |

121 | n/a | return False |

122 | n/a | # Two finite numbers. |

123 | n/a | actual_error = abs(x - y) |

124 | n/a | allowed_error = max(tol, rel*max(abs(x), abs(y))) |

125 | n/a | return actual_error <= allowed_error |

126 | n/a | |

127 | n/a | |

128 | n/a | # This class exists only as somewhere to stick a docstring containing |

129 | n/a | # doctests. The following docstring and tests were originally in a separate |

130 | n/a | # module. Now that it has been merged in here, I need somewhere to hang the. |

131 | n/a | # docstring. Ultimately, this class will die, and the information below will |

132 | n/a | # either become redundant, or be moved into more appropriate places. |

133 | n/a | class _DoNothing: |

134 | n/a | """ |

135 | n/a | When doing numeric work, especially with floats, exact equality is often |

136 | n/a | not what you want. Due to round-off error, it is often a bad idea to try |

137 | n/a | to compare floats with equality. Instead the usual procedure is to test |

138 | n/a | them with some (hopefully small!) allowance for error. |

139 | n/a | |

140 | n/a | The ``approx_equal`` function allows you to specify either an absolute |

141 | n/a | error tolerance, or a relative error, or both. |

142 | n/a | |

143 | n/a | Absolute error tolerances are simple, but you need to know the magnitude |

144 | n/a | of the quantities being compared: |

145 | n/a | |

146 | n/a | >>> approx_equal(12.345, 12.346, tol=1e-3) |

147 | n/a | True |

148 | n/a | >>> approx_equal(12.345e6, 12.346e6, tol=1e-3) # tol is too small. |

149 | n/a | False |

150 | n/a | |

151 | n/a | Relative errors are more suitable when the values you are comparing can |

152 | n/a | vary in magnitude: |

153 | n/a | |

154 | n/a | >>> approx_equal(12.345, 12.346, rel=1e-4) |

155 | n/a | True |

156 | n/a | >>> approx_equal(12.345e6, 12.346e6, rel=1e-4) |

157 | n/a | True |

158 | n/a | |

159 | n/a | but a naive implementation of relative error testing can run into trouble |

160 | n/a | around zero. |

161 | n/a | |

162 | n/a | If you supply both an absolute tolerance and a relative error, the |

163 | n/a | comparison succeeds if either individual test succeeds: |

164 | n/a | |

165 | n/a | >>> approx_equal(12.345e6, 12.346e6, tol=1e-3, rel=1e-4) |

166 | n/a | True |

167 | n/a | |

168 | n/a | """ |

169 | n/a | pass |

170 | n/a | |

171 | n/a | |

172 | n/a | |

173 | n/a | # We prefer this for testing numeric values that may not be exactly equal, |

174 | n/a | # and avoid using TestCase.assertAlmostEqual, because it sucks :-) |

175 | n/a | |

176 | n/a | class NumericTestCase(unittest.TestCase): |

177 | n/a | """Unit test class for numeric work. |

178 | n/a | |

179 | n/a | This subclasses TestCase. In addition to the standard method |

180 | n/a | ``TestCase.assertAlmostEqual``, ``assertApproxEqual`` is provided. |

181 | n/a | """ |

182 | n/a | # By default, we expect exact equality, unless overridden. |

183 | n/a | tol = rel = 0 |

184 | n/a | |

185 | n/a | def assertApproxEqual( |

186 | n/a | self, first, second, tol=None, rel=None, msg=None |

187 | n/a | ): |

188 | n/a | """Test passes if ``first`` and ``second`` are approximately equal. |

189 | n/a | |

190 | n/a | This test passes if ``first`` and ``second`` are equal to |

191 | n/a | within ``tol``, an absolute error, or ``rel``, a relative error. |

192 | n/a | |

193 | n/a | If either ``tol`` or ``rel`` are None or not given, they default to |

194 | n/a | test attributes of the same name (by default, 0). |

195 | n/a | |

196 | n/a | The objects may be either numbers, or sequences of numbers. Sequences |

197 | n/a | are tested element-by-element. |

198 | n/a | |

199 | n/a | >>> class MyTest(NumericTestCase): |

200 | n/a | ... def test_number(self): |

201 | n/a | ... x = 1.0/6 |

202 | n/a | ... y = sum([x]*6) |

203 | n/a | ... self.assertApproxEqual(y, 1.0, tol=1e-15) |

204 | n/a | ... def test_sequence(self): |

205 | n/a | ... a = [1.001, 1.001e-10, 1.001e10] |

206 | n/a | ... b = [1.0, 1e-10, 1e10] |

207 | n/a | ... self.assertApproxEqual(a, b, rel=1e-3) |

208 | n/a | ... |

209 | n/a | >>> import unittest |

210 | n/a | >>> from io import StringIO # Suppress test runner output. |

211 | n/a | >>> suite = unittest.TestLoader().loadTestsFromTestCase(MyTest) |

212 | n/a | >>> unittest.TextTestRunner(stream=StringIO()).run(suite) |

213 | n/a | <unittest.runner.TextTestResult run=2 errors=0 failures=0> |

214 | n/a | |

215 | n/a | """ |

216 | n/a | if tol is None: |

217 | n/a | tol = self.tol |

218 | n/a | if rel is None: |

219 | n/a | rel = self.rel |

220 | n/a | if ( |

221 | n/a | isinstance(first, collections.Sequence) and |

222 | n/a | isinstance(second, collections.Sequence) |

223 | n/a | ): |

224 | n/a | check = self._check_approx_seq |

225 | n/a | else: |

226 | n/a | check = self._check_approx_num |

227 | n/a | check(first, second, tol, rel, msg) |

228 | n/a | |

229 | n/a | def _check_approx_seq(self, first, second, tol, rel, msg): |

230 | n/a | if len(first) != len(second): |

231 | n/a | standardMsg = ( |

232 | n/a | "sequences differ in length: %d items != %d items" |

233 | n/a | % (len(first), len(second)) |

234 | n/a | ) |

235 | n/a | msg = self._formatMessage(msg, standardMsg) |

236 | n/a | raise self.failureException(msg) |

237 | n/a | for i, (a,e) in enumerate(zip(first, second)): |

238 | n/a | self._check_approx_num(a, e, tol, rel, msg, i) |

239 | n/a | |

240 | n/a | def _check_approx_num(self, first, second, tol, rel, msg, idx=None): |

241 | n/a | if approx_equal(first, second, tol, rel): |

242 | n/a | # Test passes. Return early, we are done. |

243 | n/a | return None |

244 | n/a | # Otherwise we failed. |

245 | n/a | standardMsg = self._make_std_err_msg(first, second, tol, rel, idx) |

246 | n/a | msg = self._formatMessage(msg, standardMsg) |

247 | n/a | raise self.failureException(msg) |

248 | n/a | |

249 | n/a | @staticmethod |

250 | n/a | def _make_std_err_msg(first, second, tol, rel, idx): |

251 | n/a | # Create the standard error message for approx_equal failures. |

252 | n/a | assert first != second |

253 | n/a | template = ( |

254 | n/a | ' %r != %r\n' |

255 | n/a | ' values differ by more than tol=%r and rel=%r\n' |

256 | n/a | ' -> absolute error = %r\n' |

257 | n/a | ' -> relative error = %r' |

258 | n/a | ) |

259 | n/a | if idx is not None: |

260 | n/a | header = 'numeric sequences first differ at index %d.\n' % idx |

261 | n/a | template = header + template |

262 | n/a | # Calculate actual errors: |

263 | n/a | abs_err, rel_err = _calc_errors(first, second) |

264 | n/a | return template % (first, second, tol, rel, abs_err, rel_err) |

265 | n/a | |

266 | n/a | |

267 | n/a | # ======================== |

268 | n/a | # === Test the helpers === |

269 | n/a | # ======================== |

270 | n/a | |

271 | n/a | class TestSign(unittest.TestCase): |

272 | n/a | """Test that the helper function sign() works correctly.""" |

273 | n/a | def testZeroes(self): |

274 | n/a | # Test that signed zeroes report their sign correctly. |

275 | n/a | self.assertEqual(sign(0.0), +1) |

276 | n/a | self.assertEqual(sign(-0.0), -1) |

277 | n/a | |

278 | n/a | |

279 | n/a | # --- Tests for approx_equal --- |

280 | n/a | |

281 | n/a | class ApproxEqualSymmetryTest(unittest.TestCase): |

282 | n/a | # Test symmetry of approx_equal. |

283 | n/a | |

284 | n/a | def test_relative_symmetry(self): |

285 | n/a | # Check that approx_equal treats relative error symmetrically. |

286 | n/a | # (a-b)/a is usually not equal to (a-b)/b. Ensure that this |

287 | n/a | # doesn't matter. |

288 | n/a | # |

289 | n/a | # Note: the reason for this test is that an early version |

290 | n/a | # of approx_equal was not symmetric. A relative error test |

291 | n/a | # would pass, or fail, depending on which value was passed |

292 | n/a | # as the first argument. |

293 | n/a | # |

294 | n/a | args1 = [2456, 37.8, -12.45, Decimal('2.54'), Fraction(17, 54)] |

295 | n/a | args2 = [2459, 37.2, -12.41, Decimal('2.59'), Fraction(15, 54)] |

296 | n/a | assert len(args1) == len(args2) |

297 | n/a | for a, b in zip(args1, args2): |

298 | n/a | self.do_relative_symmetry(a, b) |

299 | n/a | |

300 | n/a | def do_relative_symmetry(self, a, b): |

301 | n/a | a, b = min(a, b), max(a, b) |

302 | n/a | assert a < b |

303 | n/a | delta = b - a # The absolute difference between the values. |

304 | n/a | rel_err1, rel_err2 = abs(delta/a), abs(delta/b) |

305 | n/a | # Choose an error margin halfway between the two. |

306 | n/a | rel = (rel_err1 + rel_err2)/2 |

307 | n/a | # Now see that values a and b compare approx equal regardless of |

308 | n/a | # which is given first. |

309 | n/a | self.assertTrue(approx_equal(a, b, tol=0, rel=rel)) |

310 | n/a | self.assertTrue(approx_equal(b, a, tol=0, rel=rel)) |

311 | n/a | |

312 | n/a | def test_symmetry(self): |

313 | n/a | # Test that approx_equal(a, b) == approx_equal(b, a) |

314 | n/a | args = [-23, -2, 5, 107, 93568] |

315 | n/a | delta = 2 |

316 | n/a | for a in args: |

317 | n/a | for type_ in (int, float, Decimal, Fraction): |

318 | n/a | x = type_(a)*100 |

319 | n/a | y = x + delta |

320 | n/a | r = abs(delta/max(x, y)) |

321 | n/a | # There are five cases to check: |

322 | n/a | # 1) actual error <= tol, <= rel |

323 | n/a | self.do_symmetry_test(x, y, tol=delta, rel=r) |

324 | n/a | self.do_symmetry_test(x, y, tol=delta+1, rel=2*r) |

325 | n/a | # 2) actual error > tol, > rel |

326 | n/a | self.do_symmetry_test(x, y, tol=delta-1, rel=r/2) |

327 | n/a | # 3) actual error <= tol, > rel |

328 | n/a | self.do_symmetry_test(x, y, tol=delta, rel=r/2) |

329 | n/a | # 4) actual error > tol, <= rel |

330 | n/a | self.do_symmetry_test(x, y, tol=delta-1, rel=r) |

331 | n/a | self.do_symmetry_test(x, y, tol=delta-1, rel=2*r) |

332 | n/a | # 5) exact equality test |

333 | n/a | self.do_symmetry_test(x, x, tol=0, rel=0) |

334 | n/a | self.do_symmetry_test(x, y, tol=0, rel=0) |

335 | n/a | |

336 | n/a | def do_symmetry_test(self, a, b, tol, rel): |

337 | n/a | template = "approx_equal comparisons don't match for %r" |

338 | n/a | flag1 = approx_equal(a, b, tol, rel) |

339 | n/a | flag2 = approx_equal(b, a, tol, rel) |

340 | n/a | self.assertEqual(flag1, flag2, template.format((a, b, tol, rel))) |

341 | n/a | |

342 | n/a | |

343 | n/a | class ApproxEqualExactTest(unittest.TestCase): |

344 | n/a | # Test the approx_equal function with exactly equal values. |

345 | n/a | # Equal values should compare as approximately equal. |

346 | n/a | # Test cases for exactly equal values, which should compare approx |

347 | n/a | # equal regardless of the error tolerances given. |

348 | n/a | |

349 | n/a | def do_exactly_equal_test(self, x, tol, rel): |

350 | n/a | result = approx_equal(x, x, tol=tol, rel=rel) |

351 | n/a | self.assertTrue(result, 'equality failure for x=%r' % x) |

352 | n/a | result = approx_equal(-x, -x, tol=tol, rel=rel) |

353 | n/a | self.assertTrue(result, 'equality failure for x=%r' % -x) |

354 | n/a | |

355 | n/a | def test_exactly_equal_ints(self): |

356 | n/a | # Test that equal int values are exactly equal. |

357 | n/a | for n in [42, 19740, 14974, 230, 1795, 700245, 36587]: |

358 | n/a | self.do_exactly_equal_test(n, 0, 0) |

359 | n/a | |

360 | n/a | def test_exactly_equal_floats(self): |

361 | n/a | # Test that equal float values are exactly equal. |

362 | n/a | for x in [0.42, 1.9740, 1497.4, 23.0, 179.5, 70.0245, 36.587]: |

363 | n/a | self.do_exactly_equal_test(x, 0, 0) |

364 | n/a | |

365 | n/a | def test_exactly_equal_fractions(self): |

366 | n/a | # Test that equal Fraction values are exactly equal. |

367 | n/a | F = Fraction |

368 | n/a | for f in [F(1, 2), F(0), F(5, 3), F(9, 7), F(35, 36), F(3, 7)]: |

369 | n/a | self.do_exactly_equal_test(f, 0, 0) |

370 | n/a | |

371 | n/a | def test_exactly_equal_decimals(self): |

372 | n/a | # Test that equal Decimal values are exactly equal. |

373 | n/a | D = Decimal |

374 | n/a | for d in map(D, "8.2 31.274 912.04 16.745 1.2047".split()): |

375 | n/a | self.do_exactly_equal_test(d, 0, 0) |

376 | n/a | |

377 | n/a | def test_exactly_equal_absolute(self): |

378 | n/a | # Test that equal values are exactly equal with an absolute error. |

379 | n/a | for n in [16, 1013, 1372, 1198, 971, 4]: |

380 | n/a | # Test as ints. |

381 | n/a | self.do_exactly_equal_test(n, 0.01, 0) |

382 | n/a | # Test as floats. |

383 | n/a | self.do_exactly_equal_test(n/10, 0.01, 0) |

384 | n/a | # Test as Fractions. |

385 | n/a | f = Fraction(n, 1234) |

386 | n/a | self.do_exactly_equal_test(f, 0.01, 0) |

387 | n/a | |

388 | n/a | def test_exactly_equal_absolute_decimals(self): |

389 | n/a | # Test equal Decimal values are exactly equal with an absolute error. |

390 | n/a | self.do_exactly_equal_test(Decimal("3.571"), Decimal("0.01"), 0) |

391 | n/a | self.do_exactly_equal_test(-Decimal("81.3971"), Decimal("0.01"), 0) |

392 | n/a | |

393 | n/a | def test_exactly_equal_relative(self): |

394 | n/a | # Test that equal values are exactly equal with a relative error. |

395 | n/a | for x in [8347, 101.3, -7910.28, Fraction(5, 21)]: |

396 | n/a | self.do_exactly_equal_test(x, 0, 0.01) |

397 | n/a | self.do_exactly_equal_test(Decimal("11.68"), 0, Decimal("0.01")) |

398 | n/a | |

399 | n/a | def test_exactly_equal_both(self): |

400 | n/a | # Test that equal values are equal when both tol and rel are given. |

401 | n/a | for x in [41017, 16.742, -813.02, Fraction(3, 8)]: |

402 | n/a | self.do_exactly_equal_test(x, 0.1, 0.01) |

403 | n/a | D = Decimal |

404 | n/a | self.do_exactly_equal_test(D("7.2"), D("0.1"), D("0.01")) |

405 | n/a | |

406 | n/a | |

407 | n/a | class ApproxEqualUnequalTest(unittest.TestCase): |

408 | n/a | # Unequal values should compare unequal with zero error tolerances. |

409 | n/a | # Test cases for unequal values, with exact equality test. |

410 | n/a | |

411 | n/a | def do_exactly_unequal_test(self, x): |

412 | n/a | for a in (x, -x): |

413 | n/a | result = approx_equal(a, a+1, tol=0, rel=0) |

414 | n/a | self.assertFalse(result, 'inequality failure for x=%r' % a) |

415 | n/a | |

416 | n/a | def test_exactly_unequal_ints(self): |

417 | n/a | # Test unequal int values are unequal with zero error tolerance. |

418 | n/a | for n in [951, 572305, 478, 917, 17240]: |

419 | n/a | self.do_exactly_unequal_test(n) |

420 | n/a | |

421 | n/a | def test_exactly_unequal_floats(self): |

422 | n/a | # Test unequal float values are unequal with zero error tolerance. |

423 | n/a | for x in [9.51, 5723.05, 47.8, 9.17, 17.24]: |

424 | n/a | self.do_exactly_unequal_test(x) |

425 | n/a | |

426 | n/a | def test_exactly_unequal_fractions(self): |

427 | n/a | # Test that unequal Fractions are unequal with zero error tolerance. |

428 | n/a | F = Fraction |

429 | n/a | for f in [F(1, 5), F(7, 9), F(12, 11), F(101, 99023)]: |

430 | n/a | self.do_exactly_unequal_test(f) |

431 | n/a | |

432 | n/a | def test_exactly_unequal_decimals(self): |

433 | n/a | # Test that unequal Decimals are unequal with zero error tolerance. |

434 | n/a | for d in map(Decimal, "3.1415 298.12 3.47 18.996 0.00245".split()): |

435 | n/a | self.do_exactly_unequal_test(d) |

436 | n/a | |

437 | n/a | |

438 | n/a | class ApproxEqualInexactTest(unittest.TestCase): |

439 | n/a | # Inexact test cases for approx_error. |

440 | n/a | # Test cases when comparing two values that are not exactly equal. |

441 | n/a | |

442 | n/a | # === Absolute error tests === |

443 | n/a | |

444 | n/a | def do_approx_equal_abs_test(self, x, delta): |

445 | n/a | template = "Test failure for x={!r}, y={!r}" |

446 | n/a | for y in (x + delta, x - delta): |

447 | n/a | msg = template.format(x, y) |

448 | n/a | self.assertTrue(approx_equal(x, y, tol=2*delta, rel=0), msg) |

449 | n/a | self.assertFalse(approx_equal(x, y, tol=delta/2, rel=0), msg) |

450 | n/a | |

451 | n/a | def test_approx_equal_absolute_ints(self): |

452 | n/a | # Test approximate equality of ints with an absolute error. |

453 | n/a | for n in [-10737, -1975, -7, -2, 0, 1, 9, 37, 423, 9874, 23789110]: |

454 | n/a | self.do_approx_equal_abs_test(n, 10) |

455 | n/a | self.do_approx_equal_abs_test(n, 2) |

456 | n/a | |

457 | n/a | def test_approx_equal_absolute_floats(self): |

458 | n/a | # Test approximate equality of floats with an absolute error. |

459 | n/a | for x in [-284.126, -97.1, -3.4, -2.15, 0.5, 1.0, 7.8, 4.23, 3817.4]: |

460 | n/a | self.do_approx_equal_abs_test(x, 1.5) |

461 | n/a | self.do_approx_equal_abs_test(x, 0.01) |

462 | n/a | self.do_approx_equal_abs_test(x, 0.0001) |

463 | n/a | |

464 | n/a | def test_approx_equal_absolute_fractions(self): |

465 | n/a | # Test approximate equality of Fractions with an absolute error. |

466 | n/a | delta = Fraction(1, 29) |

467 | n/a | numerators = [-84, -15, -2, -1, 0, 1, 5, 17, 23, 34, 71] |

468 | n/a | for f in (Fraction(n, 29) for n in numerators): |

469 | n/a | self.do_approx_equal_abs_test(f, delta) |

470 | n/a | self.do_approx_equal_abs_test(f, float(delta)) |

471 | n/a | |

472 | n/a | def test_approx_equal_absolute_decimals(self): |

473 | n/a | # Test approximate equality of Decimals with an absolute error. |

474 | n/a | delta = Decimal("0.01") |

475 | n/a | for d in map(Decimal, "1.0 3.5 36.08 61.79 7912.3648".split()): |

476 | n/a | self.do_approx_equal_abs_test(d, delta) |

477 | n/a | self.do_approx_equal_abs_test(-d, delta) |

478 | n/a | |

479 | n/a | def test_cross_zero(self): |

480 | n/a | # Test for the case of the two values having opposite signs. |

481 | n/a | self.assertTrue(approx_equal(1e-5, -1e-5, tol=1e-4, rel=0)) |

482 | n/a | |

483 | n/a | # === Relative error tests === |

484 | n/a | |

485 | n/a | def do_approx_equal_rel_test(self, x, delta): |

486 | n/a | template = "Test failure for x={!r}, y={!r}" |

487 | n/a | for y in (x*(1+delta), x*(1-delta)): |

488 | n/a | msg = template.format(x, y) |

489 | n/a | self.assertTrue(approx_equal(x, y, tol=0, rel=2*delta), msg) |

490 | n/a | self.assertFalse(approx_equal(x, y, tol=0, rel=delta/2), msg) |

491 | n/a | |

492 | n/a | def test_approx_equal_relative_ints(self): |

493 | n/a | # Test approximate equality of ints with a relative error. |

494 | n/a | self.assertTrue(approx_equal(64, 47, tol=0, rel=0.36)) |

495 | n/a | self.assertTrue(approx_equal(64, 47, tol=0, rel=0.37)) |

496 | n/a | # --- |

497 | n/a | self.assertTrue(approx_equal(449, 512, tol=0, rel=0.125)) |

498 | n/a | self.assertTrue(approx_equal(448, 512, tol=0, rel=0.125)) |

499 | n/a | self.assertFalse(approx_equal(447, 512, tol=0, rel=0.125)) |

500 | n/a | |

501 | n/a | def test_approx_equal_relative_floats(self): |

502 | n/a | # Test approximate equality of floats with a relative error. |

503 | n/a | for x in [-178.34, -0.1, 0.1, 1.0, 36.97, 2847.136, 9145.074]: |

504 | n/a | self.do_approx_equal_rel_test(x, 0.02) |

505 | n/a | self.do_approx_equal_rel_test(x, 0.0001) |

506 | n/a | |

507 | n/a | def test_approx_equal_relative_fractions(self): |

508 | n/a | # Test approximate equality of Fractions with a relative error. |

509 | n/a | F = Fraction |

510 | n/a | delta = Fraction(3, 8) |

511 | n/a | for f in [F(3, 84), F(17, 30), F(49, 50), F(92, 85)]: |

512 | n/a | for d in (delta, float(delta)): |

513 | n/a | self.do_approx_equal_rel_test(f, d) |

514 | n/a | self.do_approx_equal_rel_test(-f, d) |

515 | n/a | |

516 | n/a | def test_approx_equal_relative_decimals(self): |

517 | n/a | # Test approximate equality of Decimals with a relative error. |

518 | n/a | for d in map(Decimal, "0.02 1.0 5.7 13.67 94.138 91027.9321".split()): |

519 | n/a | self.do_approx_equal_rel_test(d, Decimal("0.001")) |

520 | n/a | self.do_approx_equal_rel_test(-d, Decimal("0.05")) |

521 | n/a | |

522 | n/a | # === Both absolute and relative error tests === |

523 | n/a | |

524 | n/a | # There are four cases to consider: |

525 | n/a | # 1) actual error <= both absolute and relative error |

526 | n/a | # 2) actual error <= absolute error but > relative error |

527 | n/a | # 3) actual error <= relative error but > absolute error |

528 | n/a | # 4) actual error > both absolute and relative error |

529 | n/a | |

530 | n/a | def do_check_both(self, a, b, tol, rel, tol_flag, rel_flag): |

531 | n/a | check = self.assertTrue if tol_flag else self.assertFalse |

532 | n/a | check(approx_equal(a, b, tol=tol, rel=0)) |

533 | n/a | check = self.assertTrue if rel_flag else self.assertFalse |

534 | n/a | check(approx_equal(a, b, tol=0, rel=rel)) |

535 | n/a | check = self.assertTrue if (tol_flag or rel_flag) else self.assertFalse |

536 | n/a | check(approx_equal(a, b, tol=tol, rel=rel)) |

537 | n/a | |

538 | n/a | def test_approx_equal_both1(self): |

539 | n/a | # Test actual error <= both absolute and relative error. |

540 | n/a | self.do_check_both(7.955, 7.952, 0.004, 3.8e-4, True, True) |

541 | n/a | self.do_check_both(-7.387, -7.386, 0.002, 0.0002, True, True) |

542 | n/a | |

543 | n/a | def test_approx_equal_both2(self): |

544 | n/a | # Test actual error <= absolute error but > relative error. |

545 | n/a | self.do_check_both(7.955, 7.952, 0.004, 3.7e-4, True, False) |

546 | n/a | |

547 | n/a | def test_approx_equal_both3(self): |

548 | n/a | # Test actual error <= relative error but > absolute error. |

549 | n/a | self.do_check_both(7.955, 7.952, 0.001, 3.8e-4, False, True) |

550 | n/a | |

551 | n/a | def test_approx_equal_both4(self): |

552 | n/a | # Test actual error > both absolute and relative error. |

553 | n/a | self.do_check_both(2.78, 2.75, 0.01, 0.001, False, False) |

554 | n/a | self.do_check_both(971.44, 971.47, 0.02, 3e-5, False, False) |

555 | n/a | |

556 | n/a | |

557 | n/a | class ApproxEqualSpecialsTest(unittest.TestCase): |

558 | n/a | # Test approx_equal with NANs and INFs and zeroes. |

559 | n/a | |

560 | n/a | def test_inf(self): |

561 | n/a | for type_ in (float, Decimal): |

562 | n/a | inf = type_('inf') |

563 | n/a | self.assertTrue(approx_equal(inf, inf)) |

564 | n/a | self.assertTrue(approx_equal(inf, inf, 0, 0)) |

565 | n/a | self.assertTrue(approx_equal(inf, inf, 1, 0.01)) |

566 | n/a | self.assertTrue(approx_equal(-inf, -inf)) |

567 | n/a | self.assertFalse(approx_equal(inf, -inf)) |

568 | n/a | self.assertFalse(approx_equal(inf, 1000)) |

569 | n/a | |

570 | n/a | def test_nan(self): |

571 | n/a | for type_ in (float, Decimal): |

572 | n/a | nan = type_('nan') |

573 | n/a | for other in (nan, type_('inf'), 1000): |

574 | n/a | self.assertFalse(approx_equal(nan, other)) |

575 | n/a | |

576 | n/a | def test_float_zeroes(self): |

577 | n/a | nzero = math.copysign(0.0, -1) |

578 | n/a | self.assertTrue(approx_equal(nzero, 0.0, tol=0.1, rel=0.1)) |

579 | n/a | |

580 | n/a | def test_decimal_zeroes(self): |

581 | n/a | nzero = Decimal("-0.0") |

582 | n/a | self.assertTrue(approx_equal(nzero, Decimal(0), tol=0.1, rel=0.1)) |

583 | n/a | |

584 | n/a | |

585 | n/a | class TestApproxEqualErrors(unittest.TestCase): |

586 | n/a | # Test error conditions of approx_equal. |

587 | n/a | |

588 | n/a | def test_bad_tol(self): |

589 | n/a | # Test negative tol raises. |

590 | n/a | self.assertRaises(ValueError, approx_equal, 100, 100, -1, 0.1) |

591 | n/a | |

592 | n/a | def test_bad_rel(self): |

593 | n/a | # Test negative rel raises. |

594 | n/a | self.assertRaises(ValueError, approx_equal, 100, 100, 1, -0.1) |

595 | n/a | |

596 | n/a | |

597 | n/a | # --- Tests for NumericTestCase --- |

598 | n/a | |

599 | n/a | # The formatting routine that generates the error messages is complex enough |

600 | n/a | # that it too needs testing. |

601 | n/a | |

602 | n/a | class TestNumericTestCase(unittest.TestCase): |

603 | n/a | # The exact wording of NumericTestCase error messages is *not* guaranteed, |

604 | n/a | # but we need to give them some sort of test to ensure that they are |

605 | n/a | # generated correctly. As a compromise, we look for specific substrings |

606 | n/a | # that are expected to be found even if the overall error message changes. |

607 | n/a | |

608 | n/a | def do_test(self, args): |

609 | n/a | actual_msg = NumericTestCase._make_std_err_msg(*args) |

610 | n/a | expected = self.generate_substrings(*args) |

611 | n/a | for substring in expected: |

612 | n/a | self.assertIn(substring, actual_msg) |

613 | n/a | |

614 | n/a | def test_numerictestcase_is_testcase(self): |

615 | n/a | # Ensure that NumericTestCase actually is a TestCase. |

616 | n/a | self.assertTrue(issubclass(NumericTestCase, unittest.TestCase)) |

617 | n/a | |

618 | n/a | def test_error_msg_numeric(self): |

619 | n/a | # Test the error message generated for numeric comparisons. |

620 | n/a | args = (2.5, 4.0, 0.5, 0.25, None) |

621 | n/a | self.do_test(args) |

622 | n/a | |

623 | n/a | def test_error_msg_sequence(self): |

624 | n/a | # Test the error message generated for sequence comparisons. |

625 | n/a | args = (3.75, 8.25, 1.25, 0.5, 7) |

626 | n/a | self.do_test(args) |

627 | n/a | |

628 | n/a | def generate_substrings(self, first, second, tol, rel, idx): |

629 | n/a | """Return substrings we expect to see in error messages.""" |

630 | n/a | abs_err, rel_err = _calc_errors(first, second) |

631 | n/a | substrings = [ |

632 | n/a | 'tol=%r' % tol, |

633 | n/a | 'rel=%r' % rel, |

634 | n/a | 'absolute error = %r' % abs_err, |

635 | n/a | 'relative error = %r' % rel_err, |

636 | n/a | ] |

637 | n/a | if idx is not None: |

638 | n/a | substrings.append('differ at index %d' % idx) |

639 | n/a | return substrings |

640 | n/a | |

641 | n/a | |

642 | n/a | # ======================================= |

643 | n/a | # === Tests for the statistics module === |

644 | n/a | # ======================================= |

645 | n/a | |

646 | n/a | |

647 | n/a | class GlobalsTest(unittest.TestCase): |

648 | n/a | module = statistics |

649 | n/a | expected_metadata = ["__doc__", "__all__"] |

650 | n/a | |

651 | n/a | def test_meta(self): |

652 | n/a | # Test for the existence of metadata. |

653 | n/a | for meta in self.expected_metadata: |

654 | n/a | self.assertTrue(hasattr(self.module, meta), |

655 | n/a | "%s not present" % meta) |

656 | n/a | |

657 | n/a | def test_check_all(self): |

658 | n/a | # Check everything in __all__ exists and is public. |

659 | n/a | module = self.module |

660 | n/a | for name in module.__all__: |

661 | n/a | # No private names in __all__: |

662 | n/a | self.assertFalse(name.startswith("_"), |

663 | n/a | 'private name "%s" in __all__' % name) |

664 | n/a | # And anything in __all__ must exist: |

665 | n/a | self.assertTrue(hasattr(module, name), |

666 | n/a | 'missing name "%s" in __all__' % name) |

667 | n/a | |

668 | n/a | |

669 | n/a | class DocTests(unittest.TestCase): |

670 | n/a | @unittest.skipIf(sys.flags.optimize >= 2, |

671 | n/a | "Docstrings are omitted with -OO and above") |

672 | n/a | def test_doc_tests(self): |

673 | n/a | failed, tried = doctest.testmod(statistics, optionflags=doctest.ELLIPSIS) |

674 | n/a | self.assertGreater(tried, 0) |

675 | n/a | self.assertEqual(failed, 0) |

676 | n/a | |

677 | n/a | class StatisticsErrorTest(unittest.TestCase): |

678 | n/a | def test_has_exception(self): |

679 | n/a | errmsg = ( |

680 | n/a | "Expected StatisticsError to be a ValueError, but got a" |

681 | n/a | " subclass of %r instead." |

682 | n/a | ) |

683 | n/a | self.assertTrue(hasattr(statistics, 'StatisticsError')) |

684 | n/a | self.assertTrue( |

685 | n/a | issubclass(statistics.StatisticsError, ValueError), |

686 | n/a | errmsg % statistics.StatisticsError.__base__ |

687 | n/a | ) |

688 | n/a | |

689 | n/a | |

690 | n/a | # === Tests for private utility functions === |

691 | n/a | |

692 | n/a | class ExactRatioTest(unittest.TestCase): |

693 | n/a | # Test _exact_ratio utility. |

694 | n/a | |

695 | n/a | def test_int(self): |

696 | n/a | for i in (-20, -3, 0, 5, 99, 10**20): |

697 | n/a | self.assertEqual(statistics._exact_ratio(i), (i, 1)) |

698 | n/a | |

699 | n/a | def test_fraction(self): |

700 | n/a | numerators = (-5, 1, 12, 38) |

701 | n/a | for n in numerators: |

702 | n/a | f = Fraction(n, 37) |

703 | n/a | self.assertEqual(statistics._exact_ratio(f), (n, 37)) |

704 | n/a | |

705 | n/a | def test_float(self): |

706 | n/a | self.assertEqual(statistics._exact_ratio(0.125), (1, 8)) |

707 | n/a | self.assertEqual(statistics._exact_ratio(1.125), (9, 8)) |

708 | n/a | data = [random.uniform(-100, 100) for _ in range(100)] |

709 | n/a | for x in data: |

710 | n/a | num, den = statistics._exact_ratio(x) |

711 | n/a | self.assertEqual(x, num/den) |

712 | n/a | |

713 | n/a | def test_decimal(self): |

714 | n/a | D = Decimal |

715 | n/a | _exact_ratio = statistics._exact_ratio |

716 | n/a | self.assertEqual(_exact_ratio(D("0.125")), (1, 8)) |

717 | n/a | self.assertEqual(_exact_ratio(D("12.345")), (2469, 200)) |

718 | n/a | self.assertEqual(_exact_ratio(D("-1.98")), (-99, 50)) |

719 | n/a | |

720 | n/a | def test_inf(self): |

721 | n/a | INF = float("INF") |

722 | n/a | class MyFloat(float): |

723 | n/a | pass |

724 | n/a | class MyDecimal(Decimal): |

725 | n/a | pass |

726 | n/a | for inf in (INF, -INF): |

727 | n/a | for type_ in (float, MyFloat, Decimal, MyDecimal): |

728 | n/a | x = type_(inf) |

729 | n/a | ratio = statistics._exact_ratio(x) |

730 | n/a | self.assertEqual(ratio, (x, None)) |

731 | n/a | self.assertEqual(type(ratio[0]), type_) |

732 | n/a | self.assertTrue(math.isinf(ratio[0])) |

733 | n/a | |

734 | n/a | def test_float_nan(self): |

735 | n/a | NAN = float("NAN") |

736 | n/a | class MyFloat(float): |

737 | n/a | pass |

738 | n/a | for nan in (NAN, MyFloat(NAN)): |

739 | n/a | ratio = statistics._exact_ratio(nan) |

740 | n/a | self.assertTrue(math.isnan(ratio[0])) |

741 | n/a | self.assertIs(ratio[1], None) |

742 | n/a | self.assertEqual(type(ratio[0]), type(nan)) |

743 | n/a | |

744 | n/a | def test_decimal_nan(self): |

745 | n/a | NAN = Decimal("NAN") |

746 | n/a | sNAN = Decimal("sNAN") |

747 | n/a | class MyDecimal(Decimal): |

748 | n/a | pass |

749 | n/a | for nan in (NAN, MyDecimal(NAN), sNAN, MyDecimal(sNAN)): |

750 | n/a | ratio = statistics._exact_ratio(nan) |

751 | n/a | self.assertTrue(_nan_equal(ratio[0], nan)) |

752 | n/a | self.assertIs(ratio[1], None) |

753 | n/a | self.assertEqual(type(ratio[0]), type(nan)) |

754 | n/a | |

755 | n/a | |

756 | n/a | class DecimalToRatioTest(unittest.TestCase): |

757 | n/a | # Test _exact_ratio private function. |

758 | n/a | |

759 | n/a | def test_infinity(self): |

760 | n/a | # Test that INFs are handled correctly. |

761 | n/a | inf = Decimal('INF') |

762 | n/a | self.assertEqual(statistics._exact_ratio(inf), (inf, None)) |

763 | n/a | self.assertEqual(statistics._exact_ratio(-inf), (-inf, None)) |

764 | n/a | |

765 | n/a | def test_nan(self): |

766 | n/a | # Test that NANs are handled correctly. |

767 | n/a | for nan in (Decimal('NAN'), Decimal('sNAN')): |

768 | n/a | num, den = statistics._exact_ratio(nan) |

769 | n/a | # Because NANs always compare non-equal, we cannot use assertEqual. |

770 | n/a | # Nor can we use an identity test, as we don't guarantee anything |

771 | n/a | # about the object identity. |

772 | n/a | self.assertTrue(_nan_equal(num, nan)) |

773 | n/a | self.assertIs(den, None) |

774 | n/a | |

775 | n/a | def test_sign(self): |

776 | n/a | # Test sign is calculated correctly. |

777 | n/a | numbers = [Decimal("9.8765e12"), Decimal("9.8765e-12")] |

778 | n/a | for d in numbers: |

779 | n/a | # First test positive decimals. |

780 | n/a | assert d > 0 |

781 | n/a | num, den = statistics._exact_ratio(d) |

782 | n/a | self.assertGreaterEqual(num, 0) |

783 | n/a | self.assertGreater(den, 0) |

784 | n/a | # Then test negative decimals. |

785 | n/a | num, den = statistics._exact_ratio(-d) |

786 | n/a | self.assertLessEqual(num, 0) |

787 | n/a | self.assertGreater(den, 0) |

788 | n/a | |

789 | n/a | def test_negative_exponent(self): |

790 | n/a | # Test result when the exponent is negative. |

791 | n/a | t = statistics._exact_ratio(Decimal("0.1234")) |

792 | n/a | self.assertEqual(t, (617, 5000)) |

793 | n/a | |

794 | n/a | def test_positive_exponent(self): |

795 | n/a | # Test results when the exponent is positive. |

796 | n/a | t = statistics._exact_ratio(Decimal("1.234e7")) |

797 | n/a | self.assertEqual(t, (12340000, 1)) |

798 | n/a | |

799 | n/a | def test_regression_20536(self): |

800 | n/a | # Regression test for issue 20536. |

801 | n/a | # See http://bugs.python.org/issue20536 |

802 | n/a | t = statistics._exact_ratio(Decimal("1e2")) |

803 | n/a | self.assertEqual(t, (100, 1)) |

804 | n/a | t = statistics._exact_ratio(Decimal("1.47e5")) |

805 | n/a | self.assertEqual(t, (147000, 1)) |

806 | n/a | |

807 | n/a | |

808 | n/a | class IsFiniteTest(unittest.TestCase): |

809 | n/a | # Test _isfinite private function. |

810 | n/a | |

811 | n/a | def test_finite(self): |

812 | n/a | # Test that finite numbers are recognised as finite. |

813 | n/a | for x in (5, Fraction(1, 3), 2.5, Decimal("5.5")): |

814 | n/a | self.assertTrue(statistics._isfinite(x)) |

815 | n/a | |

816 | n/a | def test_infinity(self): |

817 | n/a | # Test that INFs are not recognised as finite. |

818 | n/a | for x in (float("inf"), Decimal("inf")): |

819 | n/a | self.assertFalse(statistics._isfinite(x)) |

820 | n/a | |

821 | n/a | def test_nan(self): |

822 | n/a | # Test that NANs are not recognised as finite. |

823 | n/a | for x in (float("nan"), Decimal("NAN"), Decimal("sNAN")): |

824 | n/a | self.assertFalse(statistics._isfinite(x)) |

825 | n/a | |

826 | n/a | |

827 | n/a | class CoerceTest(unittest.TestCase): |

828 | n/a | # Test that private function _coerce correctly deals with types. |

829 | n/a | |

830 | n/a | # The coercion rules are currently an implementation detail, although at |

831 | n/a | # some point that should change. The tests and comments here define the |

832 | n/a | # correct implementation. |

833 | n/a | |

834 | n/a | # Pre-conditions of _coerce: |

835 | n/a | # |

836 | n/a | # - The first time _sum calls _coerce, the |

837 | n/a | # - coerce(T, S) will never be called with bool as the first argument; |

838 | n/a | # this is a pre-condition, guarded with an assertion. |

839 | n/a | |

840 | n/a | # |

841 | n/a | # - coerce(T, T) will always return T; we assume T is a valid numeric |

842 | n/a | # type. Violate this assumption at your own risk. |

843 | n/a | # |

844 | n/a | # - Apart from as above, bool is treated as if it were actually int. |

845 | n/a | # |

846 | n/a | # - coerce(int, X) and coerce(X, int) return X. |

847 | n/a | # - |

848 | n/a | def test_bool(self): |

849 | n/a | # bool is somewhat special, due to the pre-condition that it is |

850 | n/a | # never given as the first argument to _coerce, and that it cannot |

851 | n/a | # be subclassed. So we test it specially. |

852 | n/a | for T in (int, float, Fraction, Decimal): |

853 | n/a | self.assertIs(statistics._coerce(T, bool), T) |

854 | n/a | class MyClass(T): pass |

855 | n/a | self.assertIs(statistics._coerce(MyClass, bool), MyClass) |

856 | n/a | |

857 | n/a | def assertCoerceTo(self, A, B): |

858 | n/a | """Assert that type A coerces to B.""" |

859 | n/a | self.assertIs(statistics._coerce(A, B), B) |

860 | n/a | self.assertIs(statistics._coerce(B, A), B) |

861 | n/a | |

862 | n/a | def check_coerce_to(self, A, B): |

863 | n/a | """Checks that type A coerces to B, including subclasses.""" |

864 | n/a | # Assert that type A is coerced to B. |

865 | n/a | self.assertCoerceTo(A, B) |

866 | n/a | # Subclasses of A are also coerced to B. |

867 | n/a | class SubclassOfA(A): pass |

868 | n/a | self.assertCoerceTo(SubclassOfA, B) |

869 | n/a | # A, and subclasses of A, are coerced to subclasses of B. |

870 | n/a | class SubclassOfB(B): pass |

871 | n/a | self.assertCoerceTo(A, SubclassOfB) |

872 | n/a | self.assertCoerceTo(SubclassOfA, SubclassOfB) |

873 | n/a | |

874 | n/a | def assertCoerceRaises(self, A, B): |

875 | n/a | """Assert that coercing A to B, or vice versa, raises TypeError.""" |

876 | n/a | self.assertRaises(TypeError, statistics._coerce, (A, B)) |

877 | n/a | self.assertRaises(TypeError, statistics._coerce, (B, A)) |

878 | n/a | |

879 | n/a | def check_type_coercions(self, T): |

880 | n/a | """Check that type T coerces correctly with subclasses of itself.""" |

881 | n/a | assert T is not bool |

882 | n/a | # Coercing a type with itself returns the same type. |

883 | n/a | self.assertIs(statistics._coerce(T, T), T) |

884 | n/a | # Coercing a type with a subclass of itself returns the subclass. |

885 | n/a | class U(T): pass |

886 | n/a | class V(T): pass |

887 | n/a | class W(U): pass |

888 | n/a | for typ in (U, V, W): |

889 | n/a | self.assertCoerceTo(T, typ) |

890 | n/a | self.assertCoerceTo(U, W) |

891 | n/a | # Coercing two subclasses that aren't parent/child is an error. |

892 | n/a | self.assertCoerceRaises(U, V) |

893 | n/a | self.assertCoerceRaises(V, W) |

894 | n/a | |

895 | n/a | def test_int(self): |

896 | n/a | # Check that int coerces correctly. |

897 | n/a | self.check_type_coercions(int) |

898 | n/a | for typ in (float, Fraction, Decimal): |

899 | n/a | self.check_coerce_to(int, typ) |

900 | n/a | |

901 | n/a | def test_fraction(self): |

902 | n/a | # Check that Fraction coerces correctly. |

903 | n/a | self.check_type_coercions(Fraction) |

904 | n/a | self.check_coerce_to(Fraction, float) |

905 | n/a | |

906 | n/a | def test_decimal(self): |

907 | n/a | # Check that Decimal coerces correctly. |

908 | n/a | self.check_type_coercions(Decimal) |

909 | n/a | |

910 | n/a | def test_float(self): |

911 | n/a | # Check that float coerces correctly. |

912 | n/a | self.check_type_coercions(float) |

913 | n/a | |

914 | n/a | def test_non_numeric_types(self): |

915 | n/a | for bad_type in (str, list, type(None), tuple, dict): |

916 | n/a | for good_type in (int, float, Fraction, Decimal): |

917 | n/a | self.assertCoerceRaises(good_type, bad_type) |

918 | n/a | |

919 | n/a | def test_incompatible_types(self): |

920 | n/a | # Test that incompatible types raise. |

921 | n/a | for T in (float, Fraction): |

922 | n/a | class MySubclass(T): pass |

923 | n/a | self.assertCoerceRaises(T, Decimal) |

924 | n/a | self.assertCoerceRaises(MySubclass, Decimal) |

925 | n/a | |

926 | n/a | |

927 | n/a | class ConvertTest(unittest.TestCase): |

928 | n/a | # Test private _convert function. |

929 | n/a | |

930 | n/a | def check_exact_equal(self, x, y): |

931 | n/a | """Check that x equals y, and has the same type as well.""" |

932 | n/a | self.assertEqual(x, y) |

933 | n/a | self.assertIs(type(x), type(y)) |

934 | n/a | |

935 | n/a | def test_int(self): |

936 | n/a | # Test conversions to int. |

937 | n/a | x = statistics._convert(Fraction(71), int) |

938 | n/a | self.check_exact_equal(x, 71) |

939 | n/a | class MyInt(int): pass |

940 | n/a | x = statistics._convert(Fraction(17), MyInt) |

941 | n/a | self.check_exact_equal(x, MyInt(17)) |

942 | n/a | |

943 | n/a | def test_fraction(self): |

944 | n/a | # Test conversions to Fraction. |

945 | n/a | x = statistics._convert(Fraction(95, 99), Fraction) |

946 | n/a | self.check_exact_equal(x, Fraction(95, 99)) |

947 | n/a | class MyFraction(Fraction): |

948 | n/a | def __truediv__(self, other): |

949 | n/a | return self.__class__(super().__truediv__(other)) |

950 | n/a | x = statistics._convert(Fraction(71, 13), MyFraction) |

951 | n/a | self.check_exact_equal(x, MyFraction(71, 13)) |

952 | n/a | |

953 | n/a | def test_float(self): |

954 | n/a | # Test conversions to float. |

955 | n/a | x = statistics._convert(Fraction(-1, 2), float) |

956 | n/a | self.check_exact_equal(x, -0.5) |

957 | n/a | class MyFloat(float): |

958 | n/a | def __truediv__(self, other): |

959 | n/a | return self.__class__(super().__truediv__(other)) |

960 | n/a | x = statistics._convert(Fraction(9, 8), MyFloat) |

961 | n/a | self.check_exact_equal(x, MyFloat(1.125)) |

962 | n/a | |

963 | n/a | def test_decimal(self): |

964 | n/a | # Test conversions to Decimal. |

965 | n/a | x = statistics._convert(Fraction(1, 40), Decimal) |

966 | n/a | self.check_exact_equal(x, Decimal("0.025")) |

967 | n/a | class MyDecimal(Decimal): |

968 | n/a | def __truediv__(self, other): |

969 | n/a | return self.__class__(super().__truediv__(other)) |

970 | n/a | x = statistics._convert(Fraction(-15, 16), MyDecimal) |

971 | n/a | self.check_exact_equal(x, MyDecimal("-0.9375")) |

972 | n/a | |

973 | n/a | def test_inf(self): |

974 | n/a | for INF in (float('inf'), Decimal('inf')): |

975 | n/a | for inf in (INF, -INF): |

976 | n/a | x = statistics._convert(inf, type(inf)) |

977 | n/a | self.check_exact_equal(x, inf) |

978 | n/a | |

979 | n/a | def test_nan(self): |

980 | n/a | for nan in (float('nan'), Decimal('NAN'), Decimal('sNAN')): |

981 | n/a | x = statistics._convert(nan, type(nan)) |

982 | n/a | self.assertTrue(_nan_equal(x, nan)) |

983 | n/a | |

984 | n/a | |

985 | n/a | class FailNegTest(unittest.TestCase): |

986 | n/a | """Test _fail_neg private function.""" |

987 | n/a | |

988 | n/a | def test_pass_through(self): |

989 | n/a | # Test that values are passed through unchanged. |

990 | n/a | values = [1, 2.0, Fraction(3), Decimal(4)] |

991 | n/a | new = list(statistics._fail_neg(values)) |

992 | n/a | self.assertEqual(values, new) |

993 | n/a | |

994 | n/a | def test_negatives_raise(self): |

995 | n/a | # Test that negatives raise an exception. |

996 | n/a | for x in [1, 2.0, Fraction(3), Decimal(4)]: |

997 | n/a | seq = [-x] |

998 | n/a | it = statistics._fail_neg(seq) |

999 | n/a | self.assertRaises(statistics.StatisticsError, next, it) |

1000 | n/a | |

1001 | n/a | def test_error_msg(self): |

1002 | n/a | # Test that a given error message is used. |

1003 | n/a | msg = "badness #%d" % random.randint(10000, 99999) |

1004 | n/a | try: |

1005 | n/a | next(statistics._fail_neg([-1], msg)) |

1006 | n/a | except statistics.StatisticsError as e: |

1007 | n/a | errmsg = e.args[0] |

1008 | n/a | else: |

1009 | n/a | self.fail("expected exception, but it didn't happen") |

1010 | n/a | self.assertEqual(errmsg, msg) |

1011 | n/a | |

1012 | n/a | |

1013 | n/a | # === Tests for public functions === |

1014 | n/a | |

1015 | n/a | class UnivariateCommonMixin: |

1016 | n/a | # Common tests for most univariate functions that take a data argument. |

1017 | n/a | |

1018 | n/a | def test_no_args(self): |

1019 | n/a | # Fail if given no arguments. |

1020 | n/a | self.assertRaises(TypeError, self.func) |

1021 | n/a | |

1022 | n/a | def test_empty_data(self): |

1023 | n/a | # Fail when the data argument (first argument) is empty. |

1024 | n/a | for empty in ([], (), iter([])): |

1025 | n/a | self.assertRaises(statistics.StatisticsError, self.func, empty) |

1026 | n/a | |

1027 | n/a | def prepare_data(self): |

1028 | n/a | """Return int data for various tests.""" |

1029 | n/a | data = list(range(10)) |

1030 | n/a | while data == sorted(data): |

1031 | n/a | random.shuffle(data) |

1032 | n/a | return data |

1033 | n/a | |

1034 | n/a | def test_no_inplace_modifications(self): |

1035 | n/a | # Test that the function does not modify its input data. |

1036 | n/a | data = self.prepare_data() |

1037 | n/a | assert len(data) != 1 # Necessary to avoid infinite loop. |

1038 | n/a | assert data != sorted(data) |

1039 | n/a | saved = data[:] |

1040 | n/a | assert data is not saved |

1041 | n/a | _ = self.func(data) |

1042 | n/a | self.assertListEqual(data, saved, "data has been modified") |

1043 | n/a | |

1044 | n/a | def test_order_doesnt_matter(self): |

1045 | n/a | # Test that the order of data points doesn't change the result. |

1046 | n/a | |

1047 | n/a | # CAUTION: due to floating point rounding errors, the result actually |

1048 | n/a | # may depend on the order. Consider this test representing an ideal. |

1049 | n/a | # To avoid this test failing, only test with exact values such as ints |

1050 | n/a | # or Fractions. |

1051 | n/a | data = [1, 2, 3, 3, 3, 4, 5, 6]*100 |

1052 | n/a | expected = self.func(data) |

1053 | n/a | random.shuffle(data) |

1054 | n/a | actual = self.func(data) |

1055 | n/a | self.assertEqual(expected, actual) |

1056 | n/a | |

1057 | n/a | def test_type_of_data_collection(self): |

1058 | n/a | # Test that the type of iterable data doesn't effect the result. |

1059 | n/a | class MyList(list): |

1060 | n/a | pass |

1061 | n/a | class MyTuple(tuple): |

1062 | n/a | pass |

1063 | n/a | def generator(data): |

1064 | n/a | return (obj for obj in data) |

1065 | n/a | data = self.prepare_data() |

1066 | n/a | expected = self.func(data) |

1067 | n/a | for kind in (list, tuple, iter, MyList, MyTuple, generator): |

1068 | n/a | result = self.func(kind(data)) |

1069 | n/a | self.assertEqual(result, expected) |

1070 | n/a | |

1071 | n/a | def test_range_data(self): |

1072 | n/a | # Test that functions work with range objects. |

1073 | n/a | data = range(20, 50, 3) |

1074 | n/a | expected = self.func(list(data)) |

1075 | n/a | self.assertEqual(self.func(data), expected) |

1076 | n/a | |

1077 | n/a | def test_bad_arg_types(self): |

1078 | n/a | # Test that function raises when given data of the wrong type. |

1079 | n/a | |

1080 | n/a | # Don't roll the following into a loop like this: |

1081 | n/a | # for bad in list_of_bad: |

1082 | n/a | # self.check_for_type_error(bad) |

1083 | n/a | # |

1084 | n/a | # Since assertRaises doesn't show the arguments that caused the test |

1085 | n/a | # failure, it is very difficult to debug these test failures when the |

1086 | n/a | # following are in a loop. |

1087 | n/a | self.check_for_type_error(None) |

1088 | n/a | self.check_for_type_error(23) |

1089 | n/a | self.check_for_type_error(42.0) |

1090 | n/a | self.check_for_type_error(object()) |

1091 | n/a | |

1092 | n/a | def check_for_type_error(self, *args): |

1093 | n/a | self.assertRaises(TypeError, self.func, *args) |

1094 | n/a | |

1095 | n/a | def test_type_of_data_element(self): |

1096 | n/a | # Check the type of data elements doesn't affect the numeric result. |

1097 | n/a | # This is a weaker test than UnivariateTypeMixin.testTypesConserved, |

1098 | n/a | # because it checks the numeric result by equality, but not by type. |

1099 | n/a | class MyFloat(float): |

1100 | n/a | def __truediv__(self, other): |

1101 | n/a | return type(self)(super().__truediv__(other)) |

1102 | n/a | def __add__(self, other): |

1103 | n/a | return type(self)(super().__add__(other)) |

1104 | n/a | __radd__ = __add__ |

1105 | n/a | |

1106 | n/a | raw = self.prepare_data() |

1107 | n/a | expected = self.func(raw) |

1108 | n/a | for kind in (float, MyFloat, Decimal, Fraction): |

1109 | n/a | data = [kind(x) for x in raw] |

1110 | n/a | result = type(expected)(self.func(data)) |

1111 | n/a | self.assertEqual(result, expected) |

1112 | n/a | |

1113 | n/a | |

1114 | n/a | class UnivariateTypeMixin: |

1115 | n/a | """Mixin class for type-conserving functions. |

1116 | n/a | |

1117 | n/a | This mixin class holds test(s) for functions which conserve the type of |

1118 | n/a | individual data points. E.g. the mean of a list of Fractions should itself |

1119 | n/a | be a Fraction. |

1120 | n/a | |

1121 | n/a | Not all tests to do with types need go in this class. Only those that |

1122 | n/a | rely on the function returning the same type as its input data. |

1123 | n/a | """ |

1124 | n/a | def prepare_types_for_conservation_test(self): |

1125 | n/a | """Return the types which are expected to be conserved.""" |

1126 | n/a | class MyFloat(float): |

1127 | n/a | def __truediv__(self, other): |

1128 | n/a | return type(self)(super().__truediv__(other)) |

1129 | n/a | def __rtruediv__(self, other): |

1130 | n/a | return type(self)(super().__rtruediv__(other)) |

1131 | n/a | def __sub__(self, other): |

1132 | n/a | return type(self)(super().__sub__(other)) |

1133 | n/a | def __rsub__(self, other): |

1134 | n/a | return type(self)(super().__rsub__(other)) |

1135 | n/a | def __pow__(self, other): |

1136 | n/a | return type(self)(super().__pow__(other)) |

1137 | n/a | def __add__(self, other): |

1138 | n/a | return type(self)(super().__add__(other)) |

1139 | n/a | __radd__ = __add__ |

1140 | n/a | return (float, Decimal, Fraction, MyFloat) |

1141 | n/a | |

1142 | n/a | def test_types_conserved(self): |

1143 | n/a | # Test that functions keeps the same type as their data points. |

1144 | n/a | # (Excludes mixed data types.) This only tests the type of the return |

1145 | n/a | # result, not the value. |

1146 | n/a | data = self.prepare_data() |

1147 | n/a | for kind in self.prepare_types_for_conservation_test(): |

1148 | n/a | d = [kind(x) for x in data] |

1149 | n/a | result = self.func(d) |

1150 | n/a | self.assertIs(type(result), kind) |

1151 | n/a | |

1152 | n/a | |

1153 | n/a | class TestSumCommon(UnivariateCommonMixin, UnivariateTypeMixin): |

1154 | n/a | # Common test cases for statistics._sum() function. |

1155 | n/a | |

1156 | n/a | # This test suite looks only at the numeric value returned by _sum, |

1157 | n/a | # after conversion to the appropriate type. |

1158 | n/a | def setUp(self): |

1159 | n/a | def simplified_sum(*args): |

1160 | n/a | T, value, n = statistics._sum(*args) |

1161 | n/a | return statistics._coerce(value, T) |

1162 | n/a | self.func = simplified_sum |

1163 | n/a | |

1164 | n/a | |

1165 | n/a | class TestSum(NumericTestCase): |

1166 | n/a | # Test cases for statistics._sum() function. |

1167 | n/a | |

1168 | n/a | # These tests look at the entire three value tuple returned by _sum. |

1169 | n/a | |

1170 | n/a | def setUp(self): |

1171 | n/a | self.func = statistics._sum |

1172 | n/a | |

1173 | n/a | def test_empty_data(self): |

1174 | n/a | # Override test for empty data. |

1175 | n/a | for data in ([], (), iter([])): |

1176 | n/a | self.assertEqual(self.func(data), (int, Fraction(0), 0)) |

1177 | n/a | self.assertEqual(self.func(data, 23), (int, Fraction(23), 0)) |

1178 | n/a | self.assertEqual(self.func(data, 2.3), (float, Fraction(2.3), 0)) |

1179 | n/a | |

1180 | n/a | def test_ints(self): |

1181 | n/a | self.assertEqual(self.func([1, 5, 3, -4, -8, 20, 42, 1]), |

1182 | n/a | (int, Fraction(60), 8)) |

1183 | n/a | self.assertEqual(self.func([4, 2, 3, -8, 7], 1000), |

1184 | n/a | (int, Fraction(1008), 5)) |

1185 | n/a | |

1186 | n/a | def test_floats(self): |

1187 | n/a | self.assertEqual(self.func([0.25]*20), |

1188 | n/a | (float, Fraction(5.0), 20)) |

1189 | n/a | self.assertEqual(self.func([0.125, 0.25, 0.5, 0.75], 1.5), |

1190 | n/a | (float, Fraction(3.125), 4)) |

1191 | n/a | |

1192 | n/a | def test_fractions(self): |

1193 | n/a | self.assertEqual(self.func([Fraction(1, 1000)]*500), |

1194 | n/a | (Fraction, Fraction(1, 2), 500)) |

1195 | n/a | |

1196 | n/a | def test_decimals(self): |

1197 | n/a | D = Decimal |

1198 | n/a | data = [D("0.001"), D("5.246"), D("1.702"), D("-0.025"), |

1199 | n/a | D("3.974"), D("2.328"), D("4.617"), D("2.843"), |

1200 | n/a | ] |

1201 | n/a | self.assertEqual(self.func(data), |

1202 | n/a | (Decimal, Decimal("20.686"), 8)) |

1203 | n/a | |

1204 | n/a | def test_compare_with_math_fsum(self): |

1205 | n/a | # Compare with the math.fsum function. |

1206 | n/a | # Ideally we ought to get the exact same result, but sometimes |

1207 | n/a | # we differ by a very slight amount :-( |

1208 | n/a | data = [random.uniform(-100, 1000) for _ in range(1000)] |

1209 | n/a | self.assertApproxEqual(float(self.func(data)[1]), math.fsum(data), rel=2e-16) |

1210 | n/a | |

1211 | n/a | def test_start_argument(self): |

1212 | n/a | # Test that the optional start argument works correctly. |

1213 | n/a | data = [random.uniform(1, 1000) for _ in range(100)] |

1214 | n/a | t = self.func(data)[1] |

1215 | n/a | self.assertEqual(t+42, self.func(data, 42)[1]) |

1216 | n/a | self.assertEqual(t-23, self.func(data, -23)[1]) |

1217 | n/a | self.assertEqual(t+Fraction(1e20), self.func(data, 1e20)[1]) |

1218 | n/a | |

1219 | n/a | def test_strings_fail(self): |

1220 | n/a | # Sum of strings should fail. |

1221 | n/a | self.assertRaises(TypeError, self.func, [1, 2, 3], '999') |

1222 | n/a | self.assertRaises(TypeError, self.func, [1, 2, 3, '999']) |

1223 | n/a | |

1224 | n/a | def test_bytes_fail(self): |

1225 | n/a | # Sum of bytes should fail. |

1226 | n/a | self.assertRaises(TypeError, self.func, [1, 2, 3], b'999') |

1227 | n/a | self.assertRaises(TypeError, self.func, [1, 2, 3, b'999']) |

1228 | n/a | |

1229 | n/a | def test_mixed_sum(self): |

1230 | n/a | # Mixed input types are not (currently) allowed. |

1231 | n/a | # Check that mixed data types fail. |

1232 | n/a | self.assertRaises(TypeError, self.func, [1, 2.0, Decimal(1)]) |

1233 | n/a | # And so does mixed start argument. |

1234 | n/a | self.assertRaises(TypeError, self.func, [1, 2.0], Decimal(1)) |

1235 | n/a | |

1236 | n/a | |

1237 | n/a | class SumTortureTest(NumericTestCase): |

1238 | n/a | def test_torture(self): |

1239 | n/a | # Tim Peters' torture test for sum, and variants of same. |

1240 | n/a | self.assertEqual(statistics._sum([1, 1e100, 1, -1e100]*10000), |

1241 | n/a | (float, Fraction(20000.0), 40000)) |

1242 | n/a | self.assertEqual(statistics._sum([1e100, 1, 1, -1e100]*10000), |

1243 | n/a | (float, Fraction(20000.0), 40000)) |

1244 | n/a | T, num, count = statistics._sum([1e-100, 1, 1e-100, -1]*10000) |

1245 | n/a | self.assertIs(T, float) |

1246 | n/a | self.assertEqual(count, 40000) |

1247 | n/a | self.assertApproxEqual(float(num), 2.0e-96, rel=5e-16) |

1248 | n/a | |

1249 | n/a | |

1250 | n/a | class SumSpecialValues(NumericTestCase): |

1251 | n/a | # Test that sum works correctly with IEEE-754 special values. |

1252 | n/a | |

1253 | n/a | def test_nan(self): |

1254 | n/a | for type_ in (float, Decimal): |

1255 | n/a | nan = type_('nan') |

1256 | n/a | result = statistics._sum([1, nan, 2])[1] |

1257 | n/a | self.assertIs(type(result), type_) |

1258 | n/a | self.assertTrue(math.isnan(result)) |

1259 | n/a | |

1260 | n/a | def check_infinity(self, x, inf): |

1261 | n/a | """Check x is an infinity of the same type and sign as inf.""" |

1262 | n/a | self.assertTrue(math.isinf(x)) |

1263 | n/a | self.assertIs(type(x), type(inf)) |

1264 | n/a | self.assertEqual(x > 0, inf > 0) |

1265 | n/a | assert x == inf |

1266 | n/a | |

1267 | n/a | def do_test_inf(self, inf): |

1268 | n/a | # Adding a single infinity gives infinity. |

1269 | n/a | result = statistics._sum([1, 2, inf, 3])[1] |

1270 | n/a | self.check_infinity(result, inf) |

1271 | n/a | # Adding two infinities of the same sign also gives infinity. |

1272 | n/a | result = statistics._sum([1, 2, inf, 3, inf, 4])[1] |

1273 | n/a | self.check_infinity(result, inf) |

1274 | n/a | |

1275 | n/a | def test_float_inf(self): |

1276 | n/a | inf = float('inf') |

1277 | n/a | for sign in (+1, -1): |

1278 | n/a | self.do_test_inf(sign*inf) |

1279 | n/a | |

1280 | n/a | def test_decimal_inf(self): |

1281 | n/a | inf = Decimal('inf') |

1282 | n/a | for sign in (+1, -1): |

1283 | n/a | self.do_test_inf(sign*inf) |

1284 | n/a | |

1285 | n/a | def test_float_mismatched_infs(self): |

1286 | n/a | # Test that adding two infinities of opposite sign gives a NAN. |

1287 | n/a | inf = float('inf') |

1288 | n/a | result = statistics._sum([1, 2, inf, 3, -inf, 4])[1] |

1289 | n/a | self.assertTrue(math.isnan(result)) |

1290 | n/a | |

1291 | n/a | def test_decimal_extendedcontext_mismatched_infs_to_nan(self): |

1292 | n/a | # Test adding Decimal INFs with opposite sign returns NAN. |

1293 | n/a | inf = Decimal('inf') |

1294 | n/a | data = [1, 2, inf, 3, -inf, 4] |

1295 | n/a | with decimal.localcontext(decimal.ExtendedContext): |

1296 | n/a | self.assertTrue(math.isnan(statistics._sum(data)[1])) |

1297 | n/a | |

1298 | n/a | def test_decimal_basiccontext_mismatched_infs_to_nan(self): |

1299 | n/a | # Test adding Decimal INFs with opposite sign raises InvalidOperation. |

1300 | n/a | inf = Decimal('inf') |

1301 | n/a | data = [1, 2, inf, 3, -inf, 4] |

1302 | n/a | with decimal.localcontext(decimal.BasicContext): |

1303 | n/a | self.assertRaises(decimal.InvalidOperation, statistics._sum, data) |

1304 | n/a | |

1305 | n/a | def test_decimal_snan_raises(self): |

1306 | n/a | # Adding sNAN should raise InvalidOperation. |

1307 | n/a | sNAN = Decimal('sNAN') |

1308 | n/a | data = [1, sNAN, 2] |

1309 | n/a | self.assertRaises(decimal.InvalidOperation, statistics._sum, data) |

1310 | n/a | |

1311 | n/a | |

1312 | n/a | # === Tests for averages === |

1313 | n/a | |

1314 | n/a | class AverageMixin(UnivariateCommonMixin): |

1315 | n/a | # Mixin class holding common tests for averages. |

1316 | n/a | |

1317 | n/a | def test_single_value(self): |

1318 | n/a | # Average of a single value is the value itself. |

1319 | n/a | for x in (23, 42.5, 1.3e15, Fraction(15, 19), Decimal('0.28')): |

1320 | n/a | self.assertEqual(self.func([x]), x) |

1321 | n/a | |

1322 | n/a | def prepare_values_for_repeated_single_test(self): |

1323 | n/a | return (3.5, 17, 2.5e15, Fraction(61, 67), Decimal('4.9712')) |

1324 | n/a | |

1325 | n/a | def test_repeated_single_value(self): |

1326 | n/a | # The average of a single repeated value is the value itself. |

1327 | n/a | for x in self.prepare_values_for_repeated_single_test(): |

1328 | n/a | for count in (2, 5, 10, 20): |

1329 | n/a | with self.subTest(x=x, count=count): |

1330 | n/a | data = [x]*count |

1331 | n/a | self.assertEqual(self.func(data), x) |

1332 | n/a | |

1333 | n/a | |

1334 | n/a | class TestMean(NumericTestCase, AverageMixin, UnivariateTypeMixin): |

1335 | n/a | def setUp(self): |

1336 | n/a | self.func = statistics.mean |

1337 | n/a | |

1338 | n/a | def test_torture_pep(self): |

1339 | n/a | # "Torture Test" from PEP-450. |

1340 | n/a | self.assertEqual(self.func([1e100, 1, 3, -1e100]), 1) |

1341 | n/a | |

1342 | n/a | def test_ints(self): |

1343 | n/a | # Test mean with ints. |

1344 | n/a | data = [0, 1, 2, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7, 7, 8, 9] |

1345 | n/a | random.shuffle(data) |

1346 | n/a | self.assertEqual(self.func(data), 4.8125) |

1347 | n/a | |

1348 | n/a | def test_floats(self): |

1349 | n/a | # Test mean with floats. |

1350 | n/a | data = [17.25, 19.75, 20.0, 21.5, 21.75, 23.25, 25.125, 27.5] |

1351 | n/a | random.shuffle(data) |

1352 | n/a | self.assertEqual(self.func(data), 22.015625) |

1353 | n/a | |

1354 | n/a | def test_decimals(self): |

1355 | n/a | # Test mean with Decimals. |

1356 | n/a | D = Decimal |

1357 | n/a | data = [D("1.634"), D("2.517"), D("3.912"), D("4.072"), D("5.813")] |

1358 | n/a | random.shuffle(data) |

1359 | n/a | self.assertEqual(self.func(data), D("3.5896")) |

1360 | n/a | |

1361 | n/a | def test_fractions(self): |

1362 | n/a | # Test mean with Fractions. |

1363 | n/a | F = Fraction |

1364 | n/a | data = [F(1, 2), F(2, 3), F(3, 4), F(4, 5), F(5, 6), F(6, 7), F(7, 8)] |

1365 | n/a | random.shuffle(data) |

1366 | n/a | self.assertEqual(self.func(data), F(1479, 1960)) |

1367 | n/a | |

1368 | n/a | def test_inf(self): |

1369 | n/a | # Test mean with infinities. |

1370 | n/a | raw = [1, 3, 5, 7, 9] # Use only ints, to avoid TypeError later. |

1371 | n/a | for kind in (float, Decimal): |

1372 | n/a | for sign in (1, -1): |

1373 | n/a | inf = kind("inf")*sign |

1374 | n/a | data = raw + [inf] |

1375 | n/a | result = self.func(data) |

1376 | n/a | self.assertTrue(math.isinf(result)) |

1377 | n/a | self.assertEqual(result, inf) |

1378 | n/a | |

1379 | n/a | def test_mismatched_infs(self): |

1380 | n/a | # Test mean with infinities of opposite sign. |

1381 | n/a | data = [2, 4, 6, float('inf'), 1, 3, 5, float('-inf')] |

1382 | n/a | result = self.func(data) |

1383 | n/a | self.assertTrue(math.isnan(result)) |

1384 | n/a | |

1385 | n/a | def test_nan(self): |

1386 | n/a | # Test mean with NANs. |

1387 | n/a | raw = [1, 3, 5, 7, 9] # Use only ints, to avoid TypeError later. |

1388 | n/a | for kind in (float, Decimal): |

1389 | n/a | inf = kind("nan") |

1390 | n/a | data = raw + [inf] |

1391 | n/a | result = self.func(data) |

1392 | n/a | self.assertTrue(math.isnan(result)) |

1393 | n/a | |

1394 | n/a | def test_big_data(self): |

1395 | n/a | # Test adding a large constant to every data point. |

1396 | n/a | c = 1e9 |

1397 | n/a | data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4] |

1398 | n/a | expected = self.func(data) + c |

1399 | n/a | assert expected != c |

1400 | n/a | result = self.func([x+c for x in data]) |

1401 | n/a | self.assertEqual(result, expected) |

1402 | n/a | |

1403 | n/a | def test_doubled_data(self): |

1404 | n/a | # Mean of [a,b,c...z] should be same as for [a,a,b,b,c,c...z,z]. |

1405 | n/a | data = [random.uniform(-3, 5) for _ in range(1000)] |

1406 | n/a | expected = self.func(data) |

1407 | n/a | actual = self.func(data*2) |

1408 | n/a | self.assertApproxEqual(actual, expected) |

1409 | n/a | |

1410 | n/a | def test_regression_20561(self): |

1411 | n/a | # Regression test for issue 20561. |

1412 | n/a | # See http://bugs.python.org/issue20561 |

1413 | n/a | d = Decimal('1e4') |

1414 | n/a | self.assertEqual(statistics.mean([d]), d) |

1415 | n/a | |

1416 | n/a | def test_regression_25177(self): |

1417 | n/a | # Regression test for issue 25177. |

1418 | n/a | # Ensure very big and very small floats don't overflow. |

1419 | n/a | # See http://bugs.python.org/issue25177. |

1420 | n/a | self.assertEqual(statistics.mean( |

1421 | n/a | [8.988465674311579e+307, 8.98846567431158e+307]), |

1422 | n/a | 8.98846567431158e+307) |

1423 | n/a | big = 8.98846567431158e+307 |

1424 | n/a | tiny = 5e-324 |

1425 | n/a | for n in (2, 3, 5, 200): |

1426 | n/a | self.assertEqual(statistics.mean([big]*n), big) |

1427 | n/a | self.assertEqual(statistics.mean([tiny]*n), tiny) |

1428 | n/a | |

1429 | n/a | |

1430 | n/a | class TestHarmonicMean(NumericTestCase, AverageMixin, UnivariateTypeMixin): |

1431 | n/a | def setUp(self): |

1432 | n/a | self.func = statistics.harmonic_mean |

1433 | n/a | |

1434 | n/a | def prepare_data(self): |

1435 | n/a | # Override mixin method. |

1436 | n/a | values = super().prepare_data() |

1437 | n/a | values.remove(0) |

1438 | n/a | return values |

1439 | n/a | |

1440 | n/a | def prepare_values_for_repeated_single_test(self): |

1441 | n/a | # Override mixin method. |

1442 | n/a | return (3.5, 17, 2.5e15, Fraction(61, 67), Decimal('4.125')) |

1443 | n/a | |

1444 | n/a | def test_zero(self): |

1445 | n/a | # Test that harmonic mean returns zero when given zero. |

1446 | n/a | values = [1, 0, 2] |

1447 | n/a | self.assertEqual(self.func(values), 0) |

1448 | n/a | |

1449 | n/a | def test_negative_error(self): |

1450 | n/a | # Test that harmonic mean raises when given a negative value. |

1451 | n/a | exc = statistics.StatisticsError |

1452 | n/a | for values in ([-1], [1, -2, 3]): |

1453 | n/a | with self.subTest(values=values): |

1454 | n/a | self.assertRaises(exc, self.func, values) |

1455 | n/a | |

1456 | n/a | def test_ints(self): |

1457 | n/a | # Test harmonic mean with ints. |

1458 | n/a | data = [2, 4, 4, 8, 16, 16] |

1459 | n/a | random.shuffle(data) |

1460 | n/a | self.assertEqual(self.func(data), 6*4/5) |

1461 | n/a | |

1462 | n/a | def test_floats_exact(self): |

1463 | n/a | # Test harmonic mean with some carefully chosen floats. |

1464 | n/a | data = [1/8, 1/4, 1/4, 1/2, 1/2] |

1465 | n/a | random.shuffle(data) |

1466 | n/a | self.assertEqual(self.func(data), 1/4) |

1467 | n/a | self.assertEqual(self.func([0.25, 0.5, 1.0, 1.0]), 0.5) |

1468 | n/a | |

1469 | n/a | def test_singleton_lists(self): |

1470 | n/a | # Test that harmonic mean([x]) returns (approximately) x. |

1471 | n/a | for x in range(1, 101): |

1472 | n/a | self.assertEqual(self.func([x]), x) |

1473 | n/a | |

1474 | n/a | def test_decimals_exact(self): |

1475 | n/a | # Test harmonic mean with some carefully chosen Decimals. |

1476 | n/a | D = Decimal |

1477 | n/a | self.assertEqual(self.func([D(15), D(30), D(60), D(60)]), D(30)) |

1478 | n/a | data = [D("0.05"), D("0.10"), D("0.20"), D("0.20")] |

1479 | n/a | random.shuffle(data) |

1480 | n/a | self.assertEqual(self.func(data), D("0.10")) |

1481 | n/a | data = [D("1.68"), D("0.32"), D("5.94"), D("2.75")] |

1482 | n/a | random.shuffle(data) |

1483 | n/a | self.assertEqual(self.func(data), D(66528)/70723) |

1484 | n/a | |

1485 | n/a | def test_fractions(self): |

1486 | n/a | # Test harmonic mean with Fractions. |

1487 | n/a | F = Fraction |

1488 | n/a | data = [F(1, 2), F(2, 3), F(3, 4), F(4, 5), F(5, 6), F(6, 7), F(7, 8)] |

1489 | n/a | random.shuffle(data) |

1490 | n/a | self.assertEqual(self.func(data), F(7*420, 4029)) |

1491 | n/a | |

1492 | n/a | def test_inf(self): |

1493 | n/a | # Test harmonic mean with infinity. |

1494 | n/a | values = [2.0, float('inf'), 1.0] |

1495 | n/a | self.assertEqual(self.func(values), 2.0) |

1496 | n/a | |

1497 | n/a | def test_nan(self): |

1498 | n/a | # Test harmonic mean with NANs. |

1499 | n/a | values = [2.0, float('nan'), 1.0] |

1500 | n/a | self.assertTrue(math.isnan(self.func(values))) |

1501 | n/a | |

1502 | n/a | def test_multiply_data_points(self): |

1503 | n/a | # Test multiplying every data point by a constant. |

1504 | n/a | c = 111 |

1505 | n/a | data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4] |

1506 | n/a | expected = self.func(data)*c |

1507 | n/a | result = self.func([x*c for x in data]) |

1508 | n/a | self.assertEqual(result, expected) |

1509 | n/a | |

1510 | n/a | def test_doubled_data(self): |

1511 | n/a | # Harmonic mean of [a,b...z] should be same as for [a,a,b,b...z,z]. |

1512 | n/a | data = [random.uniform(1, 5) for _ in range(1000)] |

1513 | n/a | expected = self.func(data) |

1514 | n/a | actual = self.func(data*2) |

1515 | n/a | self.assertApproxEqual(actual, expected) |

1516 | n/a | |

1517 | n/a | |

1518 | n/a | class TestMedian(NumericTestCase, AverageMixin): |

1519 | n/a | # Common tests for median and all median.* functions. |

1520 | n/a | def setUp(self): |

1521 | n/a | self.func = statistics.median |

1522 | n/a | |

1523 | n/a | def prepare_data(self): |

1524 | n/a | """Overload method from UnivariateCommonMixin.""" |

1525 | n/a | data = super().prepare_data() |

1526 | n/a | if len(data)%2 != 1: |

1527 | n/a | data.append(2) |

1528 | n/a | return data |

1529 | n/a | |

1530 | n/a | def test_even_ints(self): |

1531 | n/a | # Test median with an even number of int data points. |

1532 | n/a | data = [1, 2, 3, 4, 5, 6] |

1533 | n/a | assert len(data)%2 == 0 |

1534 | n/a | self.assertEqual(self.func(data), 3.5) |

1535 | n/a | |

1536 | n/a | def test_odd_ints(self): |

1537 | n/a | # Test median with an odd number of int data points. |

1538 | n/a | data = [1, 2, 3, 4, 5, 6, 9] |

1539 | n/a | assert len(data)%2 == 1 |

1540 | n/a | self.assertEqual(self.func(data), 4) |

1541 | n/a | |

1542 | n/a | def test_odd_fractions(self): |

1543 | n/a | # Test median works with an odd number of Fractions. |

1544 | n/a | F = Fraction |

1545 | n/a | data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7)] |

1546 | n/a | assert len(data)%2 == 1 |

1547 | n/a | random.shuffle(data) |

1548 | n/a | self.assertEqual(self.func(data), F(3, 7)) |

1549 | n/a | |

1550 | n/a | def test_even_fractions(self): |

1551 | n/a | # Test median works with an even number of Fractions. |

1552 | n/a | F = Fraction |

1553 | n/a | data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)] |

1554 | n/a | assert len(data)%2 == 0 |

1555 | n/a | random.shuffle(data) |

1556 | n/a | self.assertEqual(self.func(data), F(1, 2)) |

1557 | n/a | |

1558 | n/a | def test_odd_decimals(self): |

1559 | n/a | # Test median works with an odd number of Decimals. |

1560 | n/a | D = Decimal |

1561 | n/a | data = [D('2.5'), D('3.1'), D('4.2'), D('5.7'), D('5.8')] |

1562 | n/a | assert len(data)%2 == 1 |

1563 | n/a | random.shuffle(data) |

1564 | n/a | self.assertEqual(self.func(data), D('4.2')) |

1565 | n/a | |

1566 | n/a | def test_even_decimals(self): |

1567 | n/a | # Test median works with an even number of Decimals. |

1568 | n/a | D = Decimal |

1569 | n/a | data = [D('1.2'), D('2.5'), D('3.1'), D('4.2'), D('5.7'), D('5.8')] |

1570 | n/a | assert len(data)%2 == 0 |

1571 | n/a | random.shuffle(data) |

1572 | n/a | self.assertEqual(self.func(data), D('3.65')) |

1573 | n/a | |

1574 | n/a | |

1575 | n/a | class TestMedianDataType(NumericTestCase, UnivariateTypeMixin): |

1576 | n/a | # Test conservation of data element type for median. |

1577 | n/a | def setUp(self): |

1578 | n/a | self.func = statistics.median |

1579 | n/a | |

1580 | n/a | def prepare_data(self): |

1581 | n/a | data = list(range(15)) |

1582 | n/a | assert len(data)%2 == 1 |

1583 | n/a | while data == sorted(data): |

1584 | n/a | random.shuffle(data) |

1585 | n/a | return data |

1586 | n/a | |

1587 | n/a | |

1588 | n/a | class TestMedianLow(TestMedian, UnivariateTypeMixin): |

1589 | n/a | def setUp(self): |

1590 | n/a | self.func = statistics.median_low |

1591 | n/a | |

1592 | n/a | def test_even_ints(self): |

1593 | n/a | # Test median_low with an even number of ints. |

1594 | n/a | data = [1, 2, 3, 4, 5, 6] |

1595 | n/a | assert len(data)%2 == 0 |

1596 | n/a | self.assertEqual(self.func(data), 3) |

1597 | n/a | |

1598 | n/a | def test_even_fractions(self): |

1599 | n/a | # Test median_low works with an even number of Fractions. |

1600 | n/a | F = Fraction |

1601 | n/a | data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)] |

1602 | n/a | assert len(data)%2 == 0 |

1603 | n/a | random.shuffle(data) |

1604 | n/a | self.assertEqual(self.func(data), F(3, 7)) |

1605 | n/a | |

1606 | n/a | def test_even_decimals(self): |

1607 | n/a | # Test median_low works with an even number of Decimals. |

1608 | n/a | D = Decimal |

1609 | n/a | data = [D('1.1'), D('2.2'), D('3.3'), D('4.4'), D('5.5'), D('6.6')] |

1610 | n/a | assert len(data)%2 == 0 |

1611 | n/a | random.shuffle(data) |

1612 | n/a | self.assertEqual(self.func(data), D('3.3')) |

1613 | n/a | |

1614 | n/a | |

1615 | n/a | class TestMedianHigh(TestMedian, UnivariateTypeMixin): |

1616 | n/a | def setUp(self): |

1617 | n/a | self.func = statistics.median_high |

1618 | n/a | |

1619 | n/a | def test_even_ints(self): |

1620 | n/a | # Test median_high with an even number of ints. |

1621 | n/a | data = [1, 2, 3, 4, 5, 6] |

1622 | n/a | assert len(data)%2 == 0 |

1623 | n/a | self.assertEqual(self.func(data), 4) |

1624 | n/a | |

1625 | n/a | def test_even_fractions(self): |

1626 | n/a | # Test median_high works with an even number of Fractions. |

1627 | n/a | F = Fraction |

1628 | n/a | data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)] |

1629 | n/a | assert len(data)%2 == 0 |

1630 | n/a | random.shuffle(data) |

1631 | n/a | self.assertEqual(self.func(data), F(4, 7)) |

1632 | n/a | |

1633 | n/a | def test_even_decimals(self): |

1634 | n/a | # Test median_high works with an even number of Decimals. |

1635 | n/a | D = Decimal |

1636 | n/a | data = [D('1.1'), D('2.2'), D('3.3'), D('4.4'), D('5.5'), D('6.6')] |

1637 | n/a | assert len(data)%2 == 0 |

1638 | n/a | random.shuffle(data) |

1639 | n/a | self.assertEqual(self.func(data), D('4.4')) |

1640 | n/a | |

1641 | n/a | |

1642 | n/a | class TestMedianGrouped(TestMedian): |

1643 | n/a | # Test median_grouped. |

1644 | n/a | # Doesn't conserve data element types, so don't use TestMedianType. |

1645 | n/a | def setUp(self): |

1646 | n/a | self.func = statistics.median_grouped |

1647 | n/a | |

1648 | n/a | def test_odd_number_repeated(self): |

1649 | n/a | # Test median.grouped with repeated median values. |

1650 | n/a | data = [12, 13, 14, 14, 14, 15, 15] |

1651 | n/a | assert len(data)%2 == 1 |

1652 | n/a | self.assertEqual(self.func(data), 14) |

1653 | n/a | #--- |

1654 | n/a | data = [12, 13, 14, 14, 14, 14, 15] |

1655 | n/a | assert len(data)%2 == 1 |

1656 | n/a | self.assertEqual(self.func(data), 13.875) |

1657 | n/a | #--- |

1658 | n/a | data = [5, 10, 10, 15, 20, 20, 20, 20, 25, 25, 30] |

1659 | n/a | assert len(data)%2 == 1 |

1660 | n/a | self.assertEqual(self.func(data, 5), 19.375) |

1661 | n/a | #--- |

1662 | n/a | data = [16, 18, 18, 18, 18, 20, 20, 20, 22, 22, 22, 24, 24, 26, 28] |

1663 | n/a | assert len(data)%2 == 1 |

1664 | n/a | self.assertApproxEqual(self.func(data, 2), 20.66666667, tol=1e-8) |

1665 | n/a | |

1666 | n/a | def test_even_number_repeated(self): |

1667 | n/a | # Test median.grouped with repeated median values. |

1668 | n/a | data = [5, 10, 10, 15, 20, 20, 20, 25, 25, 30] |

1669 | n/a | assert len(data)%2 == 0 |

1670 | n/a | self.assertApproxEqual(self.func(data, 5), 19.16666667, tol=1e-8) |

1671 | n/a | #--- |

1672 | n/a | data = [2, 3, 4, 4, 4, 5] |

1673 | n/a | assert len(data)%2 == 0 |

1674 | n/a | self.assertApproxEqual(self.func(data), 3.83333333, tol=1e-8) |

1675 | n/a | #--- |

1676 | n/a | data = [2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6] |

1677 | n/a | assert len(data)%2 == 0 |

1678 | n/a | self.assertEqual(self.func(data), 4.5) |

1679 | n/a | #--- |

1680 | n/a | data = [3, 4, 4, 4, 5, 5, 5, 5, 6, 6] |

1681 | n/a | assert len(data)%2 == 0 |

1682 | n/a | self.assertEqual(self.func(data), 4.75) |

1683 | n/a | |

1684 | n/a | def test_repeated_single_value(self): |

1685 | n/a | # Override method from AverageMixin. |

1686 | n/a | # Yet again, failure of median_grouped to conserve the data type |

1687 | n/a | # causes me headaches :-( |

1688 | n/a | for x in (5.3, 68, 4.3e17, Fraction(29, 101), Decimal('32.9714')): |

1689 | n/a | for count in (2, 5, 10, 20): |

1690 | n/a | data = [x]*count |

1691 | n/a | self.assertEqual(self.func(data), float(x)) |

1692 | n/a | |

1693 | n/a | def test_odd_fractions(self): |

1694 | n/a | # Test median_grouped works with an odd number of Fractions. |

1695 | n/a | F = Fraction |

1696 | n/a | data = [F(5, 4), F(9, 4), F(13, 4), F(13, 4), F(17, 4)] |

1697 | n/a | assert len(data)%2 == 1 |

1698 | n/a | random.shuffle(data) |

1699 | n/a | self.assertEqual(self.func(data), 3.0) |

1700 | n/a | |

1701 | n/a | def test_even_fractions(self): |

1702 | n/a | # Test median_grouped works with an even number of Fractions. |

1703 | n/a | F = Fraction |

1704 | n/a | data = [F(5, 4), F(9, 4), F(13, 4), F(13, 4), F(17, 4), F(17, 4)] |

1705 | n/a | assert len(data)%2 == 0 |

1706 | n/a | random.shuffle(data) |

1707 | n/a | self.assertEqual(self.func(data), 3.25) |

1708 | n/a | |

1709 | n/a | def test_odd_decimals(self): |

1710 | n/a | # Test median_grouped works with an odd number of Decimals. |

1711 | n/a | D = Decimal |

1712 | n/a | data = [D('5.5'), D('6.5'), D('6.5'), D('7.5'), D('8.5')] |

1713 | n/a | assert len(data)%2 == 1 |

1714 | n/a | random.shuffle(data) |

1715 | n/a | self.assertEqual(self.func(data), 6.75) |

1716 | n/a | |

1717 | n/a | def test_even_decimals(self): |

1718 | n/a | # Test median_grouped works with an even number of Decimals. |

1719 | n/a | D = Decimal |

1720 | n/a | data = [D('5.5'), D('5.5'), D('6.5'), D('6.5'), D('7.5'), D('8.5')] |

1721 | n/a | assert len(data)%2 == 0 |

1722 | n/a | random.shuffle(data) |

1723 | n/a | self.assertEqual(self.func(data), 6.5) |

1724 | n/a | #--- |

1725 | n/a | data = [D('5.5'), D('5.5'), D('6.5'), D('7.5'), D('7.5'), D('8.5')] |

1726 | n/a | assert len(data)%2 == 0 |

1727 | n/a | random.shuffle(data) |

1728 | n/a | self.assertEqual(self.func(data), 7.0) |

1729 | n/a | |

1730 | n/a | def test_interval(self): |

1731 | n/a | # Test median_grouped with interval argument. |

1732 | n/a | data = [2.25, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0, 3.25, 3.5, 3.75] |

1733 | n/a | self.assertEqual(self.func(data, 0.25), 2.875) |

1734 | n/a | data = [2.25, 2.5, 2.5, 2.75, 2.75, 2.75, 3.0, 3.0, 3.25, 3.5, 3.75] |

1735 | n/a | self.assertApproxEqual(self.func(data, 0.25), 2.83333333, tol=1e-8) |

1736 | n/a | data = [220, 220, 240, 260, 260, 260, 260, 280, 280, 300, 320, 340] |

1737 | n/a | self.assertEqual(self.func(data, 20), 265.0) |

1738 | n/a | |

1739 | n/a | def test_data_type_error(self): |

1740 | n/a | # Test median_grouped with str, bytes data types for data and interval |

1741 | n/a | data = ["", "", ""] |

1742 | n/a | self.assertRaises(TypeError, self.func, data) |

1743 | n/a | #--- |

1744 | n/a | data = [b"", b"", b""] |

1745 | n/a | self.assertRaises(TypeError, self.func, data) |

1746 | n/a | #--- |

1747 | n/a | data = [1, 2, 3] |

1748 | n/a | interval = "" |

1749 | n/a | self.assertRaises(TypeError, self.func, data, interval) |

1750 | n/a | #--- |

1751 | n/a | data = [1, 2, 3] |

1752 | n/a | interval = b"" |

1753 | n/a | self.assertRaises(TypeError, self.func, data, interval) |

1754 | n/a | |

1755 | n/a | |

1756 | n/a | class TestMode(NumericTestCase, AverageMixin, UnivariateTypeMixin): |

1757 | n/a | # Test cases for the discrete version of mode. |

1758 | n/a | def setUp(self): |

1759 | n/a | self.func = statistics.mode |

1760 | n/a | |

1761 | n/a | def prepare_data(self): |

1762 | n/a | """Overload method from UnivariateCommonMixin.""" |

1763 | n/a | # Make sure test data has exactly one mode. |

1764 | n/a | return [1, 1, 1, 1, 3, 4, 7, 9, 0, 8, 2] |

1765 | n/a | |

1766 | n/a | def test_range_data(self): |

1767 | n/a | # Override test from UnivariateCommonMixin. |

1768 | n/a | data = range(20, 50, 3) |

1769 | n/a | self.assertRaises(statistics.StatisticsError, self.func, data) |

1770 | n/a | |

1771 | n/a | def test_nominal_data(self): |

1772 | n/a | # Test mode with nominal data. |

1773 | n/a | data = 'abcbdb' |

1774 | n/a | self.assertEqual(self.func(data), 'b') |

1775 | n/a | data = 'fe fi fo fum fi fi'.split() |

1776 | n/a | self.assertEqual(self.func(data), 'fi') |

1777 | n/a | |

1778 | n/a | def test_discrete_data(self): |

1779 | n/a | # Test mode with discrete numeric data. |

1780 | n/a | data = list(range(10)) |

1781 | n/a | for i in range(10): |

1782 | n/a | d = data + [i] |

1783 | n/a | random.shuffle(d) |

1784 | n/a | self.assertEqual(self.func(d), i) |

1785 | n/a | |

1786 | n/a | def test_bimodal_data(self): |

1787 | n/a | # Test mode with bimodal data. |

1788 | n/a | data = [1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8, 9, 9] |

1789 | n/a | assert data.count(2) == data.count(6) == 4 |

1790 | n/a | # Check for an exception. |

1791 | n/a | self.assertRaises(statistics.StatisticsError, self.func, data) |

1792 | n/a | |

1793 | n/a | def test_unique_data_failure(self): |

1794 | n/a | # Test mode exception when data points are all unique. |

1795 | n/a | data = list(range(10)) |

1796 | n/a | self.assertRaises(statistics.StatisticsError, self.func, data) |

1797 | n/a | |

1798 | n/a | def test_none_data(self): |

1799 | n/a | # Test that mode raises TypeError if given None as data. |

1800 | n/a | |

1801 | n/a | # This test is necessary because the implementation of mode uses |

1802 | n/a | # collections.Counter, which accepts None and returns an empty dict. |

1803 | n/a | self.assertRaises(TypeError, self.func, None) |

1804 | n/a | |

1805 | n/a | def test_counter_data(self): |

1806 | n/a | # Test that a Counter is treated like any other iterable. |

1807 | n/a | data = collections.Counter([1, 1, 1, 2]) |

1808 | n/a | # Since the keys of the counter are treated as data points, not the |

1809 | n/a | # counts, this should raise. |

1810 | n/a | self.assertRaises(statistics.StatisticsError, self.func, data) |

1811 | n/a | |

1812 | n/a | |

1813 | n/a | |

1814 | n/a | # === Tests for variances and standard deviations === |

1815 | n/a | |

1816 | n/a | class VarianceStdevMixin(UnivariateCommonMixin): |

1817 | n/a | # Mixin class holding common tests for variance and std dev. |

1818 | n/a | |

1819 | n/a | # Subclasses should inherit from this before NumericTestClass, in order |

1820 | n/a | # to see the rel attribute below. See testShiftData for an explanation. |

1821 | n/a | |

1822 | n/a | rel = 1e-12 |

1823 | n/a | |

1824 | n/a | def test_single_value(self): |

1825 | n/a | # Deviation of a single value is zero. |

1826 | n/a | for x in (11, 19.8, 4.6e14, Fraction(21, 34), Decimal('8.392')): |

1827 | n/a | self.assertEqual(self.func([x]), 0) |

1828 | n/a | |

1829 | n/a | def test_repeated_single_value(self): |

1830 | n/a | # The deviation of a single repeated value is zero. |

1831 | n/a | for x in (7.2, 49, 8.1e15, Fraction(3, 7), Decimal('62.4802')): |

1832 | n/a | for count in (2, 3, 5, 15): |

1833 | n/a | data = [x]*count |

1834 | n/a | self.assertEqual(self.func(data), 0) |

1835 | n/a | |

1836 | n/a | def test_domain_error_regression(self): |

1837 | n/a | # Regression test for a domain error exception. |

1838 | n/a | # (Thanks to Geremy Condra.) |

1839 | n/a | data = [0.123456789012345]*10000 |

1840 | n/a | # All the items are identical, so variance should be exactly zero. |

1841 | n/a | # We allow some small round-off error, but not much. |

1842 | n/a | result = self.func(data) |

1843 | n/a | self.assertApproxEqual(result, 0.0, tol=5e-17) |

1844 | n/a | self.assertGreaterEqual(result, 0) # A negative result must fail. |

1845 | n/a | |

1846 | n/a | def test_shift_data(self): |

1847 | n/a | # Test that shifting the data by a constant amount does not affect |

1848 | n/a | # the variance or stdev. Or at least not much. |

1849 | n/a | |

1850 | n/a | # Due to rounding, this test should be considered an ideal. We allow |

1851 | n/a | # some tolerance away from "no change at all" by setting tol and/or rel |

1852 | n/a | # attributes. Subclasses may set tighter or looser error tolerances. |

1853 | n/a | raw = [1.03, 1.27, 1.94, 2.04, 2.58, 3.14, 4.75, 4.98, 5.42, 6.78] |

1854 | n/a | expected = self.func(raw) |

1855 | n/a | # Don't set shift too high, the bigger it is, the more rounding error. |

1856 | n/a | shift = 1e5 |

1857 | n/a | data = [x + shift for x in raw] |

1858 | n/a | self.assertApproxEqual(self.func(data), expected) |

1859 | n/a | |

1860 | n/a | def test_shift_data_exact(self): |

1861 | n/a | # Like test_shift_data, but result is always exact. |

1862 | n/a | raw = [1, 3, 3, 4, 5, 7, 9, 10, 11, 16] |

1863 | n/a | assert all(x==int(x) for x in raw) |

1864 | n/a | expected = self.func(raw) |

1865 | n/a | shift = 10**9 |

1866 | n/a | data = [x + shift for x in raw] |

1867 | n/a | self.assertEqual(self.func(data), expected) |

1868 | n/a | |

1869 | n/a | def test_iter_list_same(self): |

1870 | n/a | # Test that iter data and list data give the same result. |

1871 | n/a | |

1872 | n/a | # This is an explicit test that iterators and lists are treated the |

1873 | n/a | # same; justification for this test over and above the similar test |

1874 | n/a | # in UnivariateCommonMixin is that an earlier design had variance and |

1875 | n/a | # friends swap between one- and two-pass algorithms, which would |

1876 | n/a | # sometimes give different results. |

1877 | n/a | data = [random.uniform(-3, 8) for _ in range(1000)] |

1878 | n/a | expected = self.func(data) |

1879 | n/a | self.assertEqual(self.func(iter(data)), expected) |

1880 | n/a | |

1881 | n/a | |

1882 | n/a | class TestPVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin): |

1883 | n/a | # Tests for population variance. |

1884 | n/a | def setUp(self): |

1885 | n/a | self.func = statistics.pvariance |

1886 | n/a | |

1887 | n/a | def test_exact_uniform(self): |

1888 | n/a | # Test the variance against an exact result for uniform data. |

1889 | n/a | data = list(range(10000)) |

1890 | n/a | random.shuffle(data) |

1891 | n/a | expected = (10000**2 - 1)/12 # Exact value. |

1892 | n/a | self.assertEqual(self.func(data), expected) |

1893 | n/a | |

1894 | n/a | def test_ints(self): |

1895 | n/a | # Test population variance with int data. |

1896 | n/a | data = [4, 7, 13, 16] |

1897 | n/a | exact = 22.5 |

1898 | n/a | self.assertEqual(self.func(data), exact) |

1899 | n/a | |

1900 | n/a | def test_fractions(self): |

1901 | n/a | # Test population variance with Fraction data. |

1902 | n/a | F = Fraction |

1903 | n/a | data = [F(1, 4), F(1, 4), F(3, 4), F(7, 4)] |

1904 | n/a | exact = F(3, 8) |

1905 | n/a | result = self.func(data) |

1906 | n/a | self.assertEqual(result, exact) |

1907 | n/a | self.assertIsInstance(result, Fraction) |

1908 | n/a | |

1909 | n/a | def test_decimals(self): |

1910 | n/a | # Test population variance with Decimal data. |

1911 | n/a | D = Decimal |

1912 | n/a | data = [D("12.1"), D("12.2"), D("12.5"), D("12.9")] |

1913 | n/a | exact = D('0.096875') |

1914 | n/a | result = self.func(data) |

1915 | n/a | self.assertEqual(result, exact) |

1916 | n/a | self.assertIsInstance(result, Decimal) |

1917 | n/a | |

1918 | n/a | |

1919 | n/a | class TestVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin): |

1920 | n/a | # Tests for sample variance. |

1921 | n/a | def setUp(self): |

1922 | n/a | self.func = statistics.variance |

1923 | n/a | |

1924 | n/a | def test_single_value(self): |

1925 | n/a | # Override method from VarianceStdevMixin. |

1926 | n/a | for x in (35, 24.7, 8.2e15, Fraction(19, 30), Decimal('4.2084')): |

1927 | n/a | self.assertRaises(statistics.StatisticsError, self.func, [x]) |

1928 | n/a | |

1929 | n/a | def test_ints(self): |

1930 | n/a | # Test sample variance with int data. |

1931 | n/a | data = [4, 7, 13, 16] |

1932 | n/a | exact = 30 |

1933 | n/a | self.assertEqual(self.func(data), exact) |

1934 | n/a | |

1935 | n/a | def test_fractions(self): |

1936 | n/a | # Test sample variance with Fraction data. |

1937 | n/a | F = Fraction |

1938 | n/a | data = [F(1, 4), F(1, 4), F(3, 4), F(7, 4)] |

1939 | n/a | exact = F(1, 2) |

1940 | n/a | result = self.func(data) |

1941 | n/a | self.assertEqual(result, exact) |

1942 | n/a | self.assertIsInstance(result, Fraction) |

1943 | n/a | |

1944 | n/a | def test_decimals(self): |

1945 | n/a | # Test sample variance with Decimal data. |

1946 | n/a | D = Decimal |

1947 | n/a | data = [D(2), D(2), D(7), D(9)] |

1948 | n/a | exact = 4*D('9.5')/D(3) |

1949 | n/a | result = self.func(data) |

1950 | n/a | self.assertEqual(result, exact) |

1951 | n/a | self.assertIsInstance(result, Decimal) |

1952 | n/a | |

1953 | n/a | |

1954 | n/a | class TestPStdev(VarianceStdevMixin, NumericTestCase): |

1955 | n/a | # Tests for population standard deviation. |

1956 | n/a | def setUp(self): |

1957 | n/a | self.func = statistics.pstdev |

1958 | n/a | |

1959 | n/a | def test_compare_to_variance(self): |

1960 | n/a | # Test that stdev is, in fact, the square root of variance. |

1961 | n/a | data = [random.uniform(-17, 24) for _ in range(1000)] |

1962 | n/a | expected = math.sqrt(statistics.pvariance(data)) |

1963 | n/a | self.assertEqual(self.func(data), expected) |

1964 | n/a | |

1965 | n/a | |

1966 | n/a | class TestStdev(VarianceStdevMixin, NumericTestCase): |

1967 | n/a | # Tests for sample standard deviation. |

1968 | n/a | def setUp(self): |

1969 | n/a | self.func = statistics.stdev |

1970 | n/a | |

1971 | n/a | def test_single_value(self): |

1972 | n/a | # Override method from VarianceStdevMixin. |

1973 | n/a | for x in (81, 203.74, 3.9e14, Fraction(5, 21), Decimal('35.719')): |

1974 | n/a | self.assertRaises(statistics.StatisticsError, self.func, [x]) |

1975 | n/a | |

1976 | n/a | def test_compare_to_variance(self): |

1977 | n/a | # Test that stdev is, in fact, the square root of variance. |

1978 | n/a | data = [random.uniform(-2, 9) for _ in range(1000)] |

1979 | n/a | expected = math.sqrt(statistics.variance(data)) |

1980 | n/a | self.assertEqual(self.func(data), expected) |

1981 | n/a | |

1982 | n/a | |

1983 | n/a | # === Run tests === |

1984 | n/a | |

1985 | n/a | def load_tests(loader, tests, ignore): |

1986 | n/a | """Used for doctest/unittest integration.""" |

1987 | n/a | tests.addTests(doctest.DocTestSuite()) |

1988 | n/a | return tests |

1989 | n/a | |

1990 | n/a | |

1991 | n/a | if __name__ == "__main__": |

1992 | n/a | unittest.main() |