Passed
Push — master ( 3727b7...72c322 )
by Alexander
02:28
created

TestExecutionDataMixin.get_case_runs_comments()   B

Complexity

Conditions 5

Size

Total Lines 41
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 41
rs 8.7893
c 0
b 0
f 0
cc 5
nop 1
1
# -*- coding: utf-8 -*-
2
3
from itertools import groupby
4
5
from django.conf import settings
6
from django.db.models import F
7
from django.contrib.contenttypes.models import ContentType
8
from django_comments.models import Comment
9
10
from tcms.testcases.models import Bug
11
from tcms.testruns.models import TestExecution
12
from tcms.testruns.models import TestExecutionStatus
13
14
15
def get_run_bug_ids(run_id):
16
    """Get list of pairs of bug ID and bug link that are added to a run
17
18
    :param int run_id: ID of test run.
19
    :return: list of pairs of bug ID and bug link.
20
    :rtype: list
21
    """
22
    return Bug.objects.values(
23
        'bug_id',
24
        'bug_system',
25
        'bug_system__tracker_type',
26
        'bug_system__url_reg_exp'
27
    ).distinct().filter(case_run__run=run_id)
28
29
30
class TestExecutionDataMixin:
31
    """Data for test case runs"""
32
33
    @staticmethod
34
    def stats_mode_case_runs(case_runs):
35
        """
36
            Statistics from case runs mode
37
38
            :param case_runs: iteratable object to access each case run
39
            :type case_runs: iterable, list, tuple
40
            :return: mapping between mode and the count. Example return value is
41
                     `{ 'manual': I, 'automated': J }`
42
            :rtype: dict
43
        """
44
        manual_count = 0
45
        automated_count = 0
46
47
        for case_run in case_runs:
48
            if case_run.case.is_automated:
49
                automated_count += 1
50
            else:
51
                manual_count += 1
52
53
        return {
54
            'manual': manual_count,
55
            'automated': automated_count,
56
        }
57
58
    @staticmethod
59
    def get_case_runs_bugs(run_pk):
60
        """Get case run bugs for run report
61
62
        :param int run_pk: run's pk whose case runs' bugs will be retrieved.
63
        :return: the mapping between case run id and bug information containing
64
            formatted bug URL.
65
        :rtype: dict
66
        """
67
68
        bugs = Bug.objects.filter(
69
            case_run__run=run_pk
70
        ).values(
71
            'case_run',
72
            'bug_id',
73
            'bug_system__url_reg_exp'
74
        ).order_by('case_run')
75
76
        rows = []
77
        for row in bugs:
78
            row['bug_url'] = row['bug_system__url_reg_exp'] % row['bug_id']
79
            rows.append(row)
80
81
        case_run_bugs = {}
82
        for case_run_id, bugs_info in groupby(rows, lambda row: row['case_run']):
83
            case_run_bugs[case_run_id] = list(bugs_info)
84
85
        return case_run_bugs
86
87
    @staticmethod
88
    def get_case_runs_comments(run_pk):
89
        """Get case runs' comments
90
91
        :param run_pk: run's pk whose comments will be retrieved.
92
        :type run_pk: int
93
        :return: the mapping between case run id and comments
94
        :rtype: dict
95
        """
96
        # note: cast to string b/c object_pk is a Textield and PostgreSQL
97
        # doesn't like TEXT in <list of integers>
98
        # in Django 1.10 we have the Cast() function for similar cases, see
99
        # https://docs.djangoproject.com/en/1.10/ref/models/database-functions/#cast
100
        object_pks = []
101
        for test_case_run in TestExecution.objects.filter(run=run_pk).only('pk'):
102
            object_pks.append(str(test_case_run.pk))
103
104
        comments = Comment.objects.filter(
105
            site=settings.SITE_ID,
106
            content_type=ContentType.objects.get_for_model(TestExecution).pk,
107
            is_public=True,
108
            is_removed=False,
109
            object_pk__in=object_pks
110
        ).annotate(
111
            case_run_id=F('object_pk')
112
        ).values(
113
            'case_run_id',
114
            'submit_date',
115
            'comment',
116
            'user_name'
117
        ).order_by('case_run_id')
118
119
        rows = []
120
        for row in comments:
121
            rows.append(row)
122
123
        case_run_comments = {}
124
        for key, groups in groupby(rows, lambda row: row['case_run_id']):
125
            case_run_comments[int(key)] = list(groups)
0 ignored issues
show
Comprehensibility Best Practice introduced by Anton Sankov
The variable int does not seem to be defined.
Loading history...
126
127
        return case_run_comments
128
129
    @staticmethod
130
    def get_summary_stats(case_runs):
131
        """Get summary statistics from case runs
132
133
        Statistics targets:
134
135
        - the number of pending test case runs, whose status is IDLE
136
        - the number of completed test case runs, whose status are PASSED,
137
          ERROR, FAILED, WAIVED
138
139
        :param case_runs: iterable object containing case runs
140
        :type case_runs: iterable
141
        :return: a mapping between statistics target and its value
142
        :rtype: dict
143
        """
144
        idle_count = 0
145
        complete_count = 0
146
        complete_status_names = TestExecutionStatus.complete_status_names
147
        idle_status_names = TestExecutionStatus.idle_status_names
148
149
        for case_run in case_runs:
150
            status_name = case_run.status.name
151
            if status_name in idle_status_names:
152
                idle_count += 1
153
            elif status_name in complete_status_names:
154
                complete_count += 1
155
156
        return {'idle': idle_count, 'complete': complete_count}
157