summaryrefslogtreecommitdiff
path: root/tests/expressions
diff options
context:
space:
mode:
authorLuke Plant <L.Plant.98@cantab.net>2022-03-30 10:56:13 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-03-30 11:03:48 +0200
commit04ad0f26ba4b8c79dc311e1789457e0c4d1b8832 (patch)
tree70b945d429808bc45c2b90fbc41e79b484dceaf4 /tests/expressions
parentfac662f4798f7e4e0ed9be6b4fb4a87a80810a68 (diff)
downloaddjango-04ad0f26ba4b8c79dc311e1789457e0c4d1b8832.tar.gz
Refs #33397 -- Added extra tests for resolving an output_field of CombinedExpression.
Diffstat (limited to 'tests/expressions')
-rw-r--r--tests/expressions/tests.py90
1 files changed, 89 insertions, 1 deletions
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index 12bf8996d1..a3d8d9b187 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -1724,6 +1724,28 @@ class FTimeDeltaTests(TestCase):
]
self.assertEqual(test_set, self.expnames[: i + 1])
+ def test_datetime_and_durationfield_addition_with_filter(self):
+ test_set = Experiment.objects.filter(end=F("start") + F("estimated_time"))
+ self.assertGreater(test_set.count(), 0)
+ self.assertEqual(
+ [e.name for e in test_set],
+ [
+ e.name
+ for e in Experiment.objects.all()
+ if e.end == e.start + e.estimated_time
+ ],
+ )
+
+ @skipUnlessDBFeature("supports_temporal_subtraction")
+ def test_datetime_subtraction_with_annotate_and_no_output_field(self):
+ test_set = Experiment.objects.annotate(
+ calculated_duration=F("end") - F("start")
+ )
+ self.assertEqual(
+ [e.calculated_duration for e in test_set],
+ [e.end - e.start for e in test_set],
+ )
+
def test_mixed_comparisons1(self):
for i, delay in enumerate(self.delays):
test_set = [
@@ -2373,7 +2395,7 @@ class CombinableTests(SimpleTestCase):
class CombinedExpressionTests(SimpleTestCase):
- def test_resolve_output_field(self):
+ def test_resolve_output_field_number(self):
tests = [
(IntegerField, AutoField, IntegerField),
(AutoField, IntegerField, IntegerField),
@@ -2395,6 +2417,72 @@ class CombinedExpressionTests(SimpleTestCase):
)
self.assertIsInstance(expr.output_field, combined)
+ def test_resolve_output_field_with_null(self):
+ def null():
+ return Value(None)
+
+ tests = [
+ # Numbers.
+ (AutoField, Combinable.ADD, null),
+ (DecimalField, Combinable.ADD, null),
+ (FloatField, Combinable.ADD, null),
+ (IntegerField, Combinable.ADD, null),
+ (IntegerField, Combinable.SUB, null),
+ (null, Combinable.ADD, IntegerField),
+ # Dates.
+ (DateField, Combinable.ADD, null),
+ (DateTimeField, Combinable.ADD, null),
+ (DurationField, Combinable.ADD, null),
+ (TimeField, Combinable.ADD, null),
+ (TimeField, Combinable.SUB, null),
+ (null, Combinable.ADD, DateTimeField),
+ (DateField, Combinable.SUB, null),
+ ]
+ msg = "Expression contains mixed types: "
+ for lhs, connector, rhs in tests:
+ with self.subTest(lhs=lhs, connector=connector, rhs=rhs):
+ expr = CombinedExpression(
+ Expression(lhs()),
+ connector,
+ Expression(rhs()),
+ )
+ with self.assertRaisesMessage(FieldError, msg):
+ expr.output_field
+
+ def test_resolve_output_field_dates(self):
+ tests = [
+ # Add - same type.
+ (DurationField, Combinable.ADD, DurationField, DurationField),
+ # Subtract - same type.
+ (DurationField, Combinable.SUB, DurationField, DurationField),
+ # Subtract - different type.
+ (DurationField, Combinable.SUB, DateField, FieldError),
+ (DurationField, Combinable.SUB, DateTimeField, FieldError),
+ (DurationField, Combinable.SUB, DateTimeField, FieldError),
+ ]
+ msg = "Expression contains mixed types: "
+ for lhs, connector, rhs, combined in tests:
+ with self.subTest(lhs=lhs, connector=connector, rhs=rhs, combined=combined):
+ expr = CombinedExpression(
+ Expression(lhs()),
+ connector,
+ Expression(rhs()),
+ )
+ if issubclass(combined, Exception):
+ with self.assertRaisesMessage(combined, msg):
+ expr.output_field
+ else:
+ self.assertIsInstance(expr.output_field, combined)
+
+ def test_mixed_char_date_with_annotate(self):
+ queryset = Experiment.objects.annotate(nonsense=F("name") + F("assigned"))
+ msg = (
+ "Expression contains mixed types: CharField, DateField. You must set "
+ "output_field."
+ )
+ with self.assertRaisesMessage(FieldError, msg):
+ list(queryset)
+
class ExpressionWrapperTests(SimpleTestCase):
def test_empty_group_by(self):