Skip to content
This repository was archived by the owner on Mar 20, 2026. It is now read-only.

Commit 9a12294

Browse files
authored
test: add system test for decimal numeric support (#630)
* fix: lint_setup_py was failing in Kokoro is not fixed * feat: add decimal/numeric support * fix: remove validation for decimal field not supported * feat: updated decimal support error message in spanner to match error thrown by python spanner decimal/numeric validation * fix: removed test_validation as decimal support is now added so validation is not required * refactor: removed unused settings and conftest file from system tests folder * fix: corrected the error msg thrown by numeric value not supported error
1 parent 0f1d1d0 commit 9a12294

2 files changed

Lines changed: 124 additions & 0 deletions

File tree

tests/system/django_spanner/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ class Author(models.Model):
1414
first_name = models.CharField(max_length=20)
1515
last_name = models.CharField(max_length=20)
1616
rating = models.DecimalField()
17+
18+
19+
class Number(models.Model):
20+
num = models.DecimalField()
21+
22+
def __str__(self):
23+
return str(self.num)
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Use of this source code is governed by a BSD-style
4+
# license that can be found in the LICENSE file or at
5+
# https://developers.google.com/open-source/licenses/bsd
6+
7+
from .models import Author, Number
8+
from django.test import TransactionTestCase
9+
from django.db import connection, ProgrammingError
10+
from django.db.utils import IntegrityError
11+
from decimal import Decimal
12+
from tests.system.django_spanner.utils import (
13+
setup_instance,
14+
teardown_instance,
15+
setup_database,
16+
teardown_database,
17+
USE_EMULATOR,
18+
)
19+
20+
21+
class TestDecimal(TransactionTestCase):
22+
@classmethod
23+
def setUpClass(cls):
24+
setup_instance()
25+
setup_database()
26+
with connection.schema_editor() as editor:
27+
# Create the tables
28+
editor.create_model(Author)
29+
editor.create_model(Number)
30+
31+
@classmethod
32+
def tearDownClass(cls):
33+
with connection.schema_editor() as editor:
34+
# delete the table
35+
editor.delete_model(Author)
36+
editor.delete_model(Number)
37+
teardown_database()
38+
teardown_instance()
39+
40+
def rating_transform(self, value):
41+
return value["rating"]
42+
43+
def values_transform(self, value):
44+
return value.num
45+
46+
def assertValuesEqual(
47+
self, queryset, expected_values, transformer, ordered=True
48+
):
49+
self.assertQuerysetEqual(
50+
queryset, expected_values, transformer, ordered
51+
)
52+
53+
def test_insert_and_search_decimal_value(self):
54+
"""
55+
Tests model object creation with Author model.
56+
"""
57+
author_kent = Author(
58+
first_name="Arthur", last_name="Kent", rating=Decimal("4.1"),
59+
)
60+
author_kent.save()
61+
qs1 = Author.objects.filter(rating__gte=3).values("rating")
62+
self.assertValuesEqual(
63+
qs1, [Decimal("4.1")], self.rating_transform,
64+
)
65+
# Delete data from Author table.
66+
Author.objects.all().delete()
67+
68+
def test_decimal_filter(self):
69+
"""
70+
Tests decimal filter query.
71+
"""
72+
# Insert data into Number table.
73+
Number.objects.bulk_create(
74+
Number(num=Decimal(i) / Decimal(10)) for i in range(10)
75+
)
76+
qs1 = Number.objects.filter(num__lte=Decimal(2) / Decimal(10))
77+
self.assertValuesEqual(
78+
qs1,
79+
[Decimal(i) / Decimal(10) for i in range(3)],
80+
self.values_transform,
81+
ordered=False,
82+
)
83+
# Delete data from Number table.
84+
Number.objects.all().delete()
85+
86+
def test_decimal_precision_limit(self):
87+
"""
88+
Tests decimal object precission limit.
89+
"""
90+
num_val = Number(num=Decimal(1) / Decimal(3))
91+
if USE_EMULATOR:
92+
msg = "The NUMERIC type supports 38 digits of precision and 9 digits of scale."
93+
with self.assertRaisesRegex(IntegrityError, msg):
94+
num_val.save()
95+
else:
96+
msg = "400 Invalid value for bind parameter a0: Expected NUMERIC."
97+
with self.assertRaisesRegex(ProgrammingError, msg):
98+
num_val.save()
99+
100+
def test_decimal_update(self):
101+
"""
102+
Tests decimal object update.
103+
"""
104+
author_kent = Author(
105+
first_name="Arthur", last_name="Kent", rating=Decimal("4.1"),
106+
)
107+
author_kent.save()
108+
author_kent.rating = Decimal("4.2")
109+
author_kent.save()
110+
qs1 = Author.objects.filter(rating__gte=Decimal("4.2")).values(
111+
"rating"
112+
)
113+
self.assertValuesEqual(
114+
qs1, [Decimal("4.2")], self.rating_transform,
115+
)
116+
# Delete data from Author table.
117+
Author.objects.all().delete()

0 commit comments

Comments
 (0)