1 # Copyright (c) 2004 Python Software Foundation.
4 # Written by Eric Price <eprice at tjhsst.edu>
5 # and Facundo Batista <facundo at taniquetil.com.ar>
6 # and Raymond Hettinger <python at rcn.com>
7 # and Aahz (aahz at pobox.com)
11 These are the test cases for the Decimal module.
13 There are two groups of tests, Arithmetic and Behaviour. The former test
14 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15 test the pythonic behaviour according to PEP 327.
17 Cowlishaw's tests can be downloaded from:
19 www2.hursley.ibm.com/decimal/dectest.zip
21 This test module can be called from command line with one parameter (Arithmetic
22 or Behaviour) to test each part, or without parameter to test both parts. If
23 you're working through IDLE, you can import this test module and call test_main()
24 with the corresponding argument.
32 from test
.test_support
import TestSkipped
, run_unittest
, run_doctest
, is_resource_enabled
39 # Useful Test Constant
40 Signals
= getcontext().flags
.keys()
42 # Tests are built around these assumed context defaults
44 DefaultContext
.rounding
=ROUND_HALF_EVEN
45 DefaultContext
.traps
=dict.fromkeys(Signals
, 0)
46 setcontext(DefaultContext
)
49 TESTDATADIR
= 'decimaltestdata'
50 if __name__
== '__main__':
54 testdir
= os
.path
.dirname(file) or os
.curdir
55 directory
= testdir
+ os
.sep
+ TESTDATADIR
+ os
.sep
57 skip_expected
= not os
.path
.isdir(directory
)
59 # Make sure it actually raises errors when not expected and caught in flags
60 # Slower, since it runs some things several times.
61 EXTENDEDERRORTEST
= False
64 #Map the test cases' error names to the actual errors
66 ErrorNames
= {'clamped' : Clamped
,
67 'conversion_syntax' : InvalidOperation
,
68 'division_by_zero' : DivisionByZero
,
69 'division_impossible' : InvalidOperation
,
70 'division_undefined' : InvalidOperation
,
72 'invalid_context' : InvalidOperation
,
73 'invalid_operation' : InvalidOperation
,
74 'overflow' : Overflow
,
76 'subnormal' : Subnormal
,
77 'underflow' : Underflow
}
80 def Nonfunction(*args
):
81 """Doesn't do anything."""
84 RoundingDict
= {'ceiling' : ROUND_CEILING
, #Maps test-case names to roundings.
86 'floor' : ROUND_FLOOR
,
87 'half_down' : ROUND_HALF_DOWN
,
88 'half_even' : ROUND_HALF_EVEN
,
89 'half_up' : ROUND_HALF_UP
,
92 # Name adapter to be able to change the Decimal and Context
93 # interface without changing the test files from Cowlishaw
94 nameAdapter
= {'toeng':'to_eng_string',
95 'tosci':'to_sci_string',
96 'samequantum':'same_quantum',
97 'tointegral':'to_integral',
98 'remaindernear':'remainder_near',
99 'divideint':'divide_int',
104 class DecimalTest(unittest
.TestCase
):
105 """Class which tests the Decimal class against the test cases.
107 Changed for unittest.
110 self
.context
= Context()
111 for key
in DefaultContext
.traps
.keys():
112 DefaultContext
.traps
[key
] = 1
113 self
.ignore_list
= ['#']
114 # Basically, a # means return NaN InvalidOperation.
115 # Different from a sNaN in trim
117 self
.ChangeDict
= {'precision' : self
.change_precision
,
118 'rounding' : self
.change_rounding_method
,
119 'maxexponent' : self
.change_max_exponent
,
120 'minexponent' : self
.change_min_exponent
,
121 'clamp' : self
.change_clamp
}
124 """Cleaning up enviroment."""
125 # leaving context in original state
126 for key
in DefaultContext
.traps
.keys():
127 DefaultContext
.traps
[key
] = 0
130 def eval_file(self
, file):
135 for line
in open(file).xreadlines():
136 line
= line
.replace('\r\n', '').replace('\n', '')
139 t
= self
.eval_line(line
)
140 except InvalidOperation
:
141 print 'Error in test cases:'
144 except DecimalException
, exception
:
145 #Exception raised where there shoudn't have been one.
146 self
.fail('Exception "'+exception
.__class
__.__name
__ + '" raised on line '+line
)
150 def eval_line(self
, s
):
151 if s
.find(' -> ') >= 0 and s
[:2] != '--' and not s
.startswith(' --'):
152 s
= (s
.split('->')[0] + '->' +
153 s
.split('->')[1].split('--')[0]).strip()
155 s
= s
.split('--')[0].strip()
157 for ignore
in self
.ignore_list
:
158 if s
.find(ignore
) >= 0:
159 #print s.split()[0], 'NotImplemented--', ignore
164 return self
.eval_directive(s
)
166 return self
.eval_equation(s
)
168 def eval_directive(self
, s
):
169 funct
, value
= map(lambda x
: x
.strip().lower(), s
.split(':'))
170 if funct
== 'rounding':
171 value
= RoundingDict
[value
]
178 funct
= self
.ChangeDict
.get(funct
, Nonfunction
)
181 def eval_equation(self
, s
):
182 #global DEFAULT_PRECISION
183 #print DEFAULT_PRECISION
185 if not TEST_ALL
and random
.random() < 0.90:
189 Sides
= s
.split('->')
190 L
= Sides
[0].strip().split()
195 L
= Sides
[1].strip().split()
198 except (TypeError, AttributeError, IndexError):
199 raise InvalidOperation
201 val
= val
.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
202 val
= val
.replace("'", '').replace('"', '')
203 val
= val
.replace('SingleQuote', "'").replace('DoubleQuote', '"')
205 fname
= nameAdapter
.get(funct
, funct
)
206 if fname
== 'rescale':
208 funct
= getattr(self
.context
, fname
)
212 theirexceptions
= [ErrorNames
[x
.lower()] for x
in exceptions
]
214 for exception
in Signals
:
215 self
.context
.traps
[exception
] = 1 #Catch these bugs...
216 for exception
in theirexceptions
:
217 self
.context
.traps
[exception
] = 0
218 for i
, val
in enumerate(valstemp
):
219 if val
.count("'") % 2 == 1:
222 conglomerate
= conglomerate
+ ' ' + val
225 val
= conglomerate
+ val
228 if fname
in ('to_sci_string', 'to_eng_string'):
229 if EXTENDEDERRORTEST
:
230 for error
in theirexceptions
:
231 self
.context
.traps
[error
] = 1
233 funct(self
.context
.create_decimal(v
))
237 self
.fail("Raised %s in %s when %s disabled" % \
240 self
.fail("Did not raise %s in %s" % (error
, s
))
241 self
.context
.traps
[error
] = 0
242 v
= self
.context
.create_decimal(v
)
249 if EXTENDEDERRORTEST
and fname
not in ('to_sci_string', 'to_eng_string'):
250 for error
in theirexceptions
:
251 self
.context
.traps
[error
] = 1
257 self
.fail("Raised %s in %s when %s disabled" % \
260 self
.fail("Did not raise %s in %s" % (error
, s
))
261 self
.context
.traps
[error
] = 0
263 result
= str(funct(*vals
))
264 if fname
== 'same_quantum':
265 result
= str(int(eval(result
))) # 'True', 'False' -> '1', '0'
266 except Signals
, error
:
267 self
.fail("Raised %s in %s" % (error
, s
))
268 except: #Catch any error long enough to state the test case.
272 myexceptions
= self
.getexceptions()
273 self
.context
.clear_flags()
276 theirexceptions
.sort()
278 self
.assertEqual(result
, ans
,
279 'Incorrect answer for ' + s
+ ' -- got ' + result
)
280 self
.assertEqual(myexceptions
, theirexceptions
,
281 'Incorrect flags set in ' + s
+ ' -- got ' \
285 def getexceptions(self
):
286 return [e
for e
in Signals
if self
.context
.flags
[e
]]
288 def change_precision(self
, prec
):
289 self
.context
.prec
= prec
290 def change_rounding_method(self
, rounding
):
291 self
.context
.rounding
= rounding
292 def change_min_exponent(self
, exp
):
293 self
.context
.Emin
= exp
294 def change_max_exponent(self
, exp
):
295 self
.context
.Emax
= exp
296 def change_clamp(self
, clamp
):
297 self
.context
._clamp
= clamp
299 # Dynamically build custom test definition for each file in the test
300 # directory and add the definitions to the DecimalTest class. This
301 # procedure insures that new files do not get skipped.
302 for filename
in os
.listdir(directory
):
303 if '.decTest' not in filename
:
305 head
, tail
= filename
.split('.')
306 tester
= lambda self
, f
=filename
: self
.eval_file(directory
+ f
)
307 setattr(DecimalTest
, 'test_' + head
, tester
)
308 del filename
, head
, tail
, tester
312 # The following classes test the behaviour of Decimal according to PEP 327
314 class DecimalExplicitConstructionTest(unittest
.TestCase
):
315 '''Unit tests for Explicit Construction cases of Decimal.'''
317 def test_explicit_empty(self
):
318 self
.assertEqual(Decimal(), Decimal("0"))
320 def test_explicit_from_None(self
):
321 self
.assertRaises(TypeError, Decimal
, None)
323 def test_explicit_from_int(self
):
327 self
.assertEqual(str(d
), '45')
330 d
= Decimal(500000123)
331 self
.assertEqual(str(d
), '500000123')
335 self
.assertEqual(str(d
), '-45')
339 self
.assertEqual(str(d
), '0')
341 def test_explicit_from_string(self
):
344 self
.assertEqual(str(Decimal('')), 'NaN')
347 self
.assertEqual(str(Decimal('45')), '45')
350 self
.assertEqual(str(Decimal('45.34')), '45.34')
353 self
.assertEqual(str(Decimal('45e2')), '4.5E+3')
356 self
.assertEqual(str(Decimal('ugly')), 'NaN')
358 def test_explicit_from_tuples(self
):
361 d
= Decimal( (0, (0,), 0) )
362 self
.assertEqual(str(d
), '0')
365 d
= Decimal( (1, (4, 5), 0) )
366 self
.assertEqual(str(d
), '-45')
369 d
= Decimal( (0, (4, 5, 3, 4), -2) )
370 self
.assertEqual(str(d
), '45.34')
373 d
= Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
374 self
.assertEqual(str(d
), '-4.34913534E-17')
376 #wrong number of items
377 self
.assertRaises(ValueError, Decimal
, (1, (4, 3, 4, 9, 1)) )
380 self
.assertRaises(ValueError, Decimal
, (8, (4, 3, 4, 9, 1), 2) )
383 self
.assertRaises(ValueError, Decimal
, (1, (4, 3, 4, 9, 1), 'wrong!') )
386 self
.assertRaises(ValueError, Decimal
, (1, (4, 3, 4, None, 1), 2) )
387 self
.assertRaises(ValueError, Decimal
, (1, (4, -3, 4, 9, 1), 2) )
389 def test_explicit_from_Decimal(self
):
394 self
.assertEqual(str(e
), '45')
395 self
.assertNotEqual(id(d
), id(e
))
398 d
= Decimal(500000123)
400 self
.assertEqual(str(e
), '500000123')
401 self
.assertNotEqual(id(d
), id(e
))
406 self
.assertEqual(str(e
), '-45')
407 self
.assertNotEqual(id(d
), id(e
))
412 self
.assertEqual(str(e
), '0')
413 self
.assertNotEqual(id(d
), id(e
))
415 def test_explicit_context_create_decimal(self
):
417 nc
= copy
.copy(getcontext())
422 self
.assertEqual(str(d
), '0')
423 d
= nc
.create_decimal()
424 self
.assertEqual(str(d
), '0')
427 self
.assertRaises(TypeError, nc
.create_decimal
, None)
430 d
= nc
.create_decimal(456)
431 self
.failUnless(isinstance(d
, Decimal
))
432 self
.assertEqual(nc
.create_decimal(45678),
433 nc
.create_decimal('457E+2'))
436 d
= Decimal('456789')
437 self
.assertEqual(str(d
), '456789')
438 d
= nc
.create_decimal('456789')
439 self
.assertEqual(str(d
), '4.57E+5')
442 d
= Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
443 self
.assertEqual(str(d
), '-4.34913534E-17')
444 d
= nc
.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
445 self
.assertEqual(str(d
), '-4.35E-17')
448 prevdec
= Decimal(500000123)
450 self
.assertEqual(str(d
), '500000123')
451 d
= nc
.create_decimal(prevdec
)
452 self
.assertEqual(str(d
), '5.00E+8')
455 class DecimalImplicitConstructionTest(unittest
.TestCase
):
456 '''Unit tests for Implicit Construction cases of Decimal.'''
458 def test_implicit_from_None(self
):
459 self
.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
461 def test_implicit_from_int(self
):
463 self
.assertEqual(str(Decimal(5) + 45), '50')
465 self
.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
467 def test_implicit_from_string(self
):
468 self
.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
470 def test_implicit_from_float(self
):
471 self
.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
473 def test_implicit_from_Decimal(self
):
474 self
.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
477 # Allow other classes to be trained to interact with Decimals
479 def __divmod__(self
, other
):
480 return 'divmod ' + str(other
)
481 def __rdivmod__(self
, other
):
482 return str(other
) + ' rdivmod'
483 def __lt__(self
, other
):
484 return 'lt ' + str(other
)
485 def __gt__(self
, other
):
486 return 'gt ' + str(other
)
487 def __le__(self
, other
):
488 return 'le ' + str(other
)
489 def __ge__(self
, other
):
490 return 'ge ' + str(other
)
491 def __eq__(self
, other
):
492 return 'eq ' + str(other
)
493 def __ne__(self
, other
):
494 return 'ne ' + str(other
)
496 self
.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
497 self
.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
498 self
.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
499 self
.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
500 self
.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
501 self
.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
502 self
.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
503 self
.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
505 # insert operator methods and then exercise them
506 for sym
, lop
, rop
in (
507 ('+', '__add__', '__radd__'),
508 ('-', '__sub__', '__rsub__'),
509 ('*', '__mul__', '__rmul__'),
510 ('/', '__div__', '__rdiv__'),
511 ('%', '__mod__', '__rmod__'),
512 ('//', '__floordiv__', '__rfloordiv__'),
513 ('**', '__pow__', '__rpow__'),
516 setattr(E
, lop
, lambda self
, other
: 'str' + lop
+ str(other
))
517 setattr(E
, rop
, lambda self
, other
: str(other
) + rop
+ 'str')
518 self
.assertEqual(eval('E()' + sym
+ 'Decimal(10)'),
520 self
.assertEqual(eval('Decimal(10)' + sym
+ 'E()'),
523 class DecimalArithmeticOperatorsTest(unittest
.TestCase
):
524 '''Unit tests for all arithmetic operators, binary and unary.'''
526 def test_addition(self
):
528 d1
= Decimal('-11.1')
532 self
.assertEqual(d1
+d2
, Decimal('11.1'))
533 self
.assertEqual(d2
+d1
, Decimal('11.1'))
535 #with other type, left
537 self
.assertEqual(c
, Decimal('-6.1'))
538 self
.assertEqual(type(c
), type(d1
))
540 #with other type, right
542 self
.assertEqual(c
, Decimal('-6.1'))
543 self
.assertEqual(type(c
), type(d1
))
547 self
.assertEqual(d1
, Decimal('11.1'))
549 #inline with other type
551 self
.assertEqual(d1
, Decimal('16.1'))
553 def test_subtraction(self
):
555 d1
= Decimal('-11.1')
559 self
.assertEqual(d1
-d2
, Decimal('-33.3'))
560 self
.assertEqual(d2
-d1
, Decimal('33.3'))
562 #with other type, left
564 self
.assertEqual(c
, Decimal('-16.1'))
565 self
.assertEqual(type(c
), type(d1
))
567 #with other type, right
569 self
.assertEqual(c
, Decimal('16.1'))
570 self
.assertEqual(type(c
), type(d1
))
574 self
.assertEqual(d1
, Decimal('-33.3'))
576 #inline with other type
578 self
.assertEqual(d1
, Decimal('-38.3'))
580 def test_multiplication(self
):
586 self
.assertEqual(d1
*d2
, Decimal('-15'))
587 self
.assertEqual(d2
*d1
, Decimal('-15'))
589 #with other type, left
591 self
.assertEqual(c
, Decimal('-25'))
592 self
.assertEqual(type(c
), type(d1
))
594 #with other type, right
596 self
.assertEqual(c
, Decimal('-25'))
597 self
.assertEqual(type(c
), type(d1
))
601 self
.assertEqual(d1
, Decimal('-15'))
603 #inline with other type
605 self
.assertEqual(d1
, Decimal('-75'))
607 def test_division(self
):
613 self
.assertEqual(d1
/d2
, Decimal('-2.5'))
614 self
.assertEqual(d2
/d1
, Decimal('-0.4'))
616 #with other type, left
618 self
.assertEqual(c
, Decimal('-1.25'))
619 self
.assertEqual(type(c
), type(d1
))
621 #with other type, right
623 self
.assertEqual(c
, Decimal('-0.8'))
624 self
.assertEqual(type(c
), type(d1
))
628 self
.assertEqual(d1
, Decimal('-2.5'))
630 #inline with other type
632 self
.assertEqual(d1
, Decimal('-0.625'))
634 def test_floor_division(self
):
640 self
.assertEqual(d1
//d2
, Decimal('2'))
641 self
.assertEqual(d2
//d1
, Decimal('0'))
643 #with other type, left
645 self
.assertEqual(c
, Decimal('1'))
646 self
.assertEqual(type(c
), type(d1
))
648 #with other type, right
650 self
.assertEqual(c
, Decimal('1'))
651 self
.assertEqual(type(c
), type(d1
))
655 self
.assertEqual(d1
, Decimal('2'))
657 #inline with other type
659 self
.assertEqual(d1
, Decimal('1'))
661 def test_powering(self
):
667 self
.assertEqual(d1
**d2
, Decimal('25'))
668 self
.assertEqual(d2
**d1
, Decimal('32'))
670 #with other type, left
672 self
.assertEqual(c
, Decimal('625'))
673 self
.assertEqual(type(c
), type(d1
))
675 #with other type, right
677 self
.assertEqual(c
, Decimal('16807'))
678 self
.assertEqual(type(c
), type(d1
))
682 self
.assertEqual(d1
, Decimal('25'))
684 #inline with other type
686 self
.assertEqual(d1
, Decimal('390625'))
688 def test_module(self
):
694 self
.assertEqual(d1
%d2, Decimal('1'))
695 self
.assertEqual(d2
%d1, Decimal('2'))
697 #with other type, left
699 self
.assertEqual(c
, Decimal('1'))
700 self
.assertEqual(type(c
), type(d1
))
702 #with other type, right
704 self
.assertEqual(c
, Decimal('2'))
705 self
.assertEqual(type(c
), type(d1
))
709 self
.assertEqual(d1
, Decimal('1'))
711 #inline with other type
713 self
.assertEqual(d1
, Decimal('1'))
715 def test_floor_div_module(self
):
721 (p
, q
) = divmod(d1
, d2
)
722 self
.assertEqual(p
, Decimal('2'))
723 self
.assertEqual(q
, Decimal('1'))
724 self
.assertEqual(type(p
), type(d1
))
725 self
.assertEqual(type(q
), type(d1
))
727 #with other type, left
728 (p
, q
) = divmod(d1
, 4)
729 self
.assertEqual(p
, Decimal('1'))
730 self
.assertEqual(q
, Decimal('1'))
731 self
.assertEqual(type(p
), type(d1
))
732 self
.assertEqual(type(q
), type(d1
))
734 #with other type, right
735 (p
, q
) = divmod(7, d1
)
736 self
.assertEqual(p
, Decimal('1'))
737 self
.assertEqual(q
, Decimal('2'))
738 self
.assertEqual(type(p
), type(d1
))
739 self
.assertEqual(type(q
), type(d1
))
741 def test_unary_operators(self
):
742 self
.assertEqual(+Decimal(45), Decimal(+45)) # +
743 self
.assertEqual(-Decimal(45), Decimal(-45)) # -
744 self
.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
747 # The following are two functions used to test threading in the next class
752 cls
.assertEqual(d1
/d3
, Decimal('0.333333333'))
754 cls
.assertEqual(d1
/d3
, Decimal('0.333333333'))
761 cls
.assertEqual(d1
/d3
, Decimal('0.333333333'))
762 thiscontext
= getcontext()
763 thiscontext
.prec
= 18
764 cls
.assertEqual(d1
/d3
, Decimal('0.333333333333333333'))
770 class DecimalUseOfContextTest(unittest
.TestCase
):
771 '''Unit tests for Use of Context cases in Decimal.'''
778 # Take care executing this test from IDLE, there's an issue in threading
779 # that hangs IDLE and I couldn't find it
781 def test_threading(self
):
782 #Test the "threading isolation" of a Context.
784 self
.synchro
= threading
.Event()
785 self
.finish1
= threading
.Event()
786 self
.finish2
= threading
.Event()
788 th1
= threading
.Thread(target
=thfunc1
, args
=(self
,))
789 th2
= threading
.Thread(target
=thfunc2
, args
=(self
,))
798 if threading
is None:
802 class DecimalUsabilityTest(unittest
.TestCase
):
803 '''Unit tests for Usability cases of Decimal.'''
805 def test_comparison_operators(self
):
807 da
= Decimal('23.42')
808 db
= Decimal('23.42')
812 self
.failUnless(dc
> da
)
813 self
.failUnless(dc
>= da
)
814 self
.failUnless(da
< dc
)
815 self
.failUnless(da
<= dc
)
816 self
.failUnless(da
== db
)
817 self
.failUnless(da
!= dc
)
818 self
.failUnless(da
<= db
)
819 self
.failUnless(da
>= db
)
820 self
.assertEqual(cmp(dc
,da
), 1)
821 self
.assertEqual(cmp(da
,dc
), -1)
822 self
.assertEqual(cmp(da
,db
), 0)
824 #a Decimal and an int
825 self
.failUnless(dc
> 23)
826 self
.failUnless(23 < dc
)
827 self
.failUnless(dc
== 45)
828 self
.assertEqual(cmp(dc
,23), 1)
829 self
.assertEqual(cmp(23,dc
), -1)
830 self
.assertEqual(cmp(dc
,45), 0)
832 #a Decimal and uncomparable
833 self
.assertNotEqual(da
, 'ugly')
834 self
.assertNotEqual(da
, 32.7)
835 self
.assertNotEqual(da
, object())
836 self
.assertNotEqual(da
, object)
839 a
= map(Decimal
, xrange(100))
843 self
.assertEqual(a
, b
)
845 def test_copy_and_deepcopy_methods(self
):
848 self
.assertEqual(id(c
), id(d
))
849 dc
= copy
.deepcopy(d
)
850 self
.assertEqual(id(dc
), id(d
))
852 def test_hash_method(self
):
853 #just that it's hashable
855 #the same hash that to an int
856 self
.assertEqual(hash(Decimal(23)), hash(23))
857 self
.assertRaises(TypeError, hash, Decimal('NaN'))
858 self
.assert_(hash(Decimal('Inf')))
859 self
.assert_(hash(Decimal('-Inf')))
861 def test_min_and_max_methods(self
):
863 d1
= Decimal('15.32')
869 self
.failUnless(min(d1
,d2
) is d1
)
870 self
.failUnless(min(d2
,d1
) is d1
)
871 self
.failUnless(max(d1
,d2
) is d2
)
872 self
.failUnless(max(d2
,d1
) is d2
)
874 #between Decimal and long
875 self
.failUnless(min(d1
,l2
) is d1
)
876 self
.failUnless(min(l2
,d1
) is d1
)
877 self
.failUnless(max(l1
,d2
) is d2
)
878 self
.failUnless(max(d2
,l1
) is d2
)
880 def test_as_nonzero(self
):
882 self
.failIf(Decimal(0))
884 self
.failUnless(Decimal('0.372'))
886 def test_tostring_methods(self
):
887 #Test str and repr methods.
890 self
.assertEqual(str(d
), '15.32') # str
891 self
.assertEqual(repr(d
), 'Decimal("15.32")') # repr
893 def test_tonum_methods(self
):
894 #Test float, int and long methods.
897 d2
= Decimal('15.32')
900 self
.assertEqual(int(d1
), 66)
901 self
.assertEqual(int(d2
), 15)
904 self
.assertEqual(long(d1
), 66)
905 self
.assertEqual(long(d2
), 15)
908 self
.assertEqual(float(d1
), 66)
909 self
.assertEqual(float(d2
), 15.32)
911 def test_eval_round_trip(self
):
914 d
= Decimal( (0, (0,), 0) )
915 self
.assertEqual(d
, eval(repr(d
)))
918 d
= Decimal( (1, (4, 5), 0) )
919 self
.assertEqual(d
, eval(repr(d
)))
922 d
= Decimal( (0, (4, 5, 3, 4), -2) )
923 self
.assertEqual(d
, eval(repr(d
)))
926 d
= Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
927 self
.assertEqual(d
, eval(repr(d
)))
929 def test_as_tuple(self
):
933 self
.assertEqual(d
.as_tuple(), (0, (0,), 0) )
937 self
.assertEqual(d
.as_tuple(), (1, (4, 5), 0) )
940 d
= Decimal("-4.34913534E-17")
941 self
.assertEqual(d
.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
944 d
= Decimal("Infinity")
945 self
.assertEqual(d
.as_tuple(), (0, (0,), 'F') )
947 def test_immutability_operations(self
):
948 # Do operations and check that it didn't change change internal objects.
950 d1
= Decimal('-25e55')
951 b1
= Decimal('-25e55')
952 d2
= Decimal('33e-33')
953 b2
= Decimal('33e-33')
955 def checkSameDec(operation
, useOther
=False):
957 eval("d1." + operation
+ "(d2)")
958 self
.assertEqual(d1
._sign
, b1
._sign
)
959 self
.assertEqual(d1
._int
, b1
._int
)
960 self
.assertEqual(d1
._exp
, b1
._exp
)
961 self
.assertEqual(d2
._sign
, b2
._sign
)
962 self
.assertEqual(d2
._int
, b2
._int
)
963 self
.assertEqual(d2
._exp
, b2
._exp
)
965 eval("d1." + operation
+ "()")
966 self
.assertEqual(d1
._sign
, b1
._sign
)
967 self
.assertEqual(d1
._int
, b1
._int
)
968 self
.assertEqual(d1
._exp
, b1
._exp
)
972 self
.assertEqual(d1
._sign
, b1
._sign
)
973 self
.assertEqual(d1
._int
, b1
._int
)
974 self
.assertEqual(d1
._exp
, b1
._exp
)
976 checkSameDec("__abs__")
977 checkSameDec("__add__", True)
978 checkSameDec("__div__", True)
979 checkSameDec("__divmod__", True)
980 checkSameDec("__cmp__", True)
981 checkSameDec("__float__")
982 checkSameDec("__floordiv__", True)
983 checkSameDec("__hash__")
984 checkSameDec("__int__")
985 checkSameDec("__long__")
986 checkSameDec("__mod__", True)
987 checkSameDec("__mul__", True)
988 checkSameDec("__neg__")
989 checkSameDec("__nonzero__")
990 checkSameDec("__pos__")
991 checkSameDec("__pow__", True)
992 checkSameDec("__radd__", True)
993 checkSameDec("__rdiv__", True)
994 checkSameDec("__rdivmod__", True)
995 checkSameDec("__repr__")
996 checkSameDec("__rfloordiv__", True)
997 checkSameDec("__rmod__", True)
998 checkSameDec("__rmul__", True)
999 checkSameDec("__rpow__", True)
1000 checkSameDec("__rsub__", True)
1001 checkSameDec("__str__")
1002 checkSameDec("__sub__", True)
1003 checkSameDec("__truediv__", True)
1004 checkSameDec("adjusted")
1005 checkSameDec("as_tuple")
1006 checkSameDec("compare", True)
1007 checkSameDec("max", True)
1008 checkSameDec("min", True)
1009 checkSameDec("normalize")
1010 checkSameDec("quantize", True)
1011 checkSameDec("remainder_near", True)
1012 checkSameDec("same_quantum", True)
1013 checkSameDec("sqrt")
1014 checkSameDec("to_eng_string")
1015 checkSameDec("to_integral")
1017 class DecimalPythonAPItests(unittest
.TestCase
):
1019 def test_pickle(self
):
1020 d
= Decimal('-3.141590000')
1023 self
.assertEqual(d
, e
)
1026 for x
in range(-250, 250):
1027 s
= '%0.2f' % (x
/ 100.0)
1028 # should work the same as for floats
1029 self
.assertEqual(int(Decimal(s
)), int(float(s
)))
1030 # should work the same as to_integral in the ROUND_DOWN mode
1032 r
= d
.to_integral(ROUND_DOWN
)
1033 self
.assertEqual(Decimal(int(d
)), r
)
1035 class ContextAPItests(unittest
.TestCase
):
1037 def test_pickle(self
):
1039 e
= pickle
.loads(pickle
.dumps(c
))
1043 self
.assertEqual(v1
, v2
)
1045 def test_equality_with_other_types(self
):
1046 self
.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1047 self
.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
1049 def test_copy(self
):
1050 # All copies should be deep
1053 self
.assertNotEqual(id(c
), id(d
))
1054 self
.assertNotEqual(id(c
.flags
), id(d
.flags
))
1055 self
.assertNotEqual(id(c
.traps
), id(d
.traps
))
1057 def test_main(arith
=False, verbose
=None):
1058 """ Execute the tests.
1060 Runs all arithmetic tests if arith is True or if the "decimal" resource
1061 is enabled in regrtest.py
1065 TEST_ALL
= arith
or is_resource_enabled('decimal')
1068 DecimalExplicitConstructionTest
,
1069 DecimalImplicitConstructionTest
,
1070 DecimalArithmeticOperatorsTest
,
1071 DecimalUseOfContextTest
,
1072 DecimalUsabilityTest
,
1073 DecimalPythonAPItests
,
1078 run_unittest(*test_classes
)
1079 import decimal
as DecimalModule
1080 run_doctest(DecimalModule
, verbose
)
1083 if __name__
== '__main__':
1084 # Calling with no arguments runs all tests.
1085 # Calling with "Skip" will skip over 90% of the arithmetic tests.
1086 if len(sys
.argv
) == 1:
1087 test_main(arith
=True, verbose
=True)
1088 elif len(sys
.argv
) == 2:
1089 arith
= sys
.argv
[1].lower() != 'skip'
1090 test_main(arith
=arith
, verbose
=True)
1092 raise ValueError("test called with wrong arguments, use test_Decimal [Skip]")