Skip to content

Commit dc2fd96

Browse files
committed
[soc2010/test-refactor] Updated expressions modeltest to unittests
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2010/test-refactor@13378 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 52a855f commit dc2fd96

File tree

3 files changed

+200
-105
lines changed

3 files changed

+200
-105
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
[
2+
{
3+
"pk": 1,
4+
"model": "expressions.employee",
5+
"fields": {
6+
"lastname": "Smith",
7+
"firstname": "Joe"
8+
}
9+
},
10+
{
11+
"pk": 2,
12+
"model": "expressions.employee",
13+
"fields": {
14+
"lastname": "Meyer",
15+
"firstname": "Frank"
16+
}
17+
},
18+
{
19+
"pk": 3,
20+
"model": "expressions.employee",
21+
"fields": {
22+
"lastname": "Mustermann",
23+
"firstname": "Max"
24+
}
25+
},
26+
{
27+
"pk": 4,
28+
"model": "expressions.employee",
29+
"fields": {
30+
"lastname": "van Rossum",
31+
"firstname": "Guido"
32+
}
33+
},
34+
{
35+
"pk": 1,
36+
"model": "expressions.company",
37+
"fields": {
38+
"ceo": 1,
39+
"num_chairs": 5,
40+
"point_of_contact": 4,
41+
"name": "Example Inc.",
42+
"num_employees": 2300
43+
}
44+
},
45+
{
46+
"pk": 2,
47+
"model": "expressions.company",
48+
"fields": {
49+
"ceo": 2,
50+
"num_chairs": 3,
51+
"point_of_contact": 2,
52+
"name": "Foobar Ltd.",
53+
"num_employees": 3
54+
}
55+
},
56+
{
57+
"pk": 3,
58+
"model": "expressions.company",
59+
"fields": {
60+
"ceo": 3,
61+
"num_chairs": 1,
62+
"point_of_contact": 3,
63+
"name": "Test GmbH",
64+
"num_employees": 32
65+
}
66+
}
67+
]

tests/modeltests/expressions/models.py

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -25,108 +25,3 @@ class Company(models.Model):
2525

