Skip to content

Commit

Permalink
Remove similar code in add_testexecution_to_issue()
Browse files Browse the repository at this point in the history
instead define this method in the base class and use
class attributes that point to the appropriate Thread class which
provides the integration with every bug tracker.
  • Loading branch information
atodorov committed May 15, 2020
1 parent 04408f4 commit 48ca8db
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 81 deletions.
103 changes: 53 additions & 50 deletions tcms/issuetracker/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,62 @@
RE_ENDS_IN_INT = re.compile(r'[\d]+$')


class IntegrationThread(threading.Thread):
"""
Used as a base class for everything else.
"""

def __init__(self, rpc, bug_system, execution, bug_id):
"""
:param rpc: Bug tracker RPC object
:param bug_system: BugSystem object
:param execution: TestExecution object
:param bug_id: Unique defect identifier in the system. Usually an int.
"""
self.rpc = rpc
self.bug_system = bug_system
self.execution = execution
self.bug_id = bug_id

super().__init__()

def text(self):
"""
Returns the text that will be posted as a comment to
the reported bug!
"""
return """---- Confirmed via test execution ----
TR-%d: %s
%s
TE-%d: %s""" % (self.execution.run.pk,
self.execution.run.summary,
self.execution.run.get_full_url(),
self.execution.pk,
self.execution.case.summary)

def post_comment(self):
raise NotImplementedError()

def run(self):
"""
Using RPC try to link the test case with existing bug!
By default will post a comment!
"""

try:
self.post_comment()
except Exception as err: # pylint: disable=broad-except
message = '%s: %s' % (err.__class__.__name__, err)
warnings.warn(message)


class IssueTrackerType:
"""
Represents actions which can be performed with issue trackers.
This is a common interface for all issue trackers that Kiwi TCMS
supports!
"""
it_class = IntegrationThread
rpc_cache = {}

def __init__(self, bug_system):
Expand Down Expand Up @@ -103,7 +153,9 @@ def add_testexecution_to_issue(self, executions, issue_url):
:executions: - iterable of TestExecution objects
:issue_url: - the URL of the existing defect
"""
raise NotImplementedError()
bug_id = self.bug_id_from_url(issue_url)
for execution in executions:
self.it_class(self.rpc, self.bug_system, execution, bug_id).start()

def is_adding_testcase_to_issue_disabled(self): # pylint: disable=invalid-name, no-self-use
"""
Expand Down Expand Up @@ -140,52 +192,3 @@ def rpc(self):
self.rpc_cache[self.bug_system.base_url] = self._rpc_connection()

return self.rpc_cache[self.bug_system.base_url]


class IntegrationThread(threading.Thread):
"""
Used as a base class for everything else.
"""

def __init__(self, rpc, bug_system, execution, bug_id):
"""
:param rpc: Bug tracker RPC object
:param bug_system: BugSystem object
:param execution: TestExecution object
:param bug_id: Unique defect identifier in the system. Usually an int.
"""
self.rpc = rpc
self.bug_system = bug_system
self.execution = execution
self.bug_id = bug_id

super().__init__()

def text(self):
"""
Returns the text that will be posted as a comment to
the reported bug!
"""
return """---- Confirmed via test execution ----
TR-%d: %s
%s
TE-%d: %s""" % (self.execution.run.pk,
self.execution.run.summary,
self.execution.run.get_full_url(),
self.execution.pk,
self.execution.case.summary)

def post_comment(self):
raise NotImplementedError()

def run(self):
"""
Using RPC try to link the test case with existing bug!
By default will post a comment!
"""

try:
self.post_comment()
except Exception as err: # pylint: disable=broad-except
message = '%s: %s' % (err.__class__.__name__, err)
warnings.warn(message)
36 changes: 5 additions & 31 deletions tcms/issuetracker/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Bugzilla(IssueTrackerType):
is not provided a temporary directory will be used each time we try to login
into Bugzilla!
"""
it_class = bugzilla_integration.BugzillaThread

def __init__(self, bug_system):
super().__init__(bug_system)
Expand All @@ -72,14 +73,6 @@ def _rpc_connection(self):
tokenfile=self._bugzilla_cache_dir + 'token',
)

def add_testexecution_to_issue(self, executions, issue_url):
bug_id = self.bug_id_from_url(issue_url)
for execution in executions:
bugzilla_integration.BugzillaThread(self.rpc,
self.bug_system,
execution,
bug_id).start()

def report_issue_from_testexecution(self, execution, user):
args = {}
args['cf_build_id'] = execution.run.build.name
Expand Down Expand Up @@ -109,6 +102,7 @@ class JIRA(IssueTrackerType):
setting (in ``product.py``). By default this setting is not provided and
the code uses ``jira.JIRA.DEFAULT_OPTIONS`` from the ``jira`` Python module!
"""
it_class = jira_integration.JiraThread

def _rpc_connection(self):
if hasattr(settings, 'JIRA_OPTIONS'):
Expand All @@ -130,11 +124,6 @@ def bug_id_from_url(cls, url):
"""
return url.strip().split('/')[-1]

def add_testexecution_to_issue(self, executions, issue_url):
bug_id = self.bug_id_from_url(issue_url)
for execution in executions:
jira_integration.JiraThread(self.rpc, self.bug_system, execution, bug_id).start()

def report_issue_from_testexecution(self, execution, user):
"""
For the HTML API description see:
Expand Down Expand Up @@ -187,16 +176,12 @@ class GitHub(IssueTrackerType):
You can leave the ``api_url`` and ``api_username`` fields blank because
the integration code doesn't use them!
"""
it_class = github_integration.GitHubThread

def _rpc_connection(self):
# NOTE: we use an access token so only the password field is required
return github.Github(self.bug_system.api_password)

def add_testexecution_to_issue(self, executions, issue_url):
bug_id = self.bug_id_from_url(issue_url)
for execution in executions:
github_integration.GitHubThread(self.rpc, self.bug_system, execution, bug_id).start()

def is_adding_testcase_to_issue_disabled(self):
return not (self.bug_system.base_url and self.bug_system.api_password)

Expand Down Expand Up @@ -245,17 +230,13 @@ class Gitlab(IssueTrackerType):
You can leave ``api_username`` field blank because
the integration code doesn't use it!
"""
it_class = gitlab_integration.GitlabThread

def _rpc_connection(self):
# we use an access token so only the password field is required
return gitlab.Gitlab(self.bug_system.api_url,
private_token=self.bug_system.api_password)

def add_testexecution_to_issue(self, executions, issue_url):
bug_id = self.bug_id_from_url(issue_url)
for execution in executions:
gitlab_integration.GitlabThread(self.rpc, self.bug_system, execution, bug_id).start()

def is_adding_testcase_to_issue_disabled(self):
return not (self.bug_system.api_url and self.bug_system.api_password)

Expand All @@ -280,6 +261,7 @@ class Redmine(IssueTrackerType):
:api_username: - a username registered in Redmine
:api_password: - the password for this username
"""
it_class = redmine_integration.RedmineThread

def _rpc_connection(self):
return redminelib.Redmine(
Expand All @@ -288,14 +270,6 @@ def _rpc_connection(self):
password=self.bug_system.api_password
)

def add_testexecution_to_issue(self, executions, issue_url):
bug_id = self.bug_id_from_url(issue_url)
for execution in executions:
redmine_integration.RedmineThread(self.rpc,
self.bug_system,
execution,
bug_id).start()

def find_project_by_name(self, name):
"""
Return a Redmine project which matches the given product name.
Expand Down

0 comments on commit 48ca8db

Please sign in to comment.