From 4c582a4ddd6a14533795d4cd15039288048f170b Mon Sep 17 00:00:00 2001 From: sidpremkumar Date: Aug 13 2019 13:18:02 +0000 Subject: [PATCH 1/2] Adding min coverage to tox --- diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..d8a8a30 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,10 @@ +[run] +branch=True +source=sync2jira/ +omit=sync2jira/mailer.py + +[report] +fail_under=60 + +[html] +directory=./coverage_report \ No newline at end of file diff --git a/tox.ini b/tox.ini index 7dbb338..5f6c94f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py37,flake8 +envlist = clean, py37,flake8 [testenv] setenv = @@ -10,11 +10,12 @@ basepython = deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt - pytest nose + pytest + pytest-cov sitepackages = False commands = - pytest {posargs} --junitxml=xunit-tests.xml + pytest {posargs} --cov --cov-append --cov-report html:htmlcov-py36 --junitxml=xunit-tests.xml [testenv:flake8] basepython = python3 @@ -27,3 +28,9 @@ max-line-length=140 [pep8] max-line-length=140 + +[testenv:clean] +basepython = python3 +deps = coverage +skip_install = False +commands = coverage erase \ No newline at end of file From 6aad8c2fe18fec5ce5254be39d3ba8eb652c61d5 Mon Sep 17 00:00:00 2001 From: sidpremkumar Date: Aug 13 2019 13:55:11 +0000 Subject: [PATCH 2/2] Add 75% min coverage and added tests accordingly --- diff --git a/.coveragerc b/.coveragerc index d8a8a30..fdbd371 100644 --- a/.coveragerc +++ b/.coveragerc @@ -4,7 +4,7 @@ source=sync2jira/ omit=sync2jira/mailer.py [report] -fail_under=60 +fail_under=75 [html] directory=./coverage_report \ No newline at end of file diff --git a/.gitignore b/.gitignore index 53c38b5..08d37fb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ venv/* venv3/* xunit-tests.xml docs/build/* +htmlcov-py36/* diff --git a/tests/test_downstream.py b/tests/test_downstream.py index 70c742f..b6dee26 100644 --- a/tests/test_downstream.py +++ b/tests/test_downstream.py @@ -5,7 +5,7 @@ try: from unittest.mock import MagicMock # noqa: F401 except ImportError: from mock import MagicMock # noqa: F401 -import os +from datetime import datetime import sync2jira.downstream as d from sync2jira.intermediary import Issue @@ -1197,6 +1197,59 @@ class TestDownstream(unittest.TestCase): user={'name': 'mock_name', 'email': 'mock_email'}) mock_mailer().send.asset_called_with('test') + @mock.patch(PATH + 'jinja2') + @mock.patch(PATH + 'send_mail') + @mock.patch('jira.client.JIRA') + def test_alert_user_multiple_users(self, + mock_client, + mock_mailer, + mock_jinja, ): + """ + This tests 'alert_user_of_duplicate_issues' function + where searching returns multiple users + """ + # Set up return values + mock_downstream_issue = MagicMock() + mock_downstream_issue.key = 'mock_key' + bad_downstream_issue = MagicMock() + bad_downstream_issue.key = 'mock_key' + bad_downstream_issue.fields.status.name = 'To Do' + mock_results_of_query = [mock_downstream_issue, bad_downstream_issue] + mock_search_user_result1 = MagicMock() + mock_search_user_result1.displayName = 'bad_name' + mock_search_user_result1.emailAddress = 'bad_email' + mock_search_user_result1.key = 'bad_owner' + mock_search_user_result2 = MagicMock() + mock_search_user_result2.displayName = 'mock_name' + mock_search_user_result2.emailAddress = 'mock_email' + mock_search_user_result2.key = 'mock_owner' + mock_client.search_users.return_value = [mock_search_user_result1, mock_search_user_result2] + mock_template = MagicMock(name='template') + mock_template.render.return_value = 'mock_html_text' + mock_template_env = MagicMock(name='templateEnv') + mock_template_env.get_template.return_value = mock_template + mock_jinja.Environment.return_value = mock_template_env + + # Call the function + d.alert_user_of_duplicate_issues( + issue=self.mock_issue, + final_result=[mock_downstream_issue], + results_of_query=mock_results_of_query, + config=self.mock_config, + client=mock_client + ) + + # Assert everything was called correctly + mock_client.search_users.assert_any_call('mock_owner') + mock_client.search_users.assert_any_call('mock_admin') + mock_template.render.assert_called_with( + admins=[{'name': 'mock_name', 'email': 'mock_email'}], + duplicate_issues=[{'url': 'mock_server/browse/mock_key', 'title': 'mock_key'}], + issue=self.mock_issue, + selected_issue={'url': 'mock_server/browse/mock_key', 'title': 'mock_key'}, + user={'name': 'mock_name', 'email': 'mock_email'}) + mock_mailer().send.asset_called_with('test') + def test_find_username(self): """ Tests 'find_username' function @@ -1210,7 +1263,6 @@ class TestDownstream(unittest.TestCase): # Assert everything was called correctly self.assertEqual(response, 'mock_user') - @mock.patch('jira.client.JIRA') def test_check_comments_for_duplicates(self, mock_client): @@ -1235,3 +1287,105 @@ class TestDownstream(unittest.TestCase): self.assertEqual(response, 'Successful Call!') mock_client.comments.assert_called_with(self.mock_downstream) mock_client.issue.assert_called_with('TEST-1234') + + @mock.patch(PATH + '_comment_format') + @mock.patch(PATH + '_comment_format_legacy') + def test_find_comment_in_jira_legacy(self, + mock_comment_format_legacy, + mock_comment_format): + """ + This function tests '_find_comment_in_jira' where we find a legacy comment + """ + # Set up return values + mock_comment_format.return_value = 'mock_comment_body' + mock_comment_format_legacy.return_value = 'mock_legacy_comment_body' + mock_jira_comment = MagicMock() + mock_jira_comment.raw = {'body': 'mock_legacy_comment_body'} + mock_comment = { + 'id': '12345', + 'date_created': datetime(2019, 8, 8) + } + + # Call the function + response = d._find_comment_in_jira(mock_comment, [mock_jira_comment]) + + # Assert everything was called correctly + mock_comment_format_legacy.assert_called_with(mock_comment) + mock_comment_format.assert_called_with(mock_comment) + self.assertEqual(response, mock_jira_comment) + + @mock.patch(PATH + '_comment_format') + @mock.patch(PATH + '_comment_format_legacy') + def test_find_comment_in_jira_id(self, + mock_comment_format_legacy, + mock_comment_format): + """ + This function tests '_find_comment_in_jira' where we match an ID + """ + # Set up return values + mock_comment_format.return_value = 'mock_comment_body' + mock_comment_format_legacy.return_value = 'mock_legacy_comment_body' + mock_jira_comment = MagicMock() + mock_jira_comment.raw = {'body': '12345'} + mock_comment = { + 'id': '12345', + 'date_created': datetime(2019, 8, 8) + } + + # Call the function + response = d._find_comment_in_jira(mock_comment, [mock_jira_comment]) + + # Assert everything was called correctly + mock_comment_format_legacy.assert_called_with(mock_comment) + mock_comment_format.assert_called_with(mock_comment) + self.assertEqual(response, mock_jira_comment) + + @mock.patch(PATH + '_comment_format') + @mock.patch(PATH + '_comment_format_legacy') + def test_find_comment_in_jira_old_comment(self, + mock_comment_format_legacy, + mock_comment_format): + """ + This function tests '_find_comment_in_jira' where we find a old comment + """ + # Set up return values + mock_comment_format.return_value = 'mock_comment_body' + mock_comment_format_legacy.return_value = 'mock_legacy_comment_body' + mock_jira_comment = MagicMock() + mock_jira_comment.raw = {'body': 'old_comment'} + mock_comment = { + 'id': '12345', + 'date_created': datetime(2019, 1, 1) + } + + # Call the function + response = d._find_comment_in_jira(mock_comment, [mock_jira_comment]) + + # Assert everything was called correctly + mock_comment_format_legacy.assert_called_with(mock_comment) + mock_comment_format.assert_called_with(mock_comment) + self.assertEqual(response, mock_jira_comment) + + @mock.patch(PATH + '_comment_format') + @mock.patch(PATH + '_comment_format_legacy') + def test_find_comment_in_jira_none(self, + mock_comment_format_legacy, + mock_comment_format): + """ + This function tests '_find_comment_in_jira' where we return None + """ + # Set up return values + mock_comment_format.return_value = 'mock_comment_body' + mock_comment_format_legacy.return_value = 'mock_legacy_comment_body' + mock_comment = { + 'id': '12345', + 'date_created': datetime(2019, 1, 1) + } + + # Call the function + response = d._find_comment_in_jira(mock_comment, []) + + # Assert everything was called correctly + mock_comment_format_legacy.assert_called_with(mock_comment) + mock_comment_format.assert_called_with(mock_comment) + self.assertEqual(response, None) \ No newline at end of file diff --git a/tests/test_intermediary.py b/tests/test_intermediary.py index dd39dc2..420769e 100644 --- a/tests/test_intermediary.py +++ b/tests/test_intermediary.py @@ -79,9 +79,9 @@ class TestIntermediary(unittest.TestCase): self.assertEqual(response.id, 'mock_date') self.assertEqual(response.downstream, 'mock_downstream') - def test_from_github(self): + def test_from_github_open(self): """ - This tests the 'from_github' function under the Issue class + This tests the 'from_github' function under the Issue class where the state is open """ # Set up return values mock_issue = { @@ -128,3 +128,53 @@ class TestIntermediary(unittest.TestCase): self.assertEqual(response.status, 'Open') self.assertEqual(response.id, '1234') self.assertEqual(response.downstream, 'mock_downstream') + + def test_from_github_closed(self): + """ + This tests the 'from_github' function under the Issue class where the state is closed + """ + # Set up return values + mock_issue = { + 'comments': [{ + 'author': 'mock_author', + 'name': 'mock_name', + 'body': 'mock_body', + 'id': 'mock_id', + 'date_created': 'mock_date' + }], + 'title': 'mock_title', + 'html_url': 'mock_url', + 'id': 1234, + 'labels': 'mock_tags', + 'milestone': 'mock_milestone', + 'priority': 'mock_priority', + 'body': 'mock_content', + 'user': 'mock_reporter', + 'assignees': 'mock_assignee', + 'state': 'closed', + 'date_created': 'mock_date' + } + + # Call the function + response = i.Issue.from_github( + upstream='github', + issue=mock_issue, + config=self.mock_config + ) + + # Assert that we made the calls correctly + self.assertEqual(response.source, 'github') + self.assertEqual(response.title, '[github] mock_title') + self.assertEqual(response.url, 'mock_url') + self.assertEqual(response.upstream, 'github') + self.assertEqual(response.comments, [{'body': 'mock_body', 'name': 'mock_name', 'author': 'mock_author', + 'changed': None, 'date_created': 'mock_date', 'id': 'mock_id'}]) + self.assertEqual(response.tags, 'mock_tags') + self.assertEqual(response.fixVersion, ['mock_milestone']) + self.assertEqual(response.priority, None) + self.assertEqual(response.content, 'mock_content') + self.assertEqual(response.reporter, 'mock_reporter') + self.assertEqual(response.assignee, 'mock_assignee') + self.assertEqual(response.status, 'Closed') + self.assertEqual(response.id, '1234') + self.assertEqual(response.downstream, 'mock_downstream') diff --git a/tests/test_main.py b/tests/test_main.py index 82c6328..d9ab496 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -250,9 +250,9 @@ class TestMain(unittest.TestCase): @mock.patch(PATH + 'd') @mock.patch(PATH + 'fedmsg') def test_listen(self, - mock_fedmsg, - mock_d, - mock_u): + mock_fedmsg, + mock_d, + mock_u): """ Test 'listen' function where everything goes smoothly """ @@ -266,4 +266,30 @@ class TestMain(unittest.TestCase): # Assert everything was called correctly mock_d.sync_with_jira.assert_called_with('dummy_issue', self.mock_config) mock_u.handle_github_message.assert_called_with(self.mock_message, self.mock_config) - mock_u.handle_pagure_message.assert_not_called() \ No newline at end of file + mock_u.handle_pagure_message.assert_not_called() + + @mock.patch(PATH + 'send_mail') + @mock.patch(PATH + 'jinja2') + def test_report_failure(self, + mock_jinja2, + mock_send_mail): + """ + Tests 'report_failure' function + """ + # Set up return values + mock_templateLoader = MagicMock() + mock_templateEnv = MagicMock() + mock_template = MagicMock() + mock_template.render.return_value = 'mock_html' + mock_templateEnv.get_template.return_value = mock_template + mock_jinja2.FileSystemLoader.return_value = mock_templateLoader + mock_jinja2.Environment.return_value = mock_templateEnv + + # Call the function + m.report_failure({'sync2jira': {'admins': [{'mock_user': 'mock_email'}]}}) + + # Assert everything was called correctly + mock_send_mail.assert_called_with(cc=None, + recipients=['mock_email'], + subject='Sync2Jira Has Failed!', + text='mock_html') \ No newline at end of file