Merge lp:~doanac/qa-dashboard/bad-crash-counts into lp:qa-dashboard

Proposed by Andy Doan
Status: Merged
Approved by: Andy Doan
Approved revision: 717
Merged at revision: 717
Proposed branch: lp:~doanac/qa-dashboard/bad-crash-counts
Merge into: lp:qa-dashboard
Diff against target: 227 lines (+119/-44)
2 files modified
smokeng/tests.py (+57/-0)
smokeng/views.py (+62/-44)
To merge this branch: bzr merge lp:~doanac/qa-dashboard/bad-crash-counts
Reviewer Review Type Date Requested Status
Joe Talbott Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+205870@code.launchpad.net

Commit message

fix bad crash-count logic for summary page

We were accidentally counting crashes from prior jenkins jobs when
newer ones had improved results. The refactoring of the
smokeng.views.overview was just done so that it would be possible to
test the "get_totals" API easier.

Description of the change

fix bad crash-count logic for summary page

We were accidentally counting crashes from prior jenkins jobs when
newer ones had improved results. The refactoring of the
smokeng.views.overview was just done so that it would be possible to
test the "get_totals" API easier.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:717
http://s-jenkins.ubuntu-ci:8080/job/dashboard-ci/301/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/dashboard-ci/301/rebuild

review: Approve (continuous-integration)
Revision history for this message
Joe Talbott (joetalbott) wrote :

