Merge ~pwlars/checkbox-ng:get-test-outcome-stats into checkbox-ng:master

Proposed by Paul Larson
Status: Merged
Approved by: Paul Larson
Approved revision: b26dca3e411eafbf18383a221a074c9c5969322a
Merged at revision: 917b76e1e5095b147a77cd4055818495c25c63b0
Proposed branch: ~pwlars/checkbox-ng:get-test-outcome-stats
Merge into: checkbox-ng:master
Diff against target: 65 lines (+27/-10)
2 files modified
plainbox/impl/providers/exporters/data/junit.xml (+7/-10)
plainbox/impl/session/state.py (+20/-0)
Reviewer Review Type Date Requested Status
Sylvain Pineau (community) Needs Information
Maciej Kisielewski Approve
Review via email: mp+344338@code.launchpad.net

Description of the change

It seems that the stats we generate for junit don't match up with the stats we generate for the c3 submission. This is because the junit stats do not filter out the resource and attachment jobs. This restricts junit output to only look at those, and adds a new helper method in states.py to facilitate getting the right set of stats for only actual tests.

To post a comment you must log in.
Revision history for this message
Paul Larson (pwlars) wrote :

I almost forgot to mention... I tested this by creating a small dummy provider with 2 simple tests (one pass, one fail) and 2 attachment jobs (1 pass, 1 fail). Without the patch, I see 4 tests, 2 fails. With the pass, I only see the two actual tests, with 1 failed.

Revision history for this message
Maciej Kisielewski (kissiel) wrote :

Very nice! +1

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

I'd keep resources and attachments in the big picture as they can fail (generating less jobs for example or lead to other tricky side effects). This patchset ignores/filters them and I don't think it's a good idea if we are basing automated reviews exclusively on "real" jobs.

Where should we tweak reports to add the missing resource/attachments and keep the existing junit.xml?

review: Needs Information
Revision history for this message
Paul Larson (pwlars) wrote :

The problem isn't with the results summary, as that uses the submission.json and results for artifacts/resource already don't show up in the submission.json. The problem I was trying to solve with this is that when you look at c3 results and at jenkins results for the same test, they often differ greatly in the number of tests executed, failed, etc. The goal is to make those numbers match so that it's less confusing. I don't think jenkins (nor junit) give us a good ability to set up another class of tests that gets filtered from the main results

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/plainbox/impl/providers/exporters/data/junit.xml b/plainbox/impl/providers/exporters/data/junit.xml
index 2a7e64a..2ac1115 100644
--- a/plainbox/impl/providers/exporters/data/junit.xml
+++ b/plainbox/impl/providers/exporters/data/junit.xml
@@ -1,15 +1,13 @@
1{%- set state = manager.default_device_context.state -%}1{%- set state = manager.default_device_context.state -%}
2{%- set job_state_map = state.job_state_map -%}2{%- set job_state_map = state.job_state_map -%}
3{%- set passes = manager.state.get_outcome_stats()["pass"] -%}3{%- set passes = manager.state.get_test_outcome_stats()["pass"] -%}
4{%- set fails = manager.state.get_outcome_stats()["fail"] -%}4{%- set fails = manager.state.get_test_outcome_stats()["fail"] -%}
5{%- set skips = manager.state.get_outcome_stats()["skip"] + 5{%- set skips = manager.state.get_test_outcome_stats()["skip"] +
6 manager.state.get_outcome_stats()["not-supported"] -%} 6 manager.state.get_test_outcome_stats()["not-supported"] -%}
7{%- set errors = manager.state.get_outcome_stats()["crash"] -%}7{%- set errors = manager.state.get_test_outcome_stats()["crash"] -%}
8<?xml version="1.0" encoding="UTF-8"?>8<?xml version="1.0" encoding="UTF-8"?>
9 <testsuites failures="{{ fails }}" name="" tests="{{ passes }}" skipped="{{ skips }}" errors="{{ errors }}">9 <testsuites failures="{{ fails }}" name="" tests="{{ passes+fails+skips+errors }}" skipped="{{ skips }}" errors="{{ errors }}">
10 {%- for job_id in job_state_map|sort %}10 {%- for job_id, job_state in job_state_map|dictsort if job_state.result.outcome != None and job_state.job.plugin not in ("resource", "attachment") %}
11 {%- set job_state = job_state_map[job_id] %}
12 {%- if job_state.result.outcome %}
13 <testcase classname="{{ job_state.job.id }}" name="{{ job_state.job.id }}" time="{{ job_state.result.execution_duration }}">11 <testcase classname="{{ job_state.job.id }}" name="{{ job_state.job.id }}" time="{{ job_state.result.execution_duration }}">
14 {%- if job_state.result.outcome == 'skip' or job_state.result.outcome == 'not-supported' -%}12 {%- if job_state.result.outcome == 'skip' or job_state.result.outcome == 'not-supported' -%}
15 <skipped />13 <skipped />
@@ -23,6 +21,5 @@
23 </error>21 </error>
24 {%- endif %}22 {%- endif %}
25 </testcase>23 </testcase>
26 {%- endif -%}
27 {%- endfor %}24 {%- endfor %}
28 </testsuites>25 </testsuites>
diff --git a/plainbox/impl/session/state.py b/plainbox/impl/session/state.py
index 9993689..63238e4 100644
--- a/plainbox/impl/session/state.py
+++ b/plainbox/impl/session/state.py
@@ -1297,6 +1297,26 @@ class SessionState:
1297 stats[job_state.result.outcome] += 11297 stats[job_state.result.outcome] += 1
1298 return stats1298 return stats
12991299
1300 def get_test_outcome_stats(self):
1301 """
1302 Process the JobState map to get stats about the job outcomes
1303 excluding attachment and resource jobs.
1304
1305 :returns:
1306 a mapping of "outcome": "total" key/value pairs
1307
1308 .. note::
1309 Only the outcomes seen during this session are reported, not all
1310 possible values (such as crash, not implemented, ...).
1311 """
1312 stats = collections.defaultdict(int)
1313 for job_id, job_state in self.job_state_map.items():
1314 if (not job_state.result.outcome or
1315 job_state.job.plugin in ("resource", "attachment")):
1316 continue
1317 stats[job_state.result.outcome] += 1
1318 return stats
1319
1300 @property1320 @property
1301 def category_map(self):1321 def category_map(self):
1302 """Map from category id to their corresponding translated names."""1322 """Map from category id to their corresponding translated names."""

Subscribers

People subscribed via source and target branches