summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/testing
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-02-06 20:20:07 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-02-06 20:20:07 -0500
commit8550a4c38629373baad853b3c37ca3bd92a2fe54 (patch)
treeeba5c68db6bc19649619df8677b9a9bac6db917a /lib/sqlalchemy/testing
parenta0ef9edc1908adb823ec788eee1974900bca4bac (diff)
downloadsqlalchemy-8550a4c38629373baad853b3c37ca3bd92a2fe54.tar.gz
port numeric tests to dialect suite
Diffstat (limited to 'lib/sqlalchemy/testing')
-rw-r--r--lib/sqlalchemy/testing/requirements.py38
-rw-r--r--lib/sqlalchemy/testing/suite/test_types.py144
2 files changed, 181 insertions, 1 deletions
diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py
index e6e21d2cb..6cc1de96d 100644
--- a/lib/sqlalchemy/testing/requirements.py
+++ b/lib/sqlalchemy/testing/requirements.py
@@ -231,6 +231,10 @@ class SuiteRequirements(Requirements):
self.config.db.dialect.sequences_optional
], "no sequence support, or sequences not optional")
+
+
+
+
@property
def reflects_pk_names(self):
return exclusions.closed()
@@ -329,6 +333,40 @@ class SuiteRequirements(Requirements):
return exclusions.open()
@property
+ def precision_numerics_general(self):
+ """target backend has general support for moderately high-precision
+ numerics."""
+ return exclusions.open()
+
+ @property
+ def precision_numerics_enotation_small(self):
+ """target backend supports Decimal() objects using E notation
+ to represent very small values."""
+ return exclusions.closed()
+
+ @property
+ def precision_numerics_enotation_large(self):
+ """target backend supports Decimal() objects using E notation
+ to represent very large values."""
+ return exclusions.closed()
+
+ @property
+ def precision_numerics_many_significant_digits(self):
+ """target backend supports values with many digits on both sides,
+ such as 319438950232418390.273596, 87673.594069654243
+
+ """
+ return exclusions.closed()
+
+ @property
+ def precision_numerics_retains_significant_digits(self):
+ """A precision numeric type will return empty significant digits,
+ i.e. a value such as 10.000 will come back in Decimal form with
+ the .000 maintained."""
+
+ return exclusions.closed()
+
+ @property
def text_type(self):
"""Target database must support an unbounded Text() "
"type such as TEXT or CLOB"""
diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py
index 5ad26c2f2..0716b1b91 100644
--- a/lib/sqlalchemy/testing/suite/test_types.py
+++ b/lib/sqlalchemy/testing/suite/test_types.py
@@ -4,8 +4,11 @@ from .. import fixtures, config
from ..assertions import eq_
from ..config import requirements
from sqlalchemy import Integer, Unicode, UnicodeText, select
-from sqlalchemy import Date, DateTime, Time, MetaData, String, Text
+from sqlalchemy import Date, DateTime, Time, MetaData, String, \
+ Text, Numeric, Float
from ..schema import Table, Column
+from ... import testing
+import decimal
import datetime
@@ -243,9 +246,148 @@ class DateHistoricTest(_DateFixture, fixtures.TablesTest):
datatype = Date
data = datetime.date(1727, 4, 1)
+class NumericTest(fixtures.TestBase):
+
+ @testing.emits_warning(r".*does \*not\* support Decimal objects natively")
+ @testing.provide_metadata
+ def _do_test(self, type_, input_, output, filter_=None, check_scale=False):
+ metadata = self.metadata
+ t = Table('t', metadata, Column('x', type_))
+ t.create()
+ t.insert().execute([{'x':x} for x in input_])
+
+ result = set([row[0] for row in t.select().execute()])
+ output = set(output)
+ if filter_:
+ result = set(filter_(x) for x in result)
+ output = set(filter_(x) for x in output)
+ eq_(result, output)
+ if check_scale:
+ eq_(
+ [str(x) for x in result],
+ [str(x) for x in output],
+ )
+
+ def test_numeric_as_decimal(self):
+ self._do_test(
+ Numeric(precision=8, scale=4),
+ [15.7563, decimal.Decimal("15.7563"), None],
+ [decimal.Decimal("15.7563"), None],
+ )
+
+ def test_numeric_as_float(self):
+ self._do_test(
+ Numeric(precision=8, scale=4, asdecimal=False),
+ [15.7563, decimal.Decimal("15.7563"), None],
+ [15.7563, None],
+ )
+
+ def test_float_as_decimal(self):
+ self._do_test(
+ Float(precision=8, asdecimal=True),
+ [15.7563, decimal.Decimal("15.7563"), None],
+ [decimal.Decimal("15.7563"), None],
+ )
+
+ def test_float_as_float(self):
+ self._do_test(
+ Float(precision=8),
+ [15.7563, decimal.Decimal("15.7563")],
+ [15.7563],
+ filter_=lambda n: n is not None and round(n, 5) or None
+ )
+
+ @testing.requires.precision_numerics_general
+ def test_precision_decimal(self):
+ numbers = set([
+ decimal.Decimal("54.234246451650"),
+ decimal.Decimal("0.004354"),
+ decimal.Decimal("900.0"),
+ ])
+
+ self._do_test(
+ Numeric(precision=18, scale=12),
+ numbers,
+ numbers,
+ )
+
+ @testing.requires.precision_numerics_enotation_large
+ def test_enotation_decimal(self):
+ """test exceedingly small decimals.
+
+ Decimal reports values with E notation when the exponent
+ is greater than 6.
+
+ """
+
+ numbers = set([
+ decimal.Decimal('1E-2'),
+ decimal.Decimal('1E-3'),
+ decimal.Decimal('1E-4'),
+ decimal.Decimal('1E-5'),
+ decimal.Decimal('1E-6'),
+ decimal.Decimal('1E-7'),
+ decimal.Decimal('1E-8'),
+ decimal.Decimal("0.01000005940696"),
+ decimal.Decimal("0.00000005940696"),
+ decimal.Decimal("0.00000000000696"),
+ decimal.Decimal("0.70000000000696"),
+ decimal.Decimal("696E-12"),
+ ])
+ self._do_test(
+ Numeric(precision=18, scale=14),
+ numbers,
+ numbers
+ )
+
+ @testing.requires.precision_numerics_enotation_large
+ def test_enotation_decimal_large(self):
+ """test exceedingly large decimals.
+
+ """
+
+ numbers = set([
+ decimal.Decimal('4E+8'),
+ decimal.Decimal("5748E+15"),
+ decimal.Decimal('1.521E+15'),
+ decimal.Decimal('00000000000000.1E+12'),
+ ])
+ self._do_test(
+ Numeric(precision=25, scale=2),
+ numbers,
+ numbers
+ )
+
+ @testing.requires.precision_numerics_many_significant_digits
+ def test_many_significant_digits(self):
+ numbers = set([
+ decimal.Decimal("31943874831932418390.01"),
+ decimal.Decimal("319438950232418390.273596"),
+ decimal.Decimal("87673.594069654243"),
+ ])
+ self._do_test(
+ Numeric(precision=38, scale=12),
+ numbers,
+ numbers
+ )
+
+ @testing.requires.precision_numerics_retains_significant_digits
+ def test_numeric_no_decimal(self):
+ numbers = set([
+ decimal.Decimal("1.000")
+ ])
+ self._do_test(
+ Numeric(precision=5, scale=3),
+ numbers,
+ numbers,
+ check_scale=True
+ )
+
+
__all__ = ('UnicodeVarcharTest', 'UnicodeTextTest',
'DateTest', 'DateTimeTest', 'TextTest',
+ 'NumericTest',
'DateTimeHistoricTest', 'DateTimeCoercedToDateTimeTest',
'TimeMicrosecondsTest', 'TimeTest', 'DateTimeMicrosecondsTest',
'DateHistoricTest', 'StringTest')