Skip to content

Commit be65314

Browse files
authored
[IMPROVEMENT] Compare tests with master branch for PRs (#869)
1 parent 5b4c69c commit be65314

File tree

4 files changed

+58
-30
lines changed

4 files changed

+58
-30
lines changed

mod_ci/controllers.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from mod_auth.models import Role
3434
from mod_ci.forms import AddUsersToBlacklist, DeleteUserForm
3535
from mod_ci.models import (BlockedUsers, GcpInstance, MaintenanceMode,
36-
PrCommentInfo)
36+
PrCommentInfo, Status)
3737
from mod_customized.models import CustomizedTest
3838
from mod_home.models import CCExtractorVersion, GeneralData
3939
from mod_regression.models import (Category, RegressionTest,
@@ -48,15 +48,6 @@
4848
mod_ci = Blueprint('ci', __name__)
4949

5050

51-
class Status:
52-
"""Define different states for the tests."""
53-
54-
PENDING = "pending"
55-
SUCCESS = "success"
56-
ERROR = "error"
57-
FAILURE = "failure"
58-
59-
6051
class Workflow_builds(DeclEnum):
6152
"""Define GitHub Action workflow build names."""
6253

@@ -1304,7 +1295,7 @@ def progress_type_request(log, test, test_id, request) -> bool:
13041295
state = Status.SUCCESS
13051296
message = 'Tests completed'
13061297
if test.test_type == TestType.pull_request:
1307-
comment_pr(test.id, state, test.pr_nr, test.platform.name)
1298+
state = comment_pr(test.id, test.pr_nr, test.platform.name)
13081299
update_build_badge(state, test)
13091300

13101301
else:
@@ -1604,23 +1595,32 @@ def get_query_regression_testid_passed(test_id: int) -> Query:
16041595

16051596
def get_info_for_pr_comment(test_id: int) -> PrCommentInfo:
16061597
"""Return info about the given test id for use in a PR comment."""
1607-
regression_testid_passed = get_query_regression_testid_passed(test_id)
1598+
last_test_master = g.db.query(Test).filter(Test.branch == "master", Test.test_type == TestType.commit).join(
1599+
TestProgress, Test.id == TestProgress.test_id).filter(
1600+
TestProgress.status == TestStatus.completed).order_by(TestProgress.id.desc()).first()
1601+
regression_test_passed = get_query_regression_testid_passed(test_id)
16081602

16091603
passed = g.db.query(label('category_id', Category.id), label(
16101604
'success', count(regressionTestLinkTable.c.regression_id))).filter(
1611-
regressionTestLinkTable.c.regression_id.in_(regression_testid_passed),
1605+
regressionTestLinkTable.c.regression_id.in_(regression_test_passed),
16121606
Category.id == regressionTestLinkTable.c.category_id).group_by(
16131607
regressionTestLinkTable.c.category_id).subquery()
16141608
tot = g.db.query(label('category', Category.name), label('total', count(regressionTestLinkTable.c.regression_id)),
16151609
label('success', passed.c.success)).outerjoin(
16161610
passed, passed.c.category_id == Category.id).filter(
16171611
Category.id == regressionTestLinkTable.c.category_id).group_by(
16181612
regressionTestLinkTable.c.category_id).all()
1619-
regression_testid_failed = RegressionTest.query.filter(RegressionTest.id.notin_(regression_testid_passed)).all()
1620-
return PrCommentInfo(tot, regression_testid_failed)
1613+
regression_test_failed = RegressionTest.query.filter(RegressionTest.id.notin_(regression_test_passed)).all()
1614+
1615+
last_test_master_id = last_test_master.id if last_test_master else 0
1616+
extra_failed_tests = [test for test in regression_test_failed if test.last_passed_on == last_test_master]
1617+
fixed_tests = RegressionTest.query.filter(RegressionTest.id.in_(regression_test_passed),
1618+
RegressionTest.last_passed_on != last_test_master_id).all()
1619+
common_failed_tests = [test for test in regression_test_failed if test.last_passed_on != last_test_master]
1620+
return PrCommentInfo(tot, extra_failed_tests, fixed_tests, common_failed_tests, last_test_master)
16211621

16221622

1623-
def comment_pr(test_id, state, pr_nr, platform) -> None:
1623+
def comment_pr(test_id, pr_nr, platform) -> str:
16241624
"""
16251625
Upload the test report to the GitHub PR as comment.
16261626
@@ -1637,8 +1637,7 @@ def comment_pr(test_id, state, pr_nr, platform) -> None:
16371637

16381638
comment_info = get_info_for_pr_comment(test_id)
16391639
template = app.jinja_env.get_or_select_template('ci/pr_comment.txt')
1640-
message = template.render(tests=comment_info.category_stats, failed_tests=comment_info.failed_tests,
1641-
test_id=test_id, state=state, platform=platform)
1640+
message = template.render(comment_info=comment_info, test_id=test_id, platform=platform)
16421641
log.debug(f"GitHub PR Comment Message Created for Test_id: {test_id}")
16431642
try:
16441643
gh = Github(g.github['bot_token'])
@@ -1655,6 +1654,7 @@ def comment_pr(test_id, state, pr_nr, platform) -> None:
16551654
log.debug(f"GitHub PR Comment ID {comment.id} Uploaded for Test_id: {test_id}")
16561655
except Exception as e:
16571656
log.error(f"GitHub PR Comment Failed for Test_id: {test_id} with Exception {e}")
1657+
return Status.SUCCESS if len(comment_info.extra_failed_tests) == 0 else Status.FAILURE
16581658

16591659

16601660
@mod_ci.route('/show_maintenance')

mod_ci/models.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
Text)
1717
from sqlalchemy.orm import relationship
1818

19-
import mod_test.models
2019
from database import Base
2120
from mod_regression.models import RegressionTest
2221
from mod_test.models import Test, TestPlatform
@@ -124,11 +123,22 @@ class CategoryTestInfo:
124123
success: Optional[int]
125124

126125

126+
class Status:
127+
"""Define different states for the tests."""
128+
129+
PENDING = "pending"
130+
SUCCESS = "success"
131+
ERROR = "error"
132+
FAILURE = "failure"
133+
134+
127135
@dataclass
128136
class PrCommentInfo:
129137
"""Contains info about a test run that is useful for displaying a PR comment."""
130138

131139
# info about successes and failures for each category
132140
category_stats: List[CategoryTestInfo]
133-
# list of regression tests that failed
134-
failed_tests: List[RegressionTest]
141+
extra_failed_tests: List[RegressionTest]
142+
fixed_tests: List[RegressionTest]
143+
common_failed_tests: List[RegressionTest]
144+
last_test_master: Test

templates/ci/pr_comment.txt

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
<b>CCExtractor CI platform</b> finished running the test files on <b>{{platform}}</b>. Below is a summary of the test results:
1+
<b>CCExtractor CI platform</b> finished running the test files on <b>{{platform}}</b>. Below is a summary of the test results{% if comment_info.last_test_master %}, when compared to <a href="{{ url_for('test.by_id', test_id=comment_info.last_test_master.id, _external=True) }}">test for commit {{ comment_info.last_test_master.commit[:7] }}...</a>{% endif %}:
22
<table>
33
<thead>
44
<td> Report Name </td>
55
<td> Tests Passed </td>
66
</thead>
7-
{% for test in tests%}
7+
{% for test in comment_info.category_stats %}
88
<tr>
99
<td> {{test.category}} </td>
1010
{% if test.success==None %}
@@ -17,17 +17,33 @@
1717
</tr>
1818
{% endfor %}
1919
</table>
20-
{% if state == "failure" %}
20+
{% if comment_info.extra_failed_tests | length %}
2121
It seems that not all tests were passed completely. This is an indication that the output of some files is not as expected (but might be according to you).
2222

2323
Your PR breaks these cases:
2424
<ul>
25-
{% for test in failed_tests %}
26-
<li> ccextractor {{ test.command }} <a href="{{ url_for('sample.sample_by_id', sample_id=test.sample.id, _external=True) }}">{{ test.sample.sha[:10] }}...</a>, Last passed: {% if test.last_passed_on %}<a href="{{ url_for('test.by_id', test_id=test.last_passed_on, _external=True) }}">Test {{ test.last_passed_on }}</a>{% else %}<span>Never</span>{% endif %}</li>
25+
{% for test in comment_info.extra_failed_tests %}
26+
<li> ccextractor {{ test.command }} <a href="{{ url_for('sample.sample_by_id', sample_id=test.sample.id, _external=True) }}">{{ test.sample.sha[:10] }}...</a></li>
2727
{% endfor %}
2828
</ul>
2929
{% else %}
30-
All tests were passed completely.
30+
All tests passing on the master branch were passed completely.
31+
{% endif %}
32+
{% if comment_info.common_failed_tests | length %}
33+
NOTE: The following tests have been failing on the master branch as well as the PR:
34+
<ul>
35+
{% for test in comment_info.common_failed_tests %}
36+
<li> ccextractor {{ test.command }} <a href="{{ url_for('sample.sample_by_id', sample_id=test.sample.id, _external=True) }}">{{ test.sample.sha[:10] }}...</a>, Last passed: {% if test.last_passed_on %}<a href="{{ url_for('test.by_id', test_id=test.last_passed_on, _external=True) }}">Test {{ test.last_passed_on }}</a>{% else %}<span>Never</span>{% endif %}</li>
37+
{% endfor %}
38+
</ul>
39+
{% endif %}
40+
{% if comment_info.fixed_tests | length %}
41+
Congratulations: Merging this PR would fix the following tests:
42+
<ul>
43+
{% for test in comment_info.fixed_tests %}
44+
<li> ccextractor {{ test.command }} <a href="{{ url_for('sample.sample_by_id', sample_id=test.sample.id, _external=True) }}">{{ test.sample.sha[:10] }}...</a>, Last passed: {% if test.last_passed_on %}<a href="{{ url_for('test.by_id', test_id=test.last_passed_on, _external=True) }}">Test {{ test.last_passed_on }}</a>{% else %}<span>Never</span>{% endif %}</li>
45+
{% endfor %}
46+
</ul>
3147
{% endif %}
3248
<br>
3349
Check the <a href="{{ url_for('test.by_id', test_id=test_id, _external=True) }}">result</a> page for more info.

tests/test_ci/test_controllers.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ def test_comment_info_handles_variant_files_correctly(self):
8585
test: Test = Test.query.filter(Test.id == TEST_RUN_ID).first()
8686
comment_info = get_info_for_pr_comment(test.id)
8787
# we got a valid variant, so should still pass
88-
self.assertEqual(comment_info.failed_tests, [])
88+
self.assertEqual(comment_info.common_failed_tests, [])
89+
self.assertEqual(comment_info.extra_failed_tests, [])
90+
self.assertEqual(comment_info.fixed_tests, [])
8991
for stats in comment_info.category_stats:
9092
# make sure the stats for the category confirm that everything passed too
9193
self.assertEqual(stats.success, stats.total)
@@ -377,7 +379,7 @@ def test_comments_successfully_in_passed_pr_test(self, mock_github):
377379

378380
# Delete old bot comments and create a new comment
379381
pull_request.get_issue_comments.return_value = [comment1, comment2]
380-
comment_pr(1, Status.SUCCESS, 1, 'linux')
382+
comment_pr(1, 1, 'linux')
381383
mock_github.assert_called_with(g.github['bot_token'])
382384
mock_github(g.github['bot_token']).get_repo.assert_called_with(
383385
f"{g.github['repository_owner']}/{g.github['repository']}")
@@ -405,7 +407,7 @@ def test_comments_successfuly_in_failed_pr_test(self, mock_github):
405407
"test files on <b>linux</b>. Below is a summary of the test results")
406408
pull_request.get_issue_comments.return_value = [MagicMock(IssueComment)]
407409
# Comment on test that fails some/all regression tests
408-
comment_pr(2, Status.FAILURE, 1, 'linux')
410+
comment_pr(2, 1, 'linux')
409411
pull_request.get_issue_comments.assert_called_with()
410412
args, kwargs = pull_request.create_issue_comment.call_args
411413
message = kwargs['body']

0 commit comments

Comments
 (0)