GFKManagerTestCase.test_fetch_generic_relations()   F
last analyzed

Complexity

Conditions 18

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
c 0
b 0
f 0
dl 0
loc 46
rs 1.2

How to fix   Complexity   

Complexity

Complex classes like GFKManagerTestCase.test_fetch_generic_relations() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
from django.test import TestCase
2
from django.contrib.auth import get_user_model
3
from django.contrib.contenttypes.models import ContentType
4
from django.contrib.auth.models import Group
5
6
from actstream.models import Action
7
from actstream.tests.base import LTE
8
9
10
class GFKManagerTestCase(TestCase):
11
12
    def setUp(self):
13
        User = get_user_model()
14
        self.user_ct = ContentType.objects.get_for_model(User)
15
        self.group_ct = ContentType.objects.get_for_model(Group)
16
        self.group, _ = Group.objects.get_or_create(name='CoolGroup')
17
        self.user1, _ = User.objects.get_or_create(username='admin')
18
        self.user2, _ = User.objects.get_or_create(username='Two')
19
        self.user3, _ = User.objects.get_or_create(username='Three')
20
        self.user4, _ = User.objects.get_or_create(username='Four')
21
        Action.objects.get_or_create(
22
            actor_content_type=self.user_ct,
23
            actor_object_id=self.user1.id,
24
            verb='followed',
25
            target_content_type=self.user_ct,
26
            target_object_id=self.user2.id
27
        )
28
        Action.objects.get_or_create(
29
            actor_content_type=self.user_ct,
30
            actor_object_id=self.user1.id,
31
            verb='followed',
32
            target_content_type=self.user_ct,
33
            target_object_id=self.user3.id
34
        )
35
        Action.objects.get_or_create(
36
            actor_content_type=self.user_ct,
37
            actor_object_id=self.user1.id,
38
            verb='followed',
39
            target_content_type=self.user_ct,
40
            target_object_id=self.user4.id
41
        )
42
        Action.objects.get_or_create(
43
            actor_content_type=self.user_ct,
44
            actor_object_id=self.user1.id,
45
            verb='joined',
46
            target_content_type=self.group_ct,
47
            target_object_id=self.group.id
48
        )
49
50
    def test_fetch_generic_relations(self):
51
        # baseline without fetch_generic_relations
52
        _actions = Action.objects.filter(actor_content_type=self.user_ct,
53
                                         actor_object_id=self.user1.id)
54
        actions = lambda: _actions._clone()
55
        num_content_types = len(set(actions().values_list(
56
            'target_content_type_id', flat=True)))
57
        n = actions().count()
58
59
        # compare to fetching only 1 generic relation
60
        full, generic = actions(), actions().fetch_generic_relations('target')
61
        self.assertNumQueries(LTE(n + 1),
62
                              lambda: [a.target for a in full])
63
        self.assertNumQueries(LTE(num_content_types + 2),
64
                              lambda: [a.target for a in generic])
65
66
        action_targets = [(a.id, a.target) for a in actions()]
67
        action_targets_fetch_generic = [
68
            (a.id, a.target)
69
            for a in actions().fetch_generic_relations('target')]
70
        self.assertEqual(action_targets, action_targets_fetch_generic)
71
72
        # compare to fetching all generic relations
73
        num_content_types = len(set(sum(actions().values_list(
74
            'actor_content_type_id', 'target_content_type_id'), ())))
75
        full, generic = actions(), actions().fetch_generic_relations()
76
        self.assertNumQueries(LTE(2 * n + 1),
77
                              lambda: [(a.actor, a.target) for a in full])
78
        self.assertNumQueries(LTE(num_content_types + 2),
79
                              lambda: [(a.actor, a.target) for a in generic])
80
81
        action_actor_targets = [(a.id, a.actor, a.target) for a in actions()]
82
        action_actor_targets_fetch_generic_all = [
83
            (a.id, a.actor, a.target)
84
            for a in actions().fetch_generic_relations()]
85
        self.assertEqual(action_actor_targets,
86
                         action_actor_targets_fetch_generic_all)
87
88
        # fetch only 1 generic relation, but access both gfks
89
        generic = lambda: actions().fetch_generic_relations('target')
90
        self.assertNumQueries(LTE(n + num_content_types + 2), lambda: [
91
            (a.actor, a.target) for a in generic()])
92
        action_actor_targets_fetch_generic_target = [
93
            (a.id, a.actor, a.target) for a in generic()]
94
        self.assertEqual(action_actor_targets,
95
                         action_actor_targets_fetch_generic_target)
96