From f61bb39d13ee6819ff10c4c84955d1423b98aa2c Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Mar 20 2018 13:38:05 +0000 Subject: Fix the flakiness of some tests --- diff --git a/pagure/lib/git_auth.py b/pagure/lib/git_auth.py index 3e75f6c..149f852 100644 --- a/pagure/lib/git_auth.py +++ b/pagure/lib/git_auth.py @@ -419,8 +419,8 @@ class Gitolite2Auth(GitAuthHelper): stream.write('# end of header\n') if groups: - for key, users in groups.iteritems(): - stream.write('@%s = %s\n' % (key, ' '.join(users))) + for key in sorted(groups): + stream.write('@%s = %s\n' % (key, ' '.join(groups[key]))) stream.write('# end of groups\n\n') prev = None @@ -552,8 +552,8 @@ class Gitolite2Auth(GitAuthHelper): stream.write('# end of header\n') if groups: - for key, users in groups.iteritems(): - stream.write('@%s = %s\n' % (key, ' '.join(users))) + for key in sorted(groups): + stream.write('@%s = %s\n' % (key, ' '.join(groups[key]))) stream.write('# end of groups\n\n') prev = None diff --git a/pagure/lib/model.py b/pagure/lib/model.py index ad45a5c..533e450 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -560,12 +560,15 @@ class Project(BASE): milestones = {} if self._milestones: - milestones = json.loads(self._milestones) - for k in milestones: - if not isinstance(milestones[k], dict): - milestones[k] = {'date': milestones[k], 'active': True} + def _convert_to_dict(value): + if isinstance(value, dict): + return value else: - break + return {'date': value, 'active': True} + milestones = dict([ + (k, _convert_to_dict(v)) for k, v in + json.loads(self._milestones).items() + ]) return milestones diff --git a/pagure/lib/tasks.py b/pagure/lib/tasks.py index e94e883..8a329d1 100644 --- a/pagure/lib/tasks.py +++ b/pagure/lib/tasks.py @@ -767,7 +767,7 @@ def update_checksums_file(self, session, folder, filenames): with open(sha_file, 'a') as stream: if new_file: stream.write('# Generated and updated by pagure\n') - for algo in algos: + for algo in sorted(algos): stream.write('%s (%s) = %s\n' % ( algo.upper(), filename, algos[algo].hexdigest())) diff --git a/tests/__init__.py b/tests/__init__.py index caaf2c9..e4a619f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -11,6 +11,7 @@ __requires__ = ['SQLAlchemy >= 0.7'] import pkg_resources +import json import logging import os import re @@ -31,6 +32,7 @@ from datetime import date from datetime import datetime from datetime import timedelta from functools import wraps +from urlparse import urlparse, parse_qs import mock import pygit2 @@ -325,6 +327,10 @@ class SimplePagureTest(unittest.TestCase): del self.app del self._app + def shortDescription(self): + doc = self.__str__() +": "+self._testMethodDoc + return doc or None + def get_csrf(self, url='/new', output=None): """Retrieve a CSRF token from given URL.""" if output is None: @@ -334,6 +340,16 @@ class SimplePagureTest(unittest.TestCase): return output.data.split( 'name="csrf_token" type="hidden" value="')[1].split('">')[0] + def assertURLEqual(self, url_1, url_2): + url_parsed_1 = list(urlparse(url_1)) + url_parsed_1[4] = parse_qs(url_parsed_1[4]) + url_parsed_2 = list(urlparse(url_2)) + url_parsed_2[4] = parse_qs(url_parsed_2[4]) + return self.assertListEqual(url_parsed_1, url_parsed_2) + + def assertJSONEqual(self, json_1, json_2): + return self.assertEqual(json.loads(json_1), json.loads(json_2)) + class Modeltests(SimplePagureTest): """ Model tests. """ diff --git a/tests/test_pagure_flask_api.py b/tests/test_pagure_flask_api.py index a032160..927e497 100644 --- a/tests/test_pagure_flask_api.py +++ b/tests/test_pagure_flask_api.py @@ -46,7 +46,7 @@ class PagureFlaskApitests(tests.SimplePagureTest): output = self.app.get('/api/0/foo/tags/') self.assertEqual(output.status_code, 404) data = json.loads(output.data) - self.assertEqual(data.keys(), ['output', 'error']) + self.assertEqual(set(data.keys()), set(['output', 'error'])) self.assertEqual(data['output'], 'notok') self.assertEqual(data['error'], 'Project not found') diff --git a/tests/test_pagure_flask_api_issue_custom_fields.py b/tests/test_pagure_flask_api_issue_custom_fields.py index 29523dd..8b13fea 100644 --- a/tests/test_pagure_flask_api_issue_custom_fields.py +++ b/tests/test_pagure_flask_api_issue_custom_fields.py @@ -111,13 +111,14 @@ class PagureFlaskApiCustomFieldIssuetests(tests.Modeltests): '/api/0/test/issue/1/custom', headers=headers, data=payload) self.assertEqual(output.status_code, 200) data = json.loads(output.data) + data["messages"].sort() self.assertDictEqual( data, { - "messages": [ + "messages": sorted([ {"bugzilla": "No changes"}, {"upstream": "Custom field upstream adjusted to True"}, - ] + ]) } ) @@ -134,16 +135,17 @@ class PagureFlaskApiCustomFieldIssuetests(tests.Modeltests): data=payload) self.assertEqual(output.status_code, 200) data = json.loads(output.data) + data["messages"].sort() self.assertDictEqual( data, { - "messages": [ + "messages": sorted([ {"bugzilla": "Custom field bugzilla adjusted to " "https://bugzilla.redhat.com/1234"}, {"reviewstatus": "Custom field reviewstatus adjusted to ack"}, {"upstream": "Custom field upstream adjusted to False (was: True)"}, - ] + ]) } ) @@ -159,15 +161,16 @@ class PagureFlaskApiCustomFieldIssuetests(tests.Modeltests): data=payload) self.assertEqual(output.status_code, 200) data = json.loads(output.data) + data["messages"].sort() self.assertDictEqual( data, { - "messages": [ + "messages": sorted([ {"bugzilla": "Custom field bugzilla reset " "(from https://bugzilla.redhat.com/1234)"}, {"reviewstatus": "Custom field reviewstatus reset (from ack)"}, {"upstream": "Custom field upstream reset (from False)"}, - ] + ]) } ) diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index f8ddac1..a950152 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -1057,8 +1057,6 @@ class PagureFlaskApiProjecttests(tests.Modeltests): "username": None }, "pagination": { - "first": "http://localhost/api/0/projects?per_page=20&page=1", - "last": "http://localhost/api/0/projects?per_page=20&page=1", "next": None, "page": 1, "pages": 1, @@ -1174,6 +1172,15 @@ class PagureFlaskApiProjecttests(tests.Modeltests): ], "total_projects": 3 } + # Test URLs + self.assertURLEqual( + data["pagination"].pop("first"), + "http://localhost/api/0/projects?per_page=20&page=1", + ) + self.assertURLEqual( + data["pagination"].pop("last"), + "http://localhost/api/0/projects?per_page=20&page=1", + ) self.assertDictEqual(data, expected_data) def test_api_projects_pagination_per_page(self): @@ -1199,13 +1206,10 @@ class PagureFlaskApiProjecttests(tests.Modeltests): "username": None }, "pagination": { - "first": "http://localhost/api/0/projects?per_page=2&page=1", - "last": "http://localhost/api/0/projects?per_page=2&page=2", "next": None, "page": 2, "pages": 2, "per_page": 2, - "prev": "http://localhost/api/0/projects?per_page=2&page=1", }, "projects": [ { @@ -1247,6 +1251,18 @@ class PagureFlaskApiProjecttests(tests.Modeltests): ], "total_projects": 3 } + self.assertURLEqual( + data["pagination"].pop("first"), + "http://localhost/api/0/projects?per_page=2&page=1", + ) + self.assertURLEqual( + data["pagination"].pop("prev"), + "http://localhost/api/0/projects?per_page=2&page=1", + ) + self.assertURLEqual( + data["pagination"].pop("last"), + "http://localhost/api/0/projects?per_page=2&page=2", + ) self.assertDictEqual(data, expected_data) def test_api_projects_pagination_invalid_page(self): @@ -1303,6 +1319,18 @@ class PagureFlaskApiProjecttests(tests.Modeltests): output = self.app.get('/api/0/projects?page=99999') self.assertEqual(output.status_code, 200) data = json.loads(output.data) + self.assertURLEqual( + data["pagination"].pop("first"), + "http://localhost/api/0/projects?per_page=20&page=1", + ) + self.assertURLEqual( + data["pagination"].pop("last"), + "http://localhost/api/0/projects?per_page=20&page=1", + ) + self.assertURLEqual( + data["pagination"].pop("prev"), + "http://localhost/api/0/projects?per_page=20&page=99998", + ) self.assertEqual( data, { @@ -1318,13 +1346,10 @@ class PagureFlaskApiProjecttests(tests.Modeltests): "username": None }, "pagination": { - "first": "http://localhost/api/0/projects?per_page=20&page=1", - "last": "http://localhost/api/0/projects?per_page=20&page=1", "next": None, "page": 99999, "pages": 1, "per_page": 20, - "prev": "http://localhost/api/0/projects?per_page=20&page=99998" }, "projects": [], "total_projects": 3 diff --git a/tests/test_pagure_flask_dump_load_ticket.py b/tests/test_pagure_flask_dump_load_ticket.py index 83de075..7023ee0 100644 --- a/tests/test_pagure_flask_dump_load_ticket.py +++ b/tests/test_pagure_flask_dump_load_ticket.py @@ -207,7 +207,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests): # Check after re-loading self.assertEqual(len(issue.comments), 3) self.assertEqual(len(issue.tags), 2) - self.assertEqual(issue.tags_text, ['future', 'feature']) + self.assertEqual(sorted(issue.tags_text), sorted(['future', 'feature'])) self.assertEqual(issue.assignee.username, 'pingou') self.assertEqual(issue.children, []) self.assertEqual(issue.parents, []) diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py index 142ba7c..e588e8b 100644 --- a/tests/test_pagure_flask_ui_fork.py +++ b/tests/test_pagure_flask_ui_fork.py @@ -21,6 +21,7 @@ import os import pygit2 from mock import patch, MagicMock +from bs4 import BeautifulSoup sys.path.insert(0, os.path.join(os.path.dirname( os.path.abspath(__file__)), '..')) @@ -1473,23 +1474,33 @@ index 0000000..2a552bb '/test/pull-request/1/update', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) - self.assertIn( - 'PR#1: PR from the feature branch - test\n - ' - 'Pagure', output.data) - self.assertIn( - '

