From 24f252e68c4bbd16c5ce6bad4d0d97a1ad7fe843 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 30 Jul 2019 23:10:40 +0300 Subject: [PATCH] [db] Remove Bug model, replace with LinkReference. Closes #1029 tracking bugs will be performed linking to their URLs instead of keeping a reference to their ID and trying to construct the URL on the fly. Obsoletes #320 --- tcms/core/ajax.py | 7 ++-- tcms/testcases/migrations/0010_remove_bug.py | 31 ++++++++++++++++++ tcms/testcases/models.py | 34 -------------------- tcms/testcases/tests/test_views.py | 6 ++-- tcms/testruns/data.py | 24 ++++++-------- tcms/testruns/models.py | 13 ++++---- tcms/testruns/views.py | 1 + tcms/tests/factories.py | 17 ++++------ 8 files changed, 63 insertions(+), 70 deletions(-) create mode 100644 tcms/testcases/migrations/0010_remove_bug.py diff --git a/tcms/core/ajax.py b/tcms/core/ajax.py index 048217718a..17d9f3a859 100644 --- a/tcms/core/ajax.py +++ b/tcms/core/ajax.py @@ -17,12 +17,13 @@ from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.decorators import permission_required -from tcms.testcases.models import TestCase, Bug +from tcms.testcases.models import TestCase from tcms.testcases.models import TestCaseTag from tcms.testplans.models import TestPlan, TestPlanTag from tcms.testruns.models import TestExecution, TestRunTag from tcms.core.helpers.comments import add_comment from tcms.core.utils.validations import validate_bug_id +from tcms.core.contrib.linkreference.models import LinkReference def tags(request): @@ -249,7 +250,9 @@ def update_bugs_to_caseruns(request): bug_system_id=bug_system_id, bz_external_track=bz_external_track) else: - bugs = Bug.objects.filter(bug_id__in=bug_ids) + # fixme: the filter condition here is wrong. We no longer have + # separate bug_ids, we have list of primary keys for LR objects + bugs = LinkReference.objects.filter(bug_id__in=bug_ids) for run in runs: for bug in bugs: if bug.case_run_id == run.pk: diff --git a/tcms/testcases/migrations/0010_remove_bug.py b/tcms/testcases/migrations/0010_remove_bug.py new file mode 100644 index 0000000000..cf9655c0db --- /dev/null +++ b/tcms/testcases/migrations/0010_remove_bug.py @@ -0,0 +1,31 @@ +from django.db import migrations + + +def forward_copy_data(apps, schema_editor): + Bug = apps.get_model('testcases', 'Bug') + LinkReference = apps.get_model('linkreference', 'LinkReference') + + for bug in Bug.objects.all(): + LinkReference.objects.create( + execution_id=bug.case_run_id, + name="%s %s" % (bug.bug_system.name, bug.bug_id), + url=bug.bug_system.url_reg_exp % bug.bug_id, + is_defect=True, + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('testcases', '0009_populate_missing_text_history'), + ('linkreference', '0002_update_fields'), + ] + + operations = [ + # copy the data from the related model + migrations.RunPython(forward_copy_data), + + migrations.DeleteModel( + name='Bug', + ), + ] diff --git a/tcms/testcases/models.py b/tcms/testcases/models.py index adb1a8333e..38ffbe8b06 100644 --- a/tcms/testcases/models.py +++ b/tcms/testcases/models.py @@ -452,40 +452,6 @@ def tracker_from_url(cls, url): return None -class Bug(TCMSActionModel): - bug_id = models.CharField(max_length=25) - case_run = models.ForeignKey('testruns.TestExecution', default=None, blank=True, null=True, - related_name='case_run_bug', on_delete=models.CASCADE) - case = models.ForeignKey(TestCase, related_name='case_bug', on_delete=models.CASCADE) - bug_system = models.ForeignKey(BugSystem, default=1, on_delete=models.CASCADE) - summary = models.CharField(max_length=255, blank=True, null=True) - description = models.TextField(blank=True, null=True) - - class Meta: - unique_together = (('bug_id', 'case_run', 'case'), - ('bug_id', 'case_run')) - - def unique_error_message(self, model_class, unique_check): - """Specific to invalid bug id""" - bug_id_uniques = (('bug_id', 'case_run', 'case'), - ('bug_id', 'case_run')) - if unique_check in bug_id_uniques: - return 'Bug %d exists in run %d already.' % (self.bug_id, self.case_run.pk) - return super().unique_error_message(model_class, unique_check) - - def __str__(self): - return self.bug_id - - def get_name(self): - if self.summary: - return self.summary - - return self.bug_id - - def get_full_url(self): - return self.bug_system.url_reg_exp % self.bug_id - - class TestCaseEmailSettings(models.Model): case = models.OneToOneField(TestCase, related_name='email_settings', on_delete=models.CASCADE) notify_on_case_update = models.BooleanField(default=True) diff --git a/tcms/testcases/tests/test_views.py b/tcms/testcases/tests/test_views.py index 63654e50f8..928e28ef36 100644 --- a/tcms/testcases/tests/test_views.py +++ b/tcms/testcases/tests/test_views.py @@ -16,7 +16,7 @@ from tcms.testcases.models import TestCase, TestCasePlan from tcms.testcases.views import get_selected_testcases from tcms.testruns.models import TestExecutionStatus -from tcms.tests.factories import BugFactory +from tcms.tests.factories import LinkReferenceFactory from tcms.tests.factories import TestCaseFactory from tcms.tests import BasePlanCase, BaseCaseRun, remove_perm_from_user from tcms.tests import user_should_have_perm @@ -66,8 +66,8 @@ def test_user_in_default_group_sees_comments(self): ) def test_user_sees_bugs(self): - bug_1 = BugFactory() - bug_2 = BugFactory() + bug_1 = LinkReferenceFactory() + bug_2 = LinkReferenceFactory() self.execution_1.add_bug(bug_1.bug_id, bug_1.bug_system.pk) self.execution_1.add_bug(bug_2.bug_id, bug_2.bug_system.pk) diff --git a/tcms/testruns/data.py b/tcms/testruns/data.py index 0f058f8313..19ea51a7f8 100644 --- a/tcms/testruns/data.py +++ b/tcms/testruns/data.py @@ -7,9 +7,9 @@ from django.contrib.contenttypes.models import ContentType from django_comments.models import Comment -from tcms.testcases.models import Bug from tcms.testruns.models import TestExecution from tcms.testruns.models import TestExecutionStatus +from tcms.core.contrib.linkreference.models import LinkReference def get_run_bug_ids(run_id): @@ -19,12 +19,10 @@ def get_run_bug_ids(run_id): :return: list of pairs of bug ID and bug link. :rtype: list """ - return Bug.objects.values( - 'bug_id', - 'bug_system', - 'bug_system__tracker_type', - 'bug_system__url_reg_exp' - ).distinct().filter(case_run__run=run_id) + return LinkReference.objects.filter( + execution__run=run_id, + is_defect=True, + ).distinct() class TestExecutionDataMixin: @@ -65,14 +63,12 @@ def get_execution_bugs(run_pk): :rtype: dict """ - bugs = Bug.objects.filter( - case_run__run=run_pk - ).values( - 'case_run', - 'bug_id', - 'bug_system__url_reg_exp' - ).order_by('case_run') + bugs = LinkReference.objects.filter( + execution__run=run_pk, + is_defect=True, + ).order_by('execution') + # fixme: everything below needs updating to work with LR rows = [] for row in bugs: row['bug_url'] = row['bug_system__url_reg_exp'] % row['bug_id'] diff --git a/tcms/testruns/models.py b/tcms/testruns/models.py index 8713c72667..edd9568222 100755 --- a/tcms/testruns/models.py +++ b/tcms/testruns/models.py @@ -13,7 +13,6 @@ from tcms.core.models import TCMSActionModel from tcms.core.history import KiwiHistoricalRecords from tcms.core.contrib.linkreference.models import LinkReference -from tcms.testcases.models import Bug from tcms.xmlrpc.serializer import TestExecutionXMLRPCSerializer from tcms.xmlrpc.serializer import TestRunXMLRPCSerializer from tcms.xmlrpc.utils import distinct_filter @@ -142,9 +141,10 @@ def get_bug_count(self): """ # note fom Django docs: A count() call performs a SELECT COUNT(*) # behind the scenes !!! - return Bug.objects.filter( - case_run__run=self.pk - ).values('bug_id').distinct().count() + return LinkReference.objects.filter( + execution__run=self.pk, + is_defect=True, + ).distinct().count() def get_percentage(self, count): case_run_count = self.total_num_caseruns @@ -359,8 +359,9 @@ def remove_bug(self, bug_id, run_id=None): self.case.remove_bug(bug_id=bug_id, run_id=run_id) def get_bugs(self): - return Bug.objects.filter( - case_run__case_run_id=self.case_run_id) + return LinkReference.objects.filter( + execution=self.pk, + is_defect=True) def get_bugs_count(self): return self.get_bugs().count() diff --git a/tcms/testruns/views.py b/tcms/testruns/views.py index 052ec18dfc..02f91dee36 100755 --- a/tcms/testruns/views.py +++ b/tcms/testruns/views.py @@ -353,6 +353,7 @@ def get_context_data(self, **kwargs): execution_bugs = [] bug_system_types = {} + # fixme: make this loop work with LinkReference objects for _bug in get_run_bug_ids(run.pk): # format the bug URLs based on DB settings execution_bugs.append(( diff --git a/tcms/tests/factories.py b/tcms/tests/factories.py index 58996de741..86ed36e13b 100644 --- a/tcms/tests/factories.py +++ b/tcms/tests/factories.py @@ -11,7 +11,6 @@ from tcms.management.models import Priority from tcms.testcases.models import TestCaseStatus -from tcms.testcases.models import BugSystem from tcms.testruns.models import TestExecutionStatus @@ -294,19 +293,15 @@ class Meta: build = factory.SubFactory(BuildFactory) -class BugFactory(DjangoModelFactory): +class LinkReferenceFactory(DjangoModelFactory): class Meta: - model = 'testcases.Bug' + model = 'linkreference.LinkReference' - bug_id = factory.Sequence(lambda n: n) - summary = factory.LazyAttribute(lambda obj: 'Summary of bug %s' % obj.bug_id) - description = '' - bug_system = factory.LazyFunction( - lambda: BugSystem.objects.first() # pylint: disable=unnecessary-lambda - ) - case_run = factory.SubFactory(TestExecutionFactory) - case = factory.SubFactory(TestCaseFactory) + execution = factory.SubFactory(TestExecutionFactory) + name = factory.Sequence(lambda n: "Bug %d" % n) + url = factory.Sequence(lambda n: "https://example.com/link/%d/" % n) + is_defect = True class TestRunTagFactory(DjangoModelFactory):