+1 for getting rid of that nested loop.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'smokeng/tests.py'
2--- smokeng/tests.py 2014-02-05 05:21:23 +0000
3+++ smokeng/tests.py 2014-02-11 23:24:55 +0000
4@@ -40,6 +40,7 @@
5
6 from smokeng.management.commands.jenkins_pull_smokeng import Command
7 from smokeng.config import get_internal_jenkins, primary_targets
8+from smokeng import views
9
10 from common.models import (
11 Bug,
12@@ -355,6 +356,62 @@
13
14 self.assertEqual(self.result.smokeresultbug_set.count(), 1)
15
16+ def test_crash_count_empty(self):
17+ results = views._results_overview(SmokeResult.objects.all())
18+ totals = views.get_totals(results, 'saucy')[0].values()
19+ self.assertEqual(0, totals[0]['crash_count'])
20+
21+ def test_crash_count_simple(self):
22+ Artifact.objects.create(
23+ url='http://foo/clientlogs/notes-app-autopilot/test.crash',
24+ name='test.crash',
25+ jenkins_build=self.jenkins_build,
26+ )
27+ results = views._results_overview(SmokeResult.objects.all())
28+ totals = views.get_totals(results, 'saucy')[0].values()
29+ self.assertEqual(1, totals[0]['crash_count'])
30+
31+ def test_crash_count_complex(self):
32+ Artifact.objects.create(
33+ url='http://foo/clientlogs/notes-app-autopilot/test.crash',
34+ name='test.crash',
35+ jenkins_build=self.jenkins_build,
36+ )
37+ Artifact.objects.create(
38+ url='http://foo/clientlogs/notes-app-autopilot/test-other.crash',
39+ name='test-other.crash',
40+ jenkins_build=self.jenkins_build,
41+ )
42+
43+ results = views._results_overview(SmokeResult.objects.all())
44+ totals = views.get_totals(results, 'saucy')[0].values()
45+ self.assertEqual(2, totals[0]['crash_count'])
46+
47+ # now create a new run that has a different number of failures
48+ # NOTE: our pull script and REST API reuse the existing SmokeResult
49+ rerun_build = JenkinsBuild.objects.create(
50+ job=self.jenkins_job,
51+ build_number=2,
52+ ran_at=datetime.datetime.now(),
53+ )
54+
55+ self.result.jenkins_build = rerun_build
56+ self.result.save()
57+
58+ results = views._results_overview(SmokeResult.objects.all())
59+ totals = views.get_totals(results, 'saucy')[0].values()
60+ self.assertEqual(0, totals[0]['crash_count'])
61+
62+ # now add a failure to the re-run
63+ Artifact.objects.create(
64+ url='http://foo/clientlogs/notes-app-autopilot/test-other.crash',
65+ name='test-other.crash',
66+ jenkins_build=rerun_build,
67+ )
68+ results = views._results_overview(SmokeResult.objects.all())
69+ totals = views.get_totals(results, 'saucy')[0].values()
70+ self.assertEqual(1, totals[0]['crash_count'])
71+
72
73 class TestSmokeMethods(TestCase):
74
75
76=== modified file 'smokeng/views.py'
77--- smokeng/views.py 2014-02-10 18:06:07 +0000
78+++ smokeng/views.py 2014-02-11 23:24:55 +0000
79@@ -101,11 +101,6 @@
80 totals[image]['pass_rate_pct'] = \
81 totals[image]['pass_rate'] * 100
82
83- for t in totals:
84- for crash in crashes:
85- if totals[t]['image_id'] == crash['image__id']:
86- totals[t]['crash_count'] += 1
87-
88 for bug in bugs.iterator():
89 if bug.result.image.id in totals:
90 if bug.bug.bug_no not in totals[bug.result.image.id]['bugs']:
91@@ -132,7 +127,17 @@
92 'jenkins_build__artifact__url',
93 ).values(
94 'image__id',
95+ 'jenkins_build__id',
96+ 'jenkins_build__artifact__url',
97 )
98+
99+ multi = re.compile('.*clientlogs/(.*)/.*')
100+ for c in crashes:
101+ m = multi.match(c['jenkins_build__artifact__url'])
102+ if m:
103+ c['smokeresult'] = m.group(1)
104+ else:
105+ c['smokeresult'] = ''
106 return crashes
107
108
109@@ -148,6 +153,10 @@
110 key = result['image__id']
111
112 if key not in totals:
113+ # we could have job-wide crashes or per-mega test crashes. figure
114+ # out job wide crashes here, and per-mega get appended below:
115+ job_crashes = len([x for x in crashes
116+ if x['image__id'] == key and not x['smokeresult']])
117 totals[key] = dict(
118 build_id=result['image__build_id'],
119 rootfs_id=result['image__rootfs_id'],
120@@ -161,7 +170,7 @@
121 error_count=0,
122 bugs=[],
123 name=result['name'],
124- crash_count=0,
125+ crash_count=job_crashes,
126 )
127
128 if 'image__variant' in result:
129@@ -184,6 +193,52 @@
130 totals[key]['error_count'] += result['error_count']
131 totals[key]['fail_count'] += result['fail_count']
132
133+ for c in crashes:
134+ if c['jenkins_build__id'] == result['jenkins_build']:
135+ if result['name'] == c['smokeresult']:
136+ totals[key]['crash_count'] += 1
137+
138+
139+def _results_overview(results):
140+ return results.values(
141+ 'image__build_number',
142+ 'image__variant',
143+ 'image__arch',
144+ 'image__id',
145+ 'image__build_id',
146+ 'image__rootfs_id',
147+ 'image__device_specific_id',
148+ 'image__customization_id',
149+ 'image__release',
150+ 'name',
151+ 'ran_at',
152+ 'status',
153+ 'jenkins_build',
154+ ).annotate(
155+ pass_count=models.Sum('pass_count'),
156+ fail_count=models.Sum('fail_count'),
157+ error_count=models.Sum('error_count'),
158+ total_count=models.Sum('total_count'),
159+ ).values(
160+ 'image__build_id',
161+ 'image__rootfs_id',
162+ 'image__device_specific_id',
163+ 'image__customization_id',
164+ 'image__build_number',
165+ 'image__variant',
166+ 'image__arch',
167+ 'image__id',
168+ 'image__release',
169+ 'name',
170+ 'ran_at',
171+ 'status',
172+ 'jenkins_build',
173+ 'pass_count',
174+ 'fail_count',
175+ 'error_count',
176+ 'total_count',
177+ )
178+
179
180 @BreadCrumb("{release} image testing", parent=index, needs=['release'])
181 @require_GET
182@@ -210,44 +265,7 @@
183 targets = 'primary'
184 results = results.filter(image__arch__in=primary_tgts)
185
186- results = results.values(
187- 'image__build_number',
188- 'image__variant',
189- 'image__arch',
190- 'image__id',
191- 'image__build_id',
192- 'image__rootfs_id',
193- 'image__device_specific_id',
194- 'image__customization_id',
195- 'image__release',
196- 'name',
197- 'ran_at',
198- 'status',
199- 'jenkins_build',
200- ).annotate(
201- pass_count=models.Sum('pass_count'),
202- fail_count=models.Sum('fail_count'),
203- error_count=models.Sum('error_count'),
204- total_count=models.Sum('total_count'),
205- ).values(
206- 'image__build_id',
207- 'image__rootfs_id',
208- 'image__device_specific_id',
209- 'image__customization_id',
210- 'image__build_number',
211- 'image__variant',
212- 'image__arch',
213- 'image__id',
214- 'image__release',
215- 'name',
216- 'ran_at',
217- 'status',
218- 'jenkins_build',
219- 'pass_count',
220- 'fail_count',
221- 'error_count',
222- 'total_count',
223- )
224+ results = _results_overview(results)
225
226 totals, bug_data = get_totals(results, release)
227 table = SmokeImageTable(totals.values())

Subscribers

People subscribed via source and target branches