PR#1\n' - ' PR from the feature branch\n', output.data) - self.assertIn( - '\n ' - 'Pull-request **un**tagged with: black', - output.data) - self.assertIn( - '\n ' - 'Pull-request tagged with: blue, yellow', - output.data) - self.assertIn( - 'title="comma separated list of tags"\n ' - 'value="blue,yellow" />', output.data) + soup = BeautifulSoup(output.data, "html.parser") + self.assertEqual( + soup.find("title").string, + 'PR#1: PR from the feature branch - test\n - Pagure' + ) + h3 = soup.find("h3") + self.assertIsNotNone(h3) + self.assertListEqual( + h3.find("span")["class"], ["label", "label-default"]) + self.assertEqual(h3.find("span").string, "PR#1") + self.assertEqual( + list(h3.stripped_strings)[1], 'PR from the feature branch') + alerts = [ + list(a.stripped_strings)[2] for a in + soup.find_all("div", class_="alert") + if list(a.stripped_strings) + ] + self.assertIn('Pull-request **un**tagged with: black', alerts) + self.assertIn('Pull-request tagged with: blue, yellow', alerts) + input_tag = soup.find("input", id="tag") + self.assertEqual( + input_tag["title"], "comma separated list of tags") + # The order is not guaranteed, compare sets. + self.assertEqual( + set(input_tag["value"].split(",")), + set(["blue", "yellow"]) + ) user.username = 'pingou' with tests.user_set(self.app.application, user): diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py index 1e79b05..b0661ba 100644 --- a/tests/test_pagure_flask_ui_issues.py +++ b/tests/test_pagure_flask_ui_issues.py @@ -27,6 +27,7 @@ import re from datetime import datetime, timedelta import pygit2 +from bs4 import BeautifulSoup from mock import patch, MagicMock sys.path.insert(0, os.path.join(os.path.dirname( @@ -990,6 +991,15 @@ class PagureFlaskIssuestests(tests.Modeltests): issues[2].assignee_id = 1 self.session.commit() + # This detects the assignee but keying on if a certain link is present + def _check_assignee_link(html, expected_links): + soup = BeautifulSoup(html, "html.parser") + for index, expected_link in enumerate(expected_links): + link = soup.find_all("tr")[index + 1].find( + "a", title="Filter issues by assignee") + self.assertIsNotNone(link, "Link %s was not found" % expected_link) + self.assertURLEqual(link["href"], expected_link) + # Sort by assignee descending output = self.app.get('/test/issues?order_key=assignee&order=desc') tr_elements = re.findall(r'(.*?)', output.data, re.M | re.S) @@ -998,16 +1008,11 @@ class PagureFlaskIssuestests(tests.Modeltests): '"arrow-thick-bottom">') # First table row is the header self.assertIn(arrowed_th, tr_elements[0]) - # This detects the assignee but keying on if a certain link is present - one = ('') - two = ('') - three = ('') - self.assertIn(one, tr_elements[1]) - self.assertIn(two, tr_elements[2]) - self.assertIn(three, tr_elements[3]) + _check_assignee_link(output.data, [ + '/test/issues?status=Open&assignee=pingou', + '/test/issues?status=Open&assignee=pingou', + '/test/issues?status=Open&assignee=foo', + ]) # Sort by assignee ascending output = self.app.get('/test/issues?order_key=assignee&order=asc') @@ -1017,16 +1022,11 @@ class PagureFlaskIssuestests(tests.Modeltests): '"arrow-thick-top">') # First table row is the header self.assertIn(arrowed_th, tr_elements[0]) - # This detects the assignee but keying on if a certain link is present - one = ('') - two = ('') - three = ('') - self.assertIn(one, tr_elements[1]) - self.assertIn(two, tr_elements[2]) - self.assertIn(three, tr_elements[3]) + _check_assignee_link(output.data, [ + '/test/issues?status=Open&assignee=foo', + '/test/issues?status=Open&assignee=pingou', + '/test/issues?status=Open&assignee=pingou', + ]) # New issue button is shown user = tests.FakeUser() diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index b30e35f..0cf7737 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -1293,7 +1293,7 @@ class PagureFlaskRepotests(tests.Modeltests): output.data) repo = pagure.lib.get_authorized_project(self.session, 'test') - gen_acl.assert_called_once() + self.assertEqual(gen_acl.call_count, 1) args = gen_acl.call_args self.assertEqual(args[0], tuple()) self.assertEqual(args[1].keys(), ['project']) diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py index 5977360..e4675fa 100644 --- a/tests/test_pagure_lib.py +++ b/tests/test_pagure_lib.py @@ -1005,7 +1005,7 @@ class PagureLibtests(tests.Modeltests): self.assertEqual(len(args), 5) # Get the arguments of the last call and get the second of these # arguments (the first one changing for each test run) - self.assertEqual( + self.assertJSONEqual( args[-1:][0][0][1], '{"added_tags_color": ["DeepSkyBlue"], "added_tags": ["tag1"]}' ) @@ -2951,7 +2951,7 @@ class PagureLibtests(tests.Modeltests): self.assertEqual( sorted([t.tag for t in repo.tags_colored]), ['tag', 'tag2', 'tag3']) - self.assertEqual(issue.tags_text, ['tag2', 'tag3']) + self.assertEqual(sorted(issue.tags_text), ['tag2', 'tag3']) @patch('pagure.lib.git.update_git') diff --git a/tests/test_pagure_lib_encoding_utils.py b/tests/test_pagure_lib_encoding_utils.py index 5c3d07d..631a57f 100644 --- a/tests/test_pagure_lib_encoding_utils.py +++ b/tests/test_pagure_lib_encoding_utils.py @@ -54,16 +54,26 @@ class TestGuessEncodings(unittest.TestCase): result = encoding_utils.guess_encodings(data) chardet_result = chardet.detect(data) if chardet.__version__[0] == '3': + # The first three have different confidence values + self.assertListEqual( + [encoding.encoding for encoding in result][:3], + ['utf-8', 'ISO-8859-9', 'ISO-8859-1'] + ) + # This is the one with the least confidence + self.assertEqual(result[-1].encoding, 'windows-1255') + # The values in the middle of the list all have the same confidence + # value and can't be sorted reliably: use sets. self.assertEqual( - [encoding.encoding for encoding in result], - ['utf-8', 'ISO-8859-9', 'ISO-8859-1', 'MacCyrillic', - 'IBM866', 'TIS-620', 'EUC-JP', 'EUC-KR', 'GB2312', 'KOI8-R', - 'Big5', 'IBM855', 'ISO-8859-7', 'SHIFT_JIS', 'windows-1253', - 'CP949', 'EUC-TW', 'ISO-8859-5', 'windows-1251', - 'windows-1255']) + set([encoding.encoding for encoding in result]), + set(['utf-8', 'ISO-8859-9', 'ISO-8859-1', 'MacCyrillic', + 'IBM866', 'TIS-620', 'EUC-JP', 'EUC-KR', 'GB2312', + 'KOI8-R', 'Big5', 'IBM855', 'ISO-8859-7', 'SHIFT_JIS', + 'windows-1253', 'CP949', 'EUC-TW', 'ISO-8859-5', + 'windows-1251', 'windows-1255']) + ) self.assertEqual(chardet_result['encoding'], 'ISO-8859-9') else: - self.assertEqual( + self.assertListEqual( [encoding.encoding for encoding in result], ['utf-8', 'ISO-8859-2', 'windows-1252']) self.assertEqual(chardet_result['encoding'], 'ISO-8859-2') diff --git a/tests/test_pagure_lib_git.py b/tests/test_pagure_lib_git.py index f4764a7..a041b4d 100644 --- a/tests/test_pagure_lib_git.py +++ b/tests/test_pagure_lib_git.py @@ -2315,7 +2315,7 @@ index 0000000..60f7480 self.assertEqual(repo.issues[1].depending_text, []) self.assertEqual(repo.issues[1].blocking_text, [1]) self.assertEqual(repo.issues[1].milestone, 'Future') - self.assertEqual( + self.assertDictEqual( repo.milestones, { u'Future': {'active': True, 'date': None}, diff --git a/tests/test_pagure_lib_gitolite_config.py b/tests/test_pagure_lib_gitolite_config.py index 5764b78..c007d01 100644 --- a/tests/test_pagure_lib_gitolite_config.py +++ b/tests/test_pagure_lib_gitolite_config.py @@ -494,8 +494,8 @@ repo requests/test @group2 = threebean puiterwijk kevin pingou # end of header -@grp2 = foo @grp = pingou +@grp2 = foo # end of groups repo test @@ -546,8 +546,8 @@ repo requests/test @group2 = threebean puiterwijk kevin pingou # end of header -@grp2 = foo @grp = pingou +@grp2 = foo # end of groups %s @@ -612,8 +612,8 @@ repo requests/test @group2 = threebean puiterwijk kevin pingou # end of header -@grp2 = foo @grp = foo pingou +@grp2 = foo # end of groups repo test2 @@ -757,8 +757,8 @@ repo requests/test with open(self.outputconf) as stream: data = stream.read().decode('utf-8') - exp = u"""@grp2 = foo -@grp = pingou + exp = u"""@grp = pingou +@grp2 = foo # end of groups repo test @@ -825,8 +825,8 @@ repo requests/somenamespace/test3 with open(self.outputconf) as stream: data = stream.read().decode('utf-8') - exp = u"""@grp2 = foo -@grp = pingou + exp = u"""@grp = pingou +@grp2 = foo # end of groups %s @@ -846,8 +846,8 @@ repo requests/somenamespace/test3 with open(self.outputconf) as stream: data = stream.read().decode('utf-8') - exp = u"""@grp2 = foo -@grp = pingou + exp = u"""@grp = pingou +@grp2 = foo # end of groups repo test2 @@ -903,8 +903,8 @@ repo requests/somenamespace/test3 with open(self.outputconf) as stream: data = stream.read().decode('utf-8') - exp = u"""@grp2 = foo -@grp = pingou + exp = u"""@grp = pingou +@grp2 = foo # end of groups %s diff --git a/tests_requirements.txt b/tests_requirements.txt index f02d009..124c3e6 100644 --- a/tests_requirements.txt +++ b/tests_requirements.txt @@ -3,6 +3,11 @@ mock nose>=0.10.4 nosexcover flake8 +beautifulsoup4 +cryptography +bcrypt +python-fedora +trollius # Seems that mock doesn't list this one funcsigs