2626
def __unicode__(self):
2727
return self.name
28-
29-
30-
__test__ = {'API_TESTS': """
31-
>>> from django.db.models import F
32-
33-
>>> Company(name='Example Inc.', num_employees=2300, num_chairs=5,
34-
... ceo=Employee.objects.create(firstname='Joe', lastname='Smith')).save()
35-
>>> Company(name='Foobar Ltd.', num_employees=3, num_chairs=3,
36-
... ceo=Employee.objects.create(firstname='Frank', lastname='Meyer')).save()
37-
>>> Company(name='Test GmbH', num_employees=32, num_chairs=1,
38-
... ceo=Employee.objects.create(firstname='Max', lastname='Mustermann')).save()
39-
40-
>>> company_query = Company.objects.values('name','num_employees','num_chairs').order_by('name','num_employees','num_chairs')
41-
42-
# We can filter for companies where the number of employees is greater than the
43-
# number of chairs.
44-
>>> company_query.filter(num_employees__gt=F('num_chairs'))
45-
[{'num_chairs': 5, 'name': u'Example Inc.', 'num_employees': 2300}, {'num_chairs': 1, 'name': u'Test GmbH', 'num_employees': 32}]
46-
47-
# We can set one field to have the value of another field
48-
# Make sure we have enough chairs
49-
>>> _ = company_query.update(num_chairs=F('num_employees'))
50-
>>> company_query
51-
[{'num_chairs': 2300, 'name': u'Example Inc.', 'num_employees': 2300}, {'num_chairs': 3, 'name': u'Foobar Ltd.', 'num_employees': 3}, {'num_chairs': 32, 'name': u'Test GmbH', 'num_employees': 32}]
52-
53-
# We can perform arithmetic operations in expressions
54-
# Make sure we have 2 spare chairs
55-
>>> _ =company_query.update(num_chairs=F('num_employees')+2)
56-
>>> company_query
57-
[{'num_chairs': 2302, 'name': u'Example Inc.', 'num_employees': 2300}, {'num_chairs': 5, 'name': u'Foobar Ltd.', 'num_employees': 3}, {'num_chairs': 34, 'name': u'Test GmbH', 'num_employees': 32}]
58-
59-
# Law of order of operations is followed
60-
>>> _ =company_query.update(num_chairs=F('num_employees') + 2 * F('num_employees'))
61-
>>> company_query
62-
[{'num_chairs': 6900, 'name': u'Example Inc.', 'num_employees': 2300}, {'num_chairs': 9, 'name': u'Foobar Ltd.', 'num_employees': 3}, {'num_chairs': 96, 'name': u'Test GmbH', 'num_employees': 32}]
63-
64-
# Law of order of operations can be overridden by parentheses
65-
>>> _ =company_query.update(num_chairs=((F('num_employees') + 2) * F('num_employees')))
66-
>>> company_query
67-
[{'num_chairs': 5294600, 'name': u'Example Inc.', 'num_employees': 2300}, {'num_chairs': 15, 'name': u'Foobar Ltd.', 'num_employees': 3}, {'num_chairs': 1088, 'name': u'Test GmbH', 'num_employees': 32}]
68-
69-
# The relation of a foreign key can become copied over to an other foreign key.
70-
>>> Company.objects.update(point_of_contact=F('ceo'))
71-
3
72-
73-
>>> [c.point_of_contact for c in Company.objects.all()]
74-
[<Employee: Joe Smith>, <Employee: Frank Meyer>, <Employee: Max Mustermann>]
75-
76-
>>> c = Company.objects.all()[0]
77-
>>> c.point_of_contact = Employee.objects.create(firstname="Guido", lastname="van Rossum")
78-
>>> c.save()
79-
80-
# F Expressions can also span joins
81-
>>> Company.objects.filter(ceo__firstname=F('point_of_contact__firstname')).distinct().order_by('name')
82-
[<Company: Foobar Ltd.>, <Company: Test GmbH>]
83-
84-
>>> _ = Company.objects.exclude(ceo__firstname=F('point_of_contact__firstname')).update(name='foo')
85-
>>> Company.objects.exclude(ceo__firstname=F('point_of_contact__firstname')).get().name
86-
u'foo'
87-
88-
>>> _ = Company.objects.exclude(ceo__firstname=F('point_of_contact__firstname')).update(name=F('point_of_contact__lastname'))
89-
Traceback (most recent call last):
90-
...
91-
FieldError: Joined field references are not permitted in this query
92-
93-
# F expressions can be used to update attributes on single objects
94-
>>> test_gmbh = Company.objects.get(name='Test GmbH')
95-
>>> test_gmbh.num_employees
96-
32
97-
>>> test_gmbh.num_employees = F('num_employees') + 4
98-
>>> test_gmbh.save()
99-
>>> test_gmbh = Company.objects.get(pk=test_gmbh.pk)
100-
>>> test_gmbh.num_employees
101-
36
102-
103-
# F expressions cannot be used to update attributes which are foreign keys, or
104-
# attributes which involve joins.
105-
>>> test_gmbh.point_of_contact = None
106-
>>> test_gmbh.save()
107-
>>> test_gmbh.point_of_contact is None
108-
True
109-
>>> test_gmbh.point_of_contact = F('ceo')
110-
Traceback (most recent call last):
111-
...
112-
ValueError: Cannot assign "<django.db.models.expressions.F object at ...>": "Company.point_of_contact" must be a "Employee" instance.
113-
114-
>>> test_gmbh.point_of_contact = test_gmbh.ceo
115-
>>> test_gmbh.save()
116-
>>> test_gmbh.name = F('ceo__last_name')
117-
>>> test_gmbh.save()
118-
Traceback (most recent call last):
119-
...
120-
FieldError: Joined field references are not permitted in this query
121-
122-
# F expressions cannot be used to update attributes on objects which do not yet
123-
# exist in the database
124-
>>> acme = Company(name='The Acme Widget Co.', num_employees=12, num_chairs=5,
125-
... ceo=test_gmbh.ceo)
126-
>>> acme.num_employees = F('num_employees') + 16
127-
>>> acme.save()
128-
Traceback (most recent call last):
129-
...
130-
TypeError: ...
131-
132-
"""}

tests/modeltests/expressions/tests.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
from django.test import TestCase
2+
3+
from django.db.models import F
4+
from django.core.exceptions import FieldError
5+
6+
from models import Employee, Company
7+
8+
class ExpressionsTestCase(TestCase):
9+
fixtures = ['f_expression_testdata.json']
10+
11+
def assertItemsEqual(self, a, b):
12+
#fixme, replace with unittest2 function
13+
return self.assertEqual(sorted(a), sorted(b))
14+
15+
def test_basic_f_expression(self):
16+
company_query = Company.objects.values('name','num_employees',
17+
'num_chairs'
18+
).order_by('name',
19+
'num_employees',
20+
'num_chairs')
21+
# We can filter for companies where the number of employees is
22+
# greater than the number of chairs.
23+
self.assertItemsEqual(company_query.filter(
24+
num_employees__gt=F('num_chairs')),
25+
[{'num_chairs': 5, 'name': u'Example Inc.',
26+
'num_employees': 2300},
27+
{'num_chairs': 1, 'name': u'Test GmbH',
28+
'num_employees': 32}])
29+
30+
# We can set one field to have the value of another field Make
31+
# sure we have enough chairs
32+
company_query.update(num_chairs=F('num_employees'))
33+
self.assertItemsEqual(company_query,
34+
[{'num_chairs': 2300, 'name': u'Example Inc.',
35+
'num_employees': 2300},
36+
{'num_chairs': 3, 'name': u'Foobar Ltd.',
37+
'num_employees': 3},
38+
{'num_chairs': 32, 'name': u'Test GmbH',
39+
'num_employees': 32}])
40+
41+
# We can perform arithmetic operations in expressions. Make
42+
# sure we have 2 spare chairs
43+
company_query.update(num_chairs=F('num_employees')+2)
44+
self.assertItemsEqual(company_query,
45+
[{'num_chairs': 2302, 'name': u'Example Inc.',
46+
'num_employees': 2300},
47+
{'num_chairs': 5, 'name': u'Foobar Ltd.',
48+
'num_employees': 3},
49+
{'num_chairs': 34, 'name': u'Test GmbH',
50+
'num_employees': 32}])
51+
52+
# Law of order of operations is followed
53+
company_query.update(num_chairs=F('num_employees') +
54+
2 * F('num_employees'))
55+
self.assertItemsEqual(company_query,
56+
[{'num_chairs': 6900, 'name': u'Example Inc.',
57+
'num_employees': 2300},
58+
{'num_chairs': 9, 'name': u'Foobar Ltd.',
59+
'num_employees': 3},
60+
{'num_chairs': 96, 'name': u'Test GmbH',
61+
'num_employees': 32}])
62+
63+
# Law of order of operations can be overridden by parentheses
64+
company_query.update(num_chairs=((F('num_employees') + 2) *
65+
F('num_employees')))
66+
self.assertItemsEqual(company_query,
67+
[{'num_chairs': 5294600, 'name': u'Example Inc.',
68+
'num_employees': 2300},
69+
{'num_chairs': 15, 'name': u'Foobar Ltd.',
70+
'num_employees': 3},
71+
{'num_chairs': 1088, 'name': u'Test GmbH',
72+
'num_employees': 32}])
73+
74+
# The relation of a foreign key can become copied over to an
75+
# other foreign key.
76+
self.assertEqual(Company.objects.update(point_of_contact=F('ceo')), 3)
77+
78+
79+
self.assertEqual(repr([c.point_of_contact for
80+
c in Company.objects.all()]),
81+
'[<Employee: Joe Smith>, <Employee: Frank Meyer>, <Employee: Max Mustermann>]')
82+
83+
def test_f_expression_spanning_join(self):
84+
# F Expressions can also span joins
85+
self.assertQuerysetEqual(
86+
Company.objects.filter(
87+
ceo__firstname=F('point_of_contact__firstname')
88+
).distinct().order_by('name'),
89+
['<Company: Foobar Ltd.>', '<Company: Test GmbH>'])
90+
91+
Company.objects.exclude(
92+
ceo__firstname=F('point_of_contact__firstname')
93+
).update(name='foo')
94+
self.assertEqual(Company.objects.exclude(
95+
ceo__firstname=F('point_of_contact__firstname')
96+
).get().name,
97+
u'foo')
98+
99+
self.assertRaises(FieldError,
100+
Company.objects.exclude(ceo__firstname=F('point_of_contact__firstname')).update,
101+
name=F('point_of_contact__lastname'))
102+
103+
def test_f_expression_update_attribute(self):
104+
# F expressions can be used to update attributes on single objects
105+
test_gmbh = Company.objects.get(name='Test GmbH')
106+
self.assertEqual(test_gmbh.num_employees, 32)
107+
test_gmbh.num_employees = F('num_employees') + 4
108+
test_gmbh.save()
109+
test_gmbh = Company.objects.get(pk=test_gmbh.pk)
110+
self.assertEqual(test_gmbh.num_employees, 36)
111+
112+
# F expressions cannot be used to update attributes which are
113+
# foreign keys, or attributes which involve joins.
114+
test_gmbh.point_of_contact = None
115+
test_gmbh.save()
116+
self.assertEqual(test_gmbh.point_of_contact, None)
117+
self.assertRaises(ValueError,
118+
setattr,
119+
test_gmbh, 'point_of_contact', F('ceo'))
120+
121+
test_gmbh.point_of_contact = test_gmbh.ceo
122+
test_gmbh.save()
123+
test_gmbh.name = F('ceo__last_name')
124+
self.assertRaises(FieldError,
125+
test_gmbh.save)
126+
127+
# F expressions cannot be used to update attributes on objects
128+
# which do not yet exist in the database
129+
acme = Company(name='The Acme Widget Co.', num_employees=12,
130+
num_chairs=5, ceo=test_gmbh.ceo)
131+
acme.num_employees = F('num_employees') + 16
132+
self.assertRaises(TypeError,
133+
acme.save)

0 commit comments

Comments
 (0)