コード例 #1
0
def detach_bug(request, case_ids, bug_ids):
    """Remove one or more bugs to the selected test cases.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param bug_ids: give one or more bug IDs. It could be an integer, a string
        containing comma separated IDs, or a list of int each of them is a bug
        ID.
    :type component_ids: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Remove bug id 1000 from case 1
        >>> TestCase.detach_bug(1, 1000)
        # Remove bug ids list [1000, 1001] from cases list [1, 2]
        >>> TestCase.detach_bug([1, 2], [1000, 1001])
        # Remove bug ids list '1000, 1001' from cases list '1, 2' with String
        >>> TestCase.detach_bug('1, 2', '1000, 1001')
    """
    case_ids = pre_process_ids(case_ids)
    bug_ids = pre_process_ids(bug_ids)

    tcs = TestCase.objects.filter(case_id__in=case_ids).iterator()
    for tc in tcs:
        for opk in bug_ids:
            try:
                tc.remove_bug(bug_id=opk)
            except ObjectDoesNotExist:
                pass

    return
コード例 #2
0
def remove_cases(request, run_ids, case_ids):
    """Remove one or more cases from the selected test runs.

    :param run_ids: give one or more run IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a run ID.
    :type run_ids: int, str or list
    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.
    :rtype: list

    Example::

        # Remove case 10 from run 1
        TestRun.remove_cases(1, 10)
        # Remove case ids list [10, 20] from run list [1, 2]
        TestRun.remove_cases([1, 2], [10, 20])
        # Remove case ids list '10, 20' from run list '1, 2' with String
        TestRun.remove_cases('1, 2', '10, 20')
    """
    trs = TestRun.objects.filter(run_id__in=pre_process_ids(run_ids))
    for tr in trs.iterator():
        crs = TestCaseRun.objects.filter(
            run=tr, case__in=pre_process_ids(case_ids))
        crs.delete()
コード例 #3
0
ファイル: testplan.py プロジェクト: MrSenko/Nitrate
def add_component(request, plan_ids, component_ids):
    """
    Description: Adds one or more components to the selected test plan.

    Params:      $plan_ids - Integer/Array/String: An integer representing the ID of the plan in the database.
                 $component_ids - Integer/Array/String - The component ID, an array of Component IDs
                                  or a comma separated list of component IDs.

    Returns:     Array: empty on success or an array of hashes with failure
                        codes if a failure occured.

    Example:
    # Add component id 54321 to plan 1234
    >>> TestPlan.add_component(1234, 54321)
    # Add component ids list [1234, 5678] to plan list [56789, 12345]
    >>> TestPlan.add_component([56789, 12345], [1234, 5678])
    # Add component ids list '1234, 5678' to plan list '56789, 12345' with String
    >>> TestPlan.add_component('56789, 12345', '1234, 5678')
    """
    # FIXME: optimize this method to reduce possible huge number of SQLs

    tps = TestPlan.objects.filter(
        plan_id__in=pre_process_ids(value=plan_ids)
    )
    cs = Component.objects.filter(
        id__in=pre_process_ids(value=component_ids)
    )

    for tp in tps.iterator():
        for c in cs.iterator():
            tp.add_component(c)

    return
コード例 #4
0
def add_cases(request, run_ids, case_ids):
    """Add one or more cases to the selected test runs.

    :param run_ids: give one or more run IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a run ID.
    :type run_ids: int, str or list
    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.
    :rtype: list

    Example::

        # Add case id 10 to run 1
        >>> TestRun.add_cases(1, 10)
        # Add case ids list [10, 20] to run list [1, 2]
        >>> TestRun.add_cases([1, 2], [10, 20])
        # Add case ids list '10, 20' to run list '1, 2' with String
        >>> TestRun.add_cases('1, 2', '10, 20')
    """
    trs = TestRun.objects.filter(run_id__in=pre_process_ids(run_ids))
    tcs = TestCase.objects.filter(case_id__in=pre_process_ids(case_ids))

    for tr in trs.iterator():
        for tc in tcs.iterator():
            tr.add_case_run(case=tc)

    return
コード例 #5
0
ファイル: testcaserun.py プロジェクト: tkdchen/Nitrate
def detach_issue(request, case_run_ids, issue_keys):
    """Remove one or more issues to the selected test case-runs.

    :param case_run_ids: give one or more case run IDs. It could be an integer,
        a string containing comma separated IDs, or a list of int each of them
        is a case run ID.
    :type run_ids: int, str or list
    :param issue_keys: give one or more case run IDs. It could be an integer,
        a string containing comma separated IDs, or a list of int each of them
        is a case run ID.
    :type issue_keys: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.
    :rtype: list

    Example::

        # Remove issue 1000 from case run 1
        >>> TestCaseRun.detach_issue(1, 1000)
        # Remove issues [1000, 2000] from case runs list [1, 2]
        >>> TestCaseRun.detach_issue([1, 2], [1000, 2000])
        # Remove issues '1000, 2000' from case runs list '1, 2' with String
        >>> TestCaseRun.detach_issue('1, 2', '1000, 2000')
    """
    tcrs = TestCaseRun.objects.filter(pk__in=pre_process_ids(case_run_ids))
    issue_keys = pre_process_ids(issue_keys)

    for tcr in tcrs.iterator():
        for issue_key in issue_keys:
            tcr.remove_issue(issue_key=issue_key, case_run=tcr)
コード例 #6
0
def add_component(request, case_ids, component_ids):
    """Adds one or more components to the selected test cases.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param component_ids: give one or more component IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a component ID.
    :type component_ids: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Add component id 1 to case 1
        >>> TestCase.add_component(1, 1)
        # Add component ids list [3, 4] to cases list [1, 2]
        >>> TestCase.add_component([1, 2], [3, 4])
        # Add component ids list '3, 4' to cases list '1, 2' with String
        >>> TestCase.add_component('1, 2', '3, 4')
    """
    from tcms.management.models import Component

    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids))
    cs = Component.objects.filter(
        id__in=pre_process_ids(value=component_ids))

    for tc in tcs.iterator():
        for c in cs.iterator():
            tc.add_component(component=c)
コード例 #7
0
ファイル: testrun.py プロジェクト: MrSenko/Nitrate
def add_cases(request, run_ids, case_ids):
    """
    Description: Add one or more cases to the selected test runs.

    Params:      $run_ids - Integer/Array/String: An integer representing the ID in the database
                                                  an array of IDs, or a comma separated list of IDs.

                 $case_ids - Integer/Array/String: An integer or alias representing the ID in the database,
                                                  an arry of case_ids or aliases, or a string of comma separated case_ids.

    Returns:     Array: empty on success or an array of hashes with failure
                        codes if a failure occured.

    Example:
    # Add case id 54321 to run 1234
    >>> TestRun.add_cases(1234, 54321)
    # Add case ids list [1234, 5678] to run list [56789, 12345]
    >>> TestRun.add_cases([56789, 12345], [1234, 5678])
    # Add case ids list '1234, 5678' to run list '56789, 12345' with String
    >>> TestRun.add_cases('56789, 12345', '1234, 5678')
    """
    trs = TestRun.objects.filter(run_id__in=pre_process_ids(run_ids))
    tcs = TestCase.objects.filter(case_id__in=pre_process_ids(case_ids))

    for tr in trs.iterator():
        for tc in tcs.iterator():
            tr.add_case_run(case=tc)

    return
コード例 #8
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def detach_bug(request, case_ids, bug_ids):
    """
    Description: Remove one or more bugs to the selected test cases.

    Params:      $case_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of case_ids, or a string of comma separated case_ids

                 $bug_ids - Integer/Array/String: An integer representing the ID in the database,
                           an array of bug_ids, or a string of comma separated primary key of bug_ids.

    Returns:     Array: empty on success or an array of hashes with failure
                 codes if a failure occured.

    Example:
    # Remove bug id 54321 from case 1234
    >>> TestCase.detach_bug(1234, 54321)
    # Remove bug ids list [1234, 5678] from cases list [56789, 12345]
    >>> TestCase.detach_bug([56789, 12345], [1234, 5678])
    # Remove bug ids list '1234, 5678' from cases list '56789, 12345' with String
    >>> TestCase.detach_bug('56789, 12345', '1234, 5678')
    """
    case_ids = pre_process_ids(case_ids)
    bug_ids = pre_process_ids(bug_ids)

    tcs = TestCase.objects.filter(case_id__in=case_ids).iterator()
    for tc in tcs:
        for opk in bug_ids:
            try:
                tc.remove_bug(bug_id=opk)
            except ObjectDoesNotExist:
                pass

    return
コード例 #9
0
ファイル: testcase.py プロジェクト: erichuanggit/Nitrate
def link_plan(request, case_ids, plan_ids):
    """"
    Description: Link test cases to the given plan.

    Params:      $case_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of case_ids, or a string of comma separated case_ids.

                 $plan_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of plan_ids, or a string of comma separated plan_ids.

    Returns:     Array: empty on success or an array of hashes with failure
                        codes if a failure occurs

    Example:
    # Add case 1234 to plan id 54321
    >>> TestCase.link_plan(1234, 54321)
    # Add case ids list [56789, 12345] to plan list [1234, 5678]
    >>> TestCase.link_plan([56789, 12345], [1234, 5678])
    # Add case ids list 56789 and 12345 to plan list 1234 and 5678 with String
    >>> TestCase.link_plan('56789, 12345', '1234, 5678')
    """
    from tcms.apps.testplans.models import TestPlan

    case_ids = pre_process_ids(value=case_ids)
    plan_ids = pre_process_ids(value=plan_ids)

    tcs = TestCase.objects.filter(pk__in=case_ids)
    tps = TestPlan.objects.filter(pk__in=plan_ids)

    # Check the non-exist case ids.
    if tcs.count() < len(case_ids):
        raise ObjectDoesNotExist(
            "TestCase", compare_list(case_ids,
                                     tcs.values_list('pk',
                                                     flat=True).iterator())
        )

    # Check the non-exist plan ids.
    if tps.count() < len(plan_ids):
        raise ObjectDoesNotExist(
            "TestPlan", compare_list(plan_ids,
                                     tps.values_list('pk',
                                                     flat=True).iterator())
        )

    # Link the plans to cases
    for tc in tcs.iterator():
        for tp in tps.iterator():
            tc.add_to_plan(tp)

    return
コード例 #10
0
ファイル: test_utils.py プロジェクト: Aaln1986/Nitrate
    def test_pre_process_ids_with_others(self):
        try:
            U.pre_process_ids((1,))
        except TypeError as e:
            self.assertEqual(str(e), 'Unrecognizable type of ids')
        else:
            self.fail("Missing validations.")

        try:
            U.pre_process_ids(dict(a=1))
        except TypeError as e:
            self.assertEqual(str(e), 'Unrecognizable type of ids')
        else:
            self.fail("Missing validations.")
コード例 #11
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def calculate_total_estimated_time(request, case_ids):
    """
    Description: Returns an total estimated time for cases.

    Params:      $case_ids - Integer/String: An integer representing the ID in the database.

    Returns:     String: Time in "HH:MM:SS" format.

    Example:
    >>> TestCase.calculate_total_time([609, 610, 611])
    """
    from django.db.models import Sum

    tcs = TestCase.objects.filter(
        pk__in=pre_process_ids(case_ids)).only('estimated_time')

    if not tcs.exists():
        raise ValueError('Please input valid case Id')

    # aggregate Sum return integer directly rather than timedelta
    seconds = tcs.aggregate(Sum('estimated_time')).get('estimated_time__sum')

    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    # TODO: return h:m:s or d:h:m
    return '%02i:%02i:%02i' % (h, m, s)
コード例 #12
0
def add_comment(request, case_ids, comment):
    """Adds comments to selected test cases.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param str comment: the comment content to add.
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Add comment 'foobar' to case 1
        >>> TestCase.add_comment(1, 'foobar')
        # Add 'foobar' to cases list [1, 2]
        >>> TestCase.add_comment([1, 2], 'foobar')
        # Add 'foobar' to cases list '1, 2' with String
        >>> TestCase.add_comment('1, 2', 'foobar')
    """
    from tcms.xmlrpc.utils import Comment

    object_pks = pre_process_ids(value=case_ids)
    c = Comment(
        request=request,
        content_type='testcases.testcase',
        object_pks=object_pks,
        comment=comment
    )

    return c.add()
コード例 #13
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def add_tag(request, case_ids, tags):
    """
    Description: Add one or more tags to the selected test cases.

    Params:     $case_ids - Integer/Array/String: An integer representing the ID in the database,
                            an array of case_ids, or a string of comma separated case_ids.

                $tags - String/Array - A single tag, an array of tags,
                        or a comma separated list of tags.

    Returns:    Array: empty on success or an array of hashes with failure
                       codes if a failure occured.

    Example:
    # Add tag 'foobar' to case 1234
    >>> TestCase.add_tag(1234, 'foobar')
    # Add tag list ['foo', 'bar'] to cases list [12345, 67890]
    >>> TestCase.add_tag([12345, 67890], ['foo', 'bar'])
    # Add tag list ['foo', 'bar'] to cases list [12345, 67890] with String
    >>> TestCase.add_tag('12345, 67890', 'foo, bar')
    """
    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids))

    tags = TestTag.string_to_list(tags)

    for tag in tags:
        t, c = TestTag.objects.get_or_create(name=tag)
        for tc in tcs.iterator():
            tc.add_tag(tag=t)

    return
コード例 #14
0
ファイル: testplan.py プロジェクト: MrSenko/Nitrate
def add_tag(request, plan_ids, tags):
    """
    Description: Add one or more tags to the selected test plans.

    Params:      $plan_ids - Integer/Array/String: An integer representing the ID of the plan in the database,
                      an arry of plan_ids, or a string of comma separated plan_ids.

                  $tags - String/Array - A single tag, an array of tags,
                      or a comma separated list of tags.

    Returns:     Array: empty on success or an array of hashes with failure
                  codes if a failure occured.

    Example:
    # Add tag 'foobar' to plan 1234
    >>> TestPlan.add_tag(1234, 'foobar')
    # Add tag list ['foo', 'bar'] to plan list [12345, 67890]
    >>> TestPlan.add_tag([12345, 67890], ['foo', 'bar'])
    # Add tag list ['foo', 'bar'] to plan list [12345, 67890] with String
    >>> TestPlan.add_tag('12345, 67890', 'foo, bar')
    """
    # FIXME: this could be optimized to reduce possible huge number of SQLs

    tps = TestPlan.objects.filter(plan_id__in=pre_process_ids(value=plan_ids))
    tags = TestTag.string_to_list(tags)

    for tag in tags:
        t, c = TestTag.objects.get_or_create(name=tag)
        for tp in tps.iterator():
            tp.add_tag(tag=t)

    return
コード例 #15
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def notification_add_cc(request, case_ids, cc_list):
    '''
    Description: Add email addresses to the notification CC list of specific TestCases

    Params:      $case_ids - Integer/Array: one or more TestCase IDs

                 $cc_list - Array: one or more Email addresses, which will be
                            added to each TestCase indicated by the case_ids.

    Returns:     JSON. When succeed, status is 0, and message maybe empty or
                 anything else that depends on the implementation. If something
                 wrong, status will be 1 and message will be a short description
                 to the error.
    '''

    try:
        validate_cc_list(cc_list)
    except (TypeError, ValidationError):
        raise

    try:
        tc_ids = pre_process_ids(case_ids)

        for tc in TestCase.objects.filter(pk__in=tc_ids).iterator():
            # First, find those that do not exist yet.
            existing_cc = tc.emailing.get_cc_list()
            adding_cc = list(set(cc_list) - set(existing_cc))

            tc.emailing.add_cc(adding_cc)

    except (TypeError, ValueError, Exception):
        raise
コード例 #16
0
def add_tag(request, case_ids, tags):
    """Add one or more tags to the selected test cases.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param tags: tag name or a list of tag names to remove.
    :type tags: str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Add tag 'foobar' to case 1
        >>> TestCase.add_tag(1, 'foobar')
        # Add tag list ['foo', 'bar'] to cases list [1, 2]
        >>> TestCase.add_tag([1, 2], ['foo', 'bar'])
        # Add tag list ['foo', 'bar'] to cases list [1, 2] with String
        >>> TestCase.add_tag('1, 2', 'foo, bar')
    """
    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids))

    tags = TestTag.string_to_list(tags)

    for tag in tags:
        t, c = TestTag.objects.get_or_create(name=tag)
        for tc in tcs.iterator():
            tc.add_tag(tag=t)

    return
コード例 #17
0
def get_bugs(request, run_ids):
    """Get the list of bugs attached to this run.

    :param run_ids: give one or more run IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a run ID.
    :type run_ids: int, str or list
    :return: a list of mappings of :class:`TestCaseBug`.
    :rtype: list[dict]

    Example::

        # Get bugs belong to ID 12345
        >>> TestRun.get_bugs(1)
        # Get bug belong to run ids list [1, 2]
        >>> TestRun.get_bugs([1, 2])
        # Get bug belong to run ids list 1 and 2 with string
        >>> TestRun.get_bugs('1, 2')
    """
    from tcms.testcases.models import TestCaseBug

    trs = TestRun.objects.filter(
        run_id__in=pre_process_ids(value=run_ids)
    )
    tcrs = TestCaseRun.objects.filter(
        run__run_id__in=trs.values_list('run_id', flat=True)
    )

    query = {'case_run__case_run_id__in': tcrs.values_list('case_run_id',
                                                           flat=True)}
    return TestCaseBug.to_xmlrpc(query)
コード例 #18
0
def calculate_total_estimated_time(request, case_ids):
    """Returns an total estimated time for cases.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :return: Time in "HH:MM:SS" format.
    :rtype: str

    Example::

        >>> TestCase.calculate_total_estimated_time([609, 610, 611])
    """
    from django.db.models import Sum

    tcs = TestCase.objects.filter(
        pk__in=pre_process_ids(case_ids)).only('estimated_time')

    if not tcs.exists():
        raise ValueError('Please input valid case Id')

    # aggregate Sum return integer directly rather than timedelta
    seconds = tcs.aggregate(Sum('estimated_time')).get('estimated_time__sum')

    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    # TODO: return h:m:s or d:h:m
    return '%02i:%02i:%02i' % (h, m, s)
コード例 #19
0
ファイル: testcase.py プロジェクト: erichuanggit/Nitrate
def calculate_average_estimated_time(request, case_ids):
    """
    Description: Returns an average estimated time for cases.

    Params:      $case_ids - Integer/String: An integer representing the ID in the database.

    Returns:     String: Time in "HH:MM:SS" format.

    Example:
    >>> TestCase.calculate_average_time([609, 610, 611])
    """
    from datetime import timedelta
    from tcms.core.utils.xmlrpc import SECONDS_PER_DAY

    tcs = TestCase.objects.filter(
        pk__in=pre_process_ids(case_ids)).only('estimated_time')
    time = timedelta(0)
    case_count = 0
    for tc in tcs.iterator():
        case_count += 1
        time += tc.estimated_time

    seconds = time.seconds + (time.days * SECONDS_PER_DAY)
    # iterator will not populate cache so here will access db again
    # seconds = seconds / len(tcs)
    seconds = seconds / case_count

    return '%02i:%02i:%02i' % (
        seconds / 3600,  # Hours
        seconds / 60,  # Minutes
        seconds % 60  # Seconds
    )
コード例 #20
0
ファイル: testcase.py プロジェクト: erichuanggit/Nitrate
def calculate_total_estimated_time(request, case_ids):
    """
    Description: Returns an total estimated time for cases.

    Params:      $case_ids - Integer/String: An integer representing the ID in the database.

    Returns:     String: Time in "HH:MM:SS" format.

    Example:
    >>> TestCase.calculate_total_time([609, 610, 611])
    """
    from datetime import timedelta
    from tcms.core.utils.xmlrpc import SECONDS_PER_DAY

    tcs = TestCase.objects.filter(
        pk__in=pre_process_ids(case_ids)).only('estimated_time')
    time = timedelta(0)
    for tc in tcs.iterator():
        time += tc.estimated_time

    seconds = time.seconds + (time.days * SECONDS_PER_DAY)

    return '%02i:%02i:%02i' % (
        seconds / 3600,  # Hours
        seconds / 60,  # Minutes
        seconds % 60  # Seconds
    )
コード例 #21
0
def get_bugs(request, case_ids):
    """Get the list of bugs that are associated with this test case.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :return: list of mappings of :class:`TestCaseBug`.
    :rtype: list

    Example::

        # Get bugs belong to ID 1
        >>> TestCase.get_bugs(1)
        # Get bug belong to case ids list [1, 2]
        >>> TestCase.get_bugs([1, 2])
        # Get bug belong to case ids list 1 and 2 with string
        >>> TestCase.get_bugs('1, 2')
    """
    from tcms.testcases.models import TestCaseBug

    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids)
    )

    query = {'case__case_id__in': tcs.values_list('case_id', flat=True)}
    return TestCaseBug.to_xmlrpc(query)
コード例 #22
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def notification_remove_cc(request, case_ids, cc_list):
    '''
    Description: Remove email addresses from the notification CC list of specific TestCases

    Params:      $case_ids - Integer/Array: one or more TestCase IDs

                 $cc_list - Array: contians the email addresses that will
                            be removed from each TestCase indicated by case_ids.

    Returns:     JSON. When succeed, status is 0, and message maybe empty or
                 anything else that depends on the implementation. If something
                 wrong, status will be 1 and message will be a short description
                 to the error.
    '''

    try:
        validate_cc_list(cc_list)
    except (TypeError, ValidationError):
        raise

    try:
        tc_ids = pre_process_ids(case_ids)
        cursor = connection.writer_cursor
        ids_values = ",".join(itertools.repeat('%s', len(tc_ids)))
        email_values = ",".join(itertools.repeat('%s', len(cc_list)))
        sql = TC_REMOVE_CC % (ids_values, email_values)
        tc_ids.extend(cc_list)
        cursor.execute(sql, tc_ids)
        transaction.commit_unless_managed()
    except (TypeError, ValueError, Exception):
        raise
コード例 #23
0
def add_tag(request, plan_ids, tags):
    """Add one or more tags to the selected test plans.

    :param plan_ids: give one or more plan IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a plan ID.
    :type plan_ids: int, str or list
    :param tags: a tag name or list of tag names to be added.
    :type tags: str or list[str]
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Add tag 'foobar' to plan 1
        >>> TestPlan.add_tag(1, 'foobar')
        # Add tag list ['foo', 'bar'] to plan list [1, 2]
        >>> TestPlan.add_tag([1, 2], ['foo', 'bar'])
        # Add tag list ['foo', 'bar'] to plan list [1, 2] with String
        >>> TestPlan.add_tag('1, 2', 'foo, bar')
    """
    # FIXME: this could be optimized to reduce possible huge number of SQLs

    tps = TestPlan.objects.filter(plan_id__in=pre_process_ids(value=plan_ids))
    tags = TestTag.string_to_list(tags)

    for tag in tags:
        t, c = TestTag.objects.get_or_create(name=tag)
        for tp in tps.iterator():
            tp.add_tag(tag=t)

    return
コード例 #24
0
def update(request, case_ids, values):
    """Updates the fields of the selected case or cases.

                 $values   - Hash of keys matching TestCase fields and the new values
                             to set each field to.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param dict values: a mapping containing these case data to update.

        * case_status: (ini) optional
        * product: (ini) optional (Required if changes category)
        * category: (ini) optional
        * priority: (ini) optional
        * default_tester: (str or int) optional (str - user_name, int - user_id)
        * estimated_time: (str) optional (2h30m30s(recommend) or HH:MM:SS
        * is_automated: (ini) optional (0 - Manual, 1 - Auto, 2 - Both)
        * is_automated_proposed: (bool) optional
        * script: (str) optional
        * arguments: (str) optional
        * summary: (str) optional
        * requirement: (str) optional
        * alias: (str) optional
        * notes: (str) optional
        * extra_link: (str) optional (reference link)

    :return: a list of mappings of updated :class:`TestCase`.
    :rtype: list(dict)

    Example::

        # Update alias to 'tcms' for case 1 and 2
        >>> TestCase.update([1, 2], {'alias': 'tcms'})
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import UpdateCaseForm

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(values.get('estimated_time'))

    form = UpdateCaseForm(values)

    if values.get('category') and not values.get('product'):
        raise ValueError('Product ID is required for category')

    if values.get('product'):
        form.populate(product_id=values['product'])

    if form.is_valid():
        tcs = TestCase.update(
            case_ids=pre_process_ids(value=case_ids),
            values=form.cleaned_data,
        )
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': tcs.values_list('pk', flat=True)}
    return TestCase.to_xmlrpc(query)
コード例 #25
0
ファイル: testrun.py プロジェクト: MrSenko/Nitrate
def get_bugs(request, run_ids):
    """
    *** FIXME: BUGGY IN SERIALISER - List can not be serialize. ***
    Description: Get the list of bugs attached to this run.

    Params:      $run_ids - Integer/Array/String: An integer representing the ID in the database
                                                  an array of integers or a comma separated list of integers.

    Returns:     Array: An array of bug object hashes.

    Example:
    # Get bugs belong to ID 12345
    >>> TestRun.get_bugs(12345)
    # Get bug belong to run ids list [12456, 23456]
    >>> TestRun.get_bugs([12456, 23456])
    # Get bug belong to run ids list 12456 and 23456 with string
    >>> TestRun.get_bugs('12456, 23456')
    """
    from tcms.testcases.models import TestCaseBug

    trs = TestRun.objects.filter(
        run_id__in=pre_process_ids(value=run_ids)
    )
    tcrs = TestCaseRun.objects.filter(
        run__run_id__in=trs.values_list('run_id', flat=True)
    )

    query = {'case_run__case_run_id__in': tcrs.values_list('case_run_id',
                                                           flat=True)}
    return TestCaseBug.to_xmlrpc(query)
コード例 #26
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def add_comment(request, case_ids, comment):
    """
    Description: Adds comments to selected test cases.

    Params:      $case_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of case_ids, or a string of comma separated case_ids.

                 $comment - String - The comment

    Returns:     Array: empty on success or an array of hashes with failure
                        codes if a failure occured.

    Example:
    # Add comment 'foobar' to case 1234
    >>> TestCase.add_comment(1234, 'foobar')
    # Add 'foobar' to cases list [56789, 12345]
    >>> TestCase.add_comment([56789, 12345], 'foobar')
    # Add 'foobar' to cases list '56789, 12345' with String
    >>> TestCase.add_comment('56789, 12345', 'foobar')
    """
    from tcms.xmlrpc.utils import Comment

    object_pks = pre_process_ids(value=case_ids)
    c = Comment(
        request=request,
        content_type='testcases.testcase',
        object_pks=object_pks,
        comment=comment
    )

    return c.add()
コード例 #27
0
ファイル: testcase.py プロジェクト: erichuanggit/Nitrate
def notification_remove_cc(request, case_ids, cc_list):
    '''
    Description: Remove email addresses from the notification CC list of specific TestCases

    Params:      $case_ids - Integer/Array: one or more TestCase IDs

                 $cc_list - Array: contians the email addresses that will
                            be removed from each TestCase indicated by case_ids.

    Returns:     JSON. When succeed, status is 0, and message maybe empty or
                 anything else that depends on the implementation. If something
                 wrong, status will be 1 and message will be a short description
                 to the error.
    '''

    try:
        validate_cc_list(cc_list)
    except (TypeError, ValidationError):
        raise

    try:
        tc_ids = pre_process_ids(case_ids)

        for tc in TestCase.objects.filter(pk__in=tc_ids).iterator():
            tc.emailing.cc_list.filter(email__in=cc_list).delete()
    except (TypeError, ValueError, Exception):
        raise
コード例 #28
0
ファイル: test_utils.py プロジェクト: Aaln1986/Nitrate
    def test_pre_process_ids_with_string(self):
        try:
            U.pre_process_ids(["a", "b"])
        except ValueError as e:
            pass
        except Exception:
            self.fail("Unexcept error occurs.")
        else:
            self.fail("Missing validations.")

        try:
            U.pre_process_ids("1@2@3@4")
        except ValueError as e:
            pass
        except Exception:
            self.fail("Unexcept error occurs.")
        else:
            self.fail("Missing validations.")
コード例 #29
0
def add_to_run(request, case_ids, run_ids):
    """Add one or more cases to the selected test runs.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param run_ids: give one or more run IDs. It could be an integer, a string
        containing comma separated IDs, or a list of int each of them is a run
        ID.
    :type run_ids: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Add case 1 to run id 1
        >>> TestCase.add_to_run(1, 1)
        # Add case ids list [1, 2] to run list [3, 4]
        >>> TestCase.add_to_run([1, 2], [3, 4])
        # Add case ids list 1 and 2 to run list 3 and 4 with String
        >>> TestCase.add_to_run('1, 2', '3, 4')
    """
    from tcms.testruns.models import TestRun

    case_ids = pre_process_ids(case_ids)
    run_ids = pre_process_ids(run_ids)

    trs = TestRun.objects.filter(run_id__in=run_ids)
    if not trs.exists():
        raise ValueError('Invalid run_ids')

    tcs = TestCase.objects.filter(case_id__in=case_ids)
    if not tcs.exists():
        raise ValueError('Invalid case_ids')

    for tr in trs.iterator():
        for tc in tcs.iterator():
            tr.add_case_run(case=tc)

    return
コード例 #30
0
def remove_component(request, case_ids, component_ids):
    """Removes selected component from the selected test case.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param component_ids: give one or more component IDs. It could be an
        integer, a string containing comma separated IDs, or a list of int each
        of them is a component ID.
    :type plan_ids: int, str or list
    :return: a list which is emtpy on success.
    :rtype: list

    Example::

        # Remove component id 1 from case 1
        >>> TestCase.remove_component(1, 1)
        # Remove component ids list [3, 4] from cases list [1, 2]
        >>> TestCase.remove_component([1, 2], [3, 4])
        # Remove component ids list '3, 4' from cases list '1, 2' with String
        >>> TestCase.remove_component('1, 2', '3, 4')
    """
    from tcms.management.models import Component

    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids)
    )
    tccs = Component.objects.filter(
        id__in=pre_process_ids(value=component_ids)
    )

    for tc in tcs.iterator():
        for tcc in tccs.iterator():
            try:
                tc.remove_component(component=tcc)
            except ObjectDoesNotExist:
                pass

    return
コード例 #31
0
ファイル: testcase.py プロジェクト: jetlyb/Kiwi
def get_bugs(case_ids):
    """
    Description: Get the list of bugs that are associated with this test case.

    Params:      $case_ids - Integer/String: An integer representing the ID in the database

    Returns:     Array: An array of bug object hashes.

    Example:
    # Get bugs belong to ID 12345
    >>> TestCase.get_bugs(12345)
    # Get bug belong to case ids list [12456, 23456]
    >>> TestCase.get_bugs([12456, 23456])
    # Get bug belong to case ids list 12456 and 23456 with string
    >>> TestCase.get_bugs('12456, 23456')
    """
    from tcms.testcases.models import TestCaseBug

    tcs = TestCase.objects.filter(case_id__in=pre_process_ids(value=case_ids))

    query = {'case__case_id__in': tcs.values_list('case_id', flat=True)}
    return TestCaseBug.to_xmlrpc(query)
コード例 #32
0
def get_issues(request, case_ids):
    """Get the list of issues that are associated with this test case.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :return: list of mappings of :class:`Issue`.
    :rtype: list[dict]

    Example::

        # Get issues belonging to case 1
        TestCase.get_issues(1)
        # Get issues belonging to cases [1, 2]
        TestCase.get_issues([1, 2])
        # Get issues belonging to case 1 and 2 with string
        TestCase.get_issues('1, 2')
    """
    case_ids = pre_process_ids(case_ids)
    query = {'case__in': case_ids}
    return Issue.to_xmlrpc(query)
コード例 #33
0
ファイル: testplan.py プロジェクト: thr27/Kiwi
def remove_tag(request, plan_ids, tags):
    """
    Description: Remove a tag from a plan.

    Params:      $plan_ids - Integer/Array/String: An integer or alias representing the ID in the database,
                                                   an array of plan_ids, or a string of comma separated plan_ids.

                 $tag - String - A single tag to be removed.

    Returns:     Array: Empty on success.

    Example:
    # Remove tag 'foo' from plan 1234
    >>> TestPlan.remove_tag(1234, 'foo')
    # Remove tag 'foo' and 'bar' from plan list [56789, 12345]
    >>> TestPlan.remove_tag([56789, 12345], ['foo', 'bar'])
    # Remove tag 'foo' and 'bar' from plan list '56789, 12345' with String
    >>> TestPlan.remove_tag('56789, 12345', 'foo, bar')
    """
    from tcms.management.models import TestTag

    tps = TestPlan.objects.filter(
        plan_id__in=pre_process_ids(value=plan_ids)
    )
    tgs = TestTag.objects.filter(
        name__in=TestTag.string_to_list(tags)
    )

    for tp in tps.iterator():
        for tg in tgs.iterator():
            try:
                tp.remove_tag(tag=tg)
            except ObjectDoesNotExist:
                pass
            except:
                raise

    return
コード例 #34
0
ファイル: testplan.py プロジェクト: jetlyb/Kiwi
def remove_tag(plan_ids, tags):
    """
    Description: Remove a tag from a plan.

    Params:      $plan_ids - Integer/Array/String: An integer or alias representing the ID
                                                   in the database, an array of plan_ids,
                                                   or a string of comma separated plan_ids.

                 $tag - String - A single tag to be removed.

    Returns:     Array: Empty on success.

    Example:
    # Remove tag 'foo' from plan 1234
    >>> TestPlan.remove_tag(1234, 'foo')
    # Remove tag 'foo' and 'bar' from plan list [56789, 12345]
    >>> TestPlan.remove_tag([56789, 12345], ['foo', 'bar'])
    # Remove tag 'foo' and 'bar' from plan list '56789, 12345' with String
    >>> TestPlan.remove_tag('56789, 12345', 'foo, bar')
    """
    from tcms.management.models import TestTag

    test_plans = TestPlan.objects.filter(
        plan_id__in=pre_process_ids(value=plan_ids)
    )

    if not isinstance(tags, (str, list)):
        raise ValueError('Parameter tags must be a string or list(string)')

    test_tags = TestTag.objects.filter(
        name__in=string_to_list(tags)
    )

    for test_plan in test_plans.iterator():
        for test_tag in test_tags.iterator():
            test_plan.remove_tag(tag=test_tag)

    return
コード例 #35
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def notification_get_cc_list(request, case_ids):
    '''
    Description: Return whole CC list of each TestCase

    Params:      $case_ids - Integer/Array: one or more TestCase IDs

    Returns:     An dictionary object with case_id as key and a list of CC as the value
                 Each case_id will be converted to a str object in the result.
    '''

    result = {}

    try:
        tc_ids = pre_process_ids(case_ids)

        for tc in TestCase.objects.filter(pk__in=tc_ids).iterator():
            cc_list = tc.emailing.get_cc_list()
            result[str(tc.pk)] = cc_list

    except (TypeError, ValueError, Exception):
        raise

    return result
コード例 #36
0
ファイル: testcase.py プロジェクト: artjoman/Nitrate
def add_tag(request, case_ids, tags):
    """Add one or more tags to the selected test cases.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param tags: tag name or a list of tag names to remove.
    :type tags: str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.

    Example::

        # Add tag 'foobar' to case 1
        TestCase.add_tag(1, 'foobar')
        # Add tag list ['foo', 'bar'] to cases list [1, 2]
        TestCase.add_tag([1, 2], ['foo', 'bar'])
        # Add tag list ['foo', 'bar'] to cases list [1, 2] with String
        TestCase.add_tag('1, 2', 'foo, bar')
    """
    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids)
    ).only('pk')

    if not tcs.exists():
        return

    tags = TestTag.string_to_list(tags)

    if not tags:
        return

    for tag in tags:
        t, c = TestTag.objects.get_or_create(name=tag)
        for tc in tcs.iterator():
            tc.add_tag(tag=t)
コード例 #37
0
ファイル: testplan.py プロジェクト: jetlyb/Kiwi
def add_tag(plan_ids, tags):
    """
    Description: Add one or more tags to the selected test plans.

    Params:      $plan_ids - Integer/Array/String: An integer representing the ID of the plan
                      in the database,
                      an arry of plan_ids, or a string of comma separated plan_ids.

                  $tags - String/Array - A single tag, an array of tags,
                      or a comma separated list of tags.

    Returns:     Array: empty on success or an array of hashes with failure
                  codes if a failure occured.

    Example:
    # Add tag 'foobar' to plan 1234
    >>> TestPlan.add_tag(1234, 'foobar')
    # Add tag list ['foo', 'bar'] to plan list [12345, 67890]
    >>> TestPlan.add_tag([12345, 67890], ['foo', 'bar'])
    # Add tag list ['foo', 'bar'] to plan list [12345, 67890] with String
    >>> TestPlan.add_tag('12345, 67890', 'foo, bar')
    """
    # FIXME: this could be optimized to reduce possible huge number of SQLs

    tps = TestPlan.objects.filter(plan_id__in=pre_process_ids(value=plan_ids))

    if not isinstance(tags, (str, list)):
        raise ValueError('Parameter tags must be a string or list(string)')

    tags = string_to_list(tags)

    for tag in tags:
        t, c = TestTag.objects.get_or_create(name=tag)
        for tp in tps.iterator():
            tp.add_tag(tag=t)

    return
コード例 #38
0
def remove_tag(request, run_ids, tags):
    """Remove a tag from a run.

    :param run_ids: give one or more run IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a run ID.
    :type run_ids: int, str or list
    :param tags: tag name or a list of tag names to remove.
    :type tags: str or list
    :return: a list which is empty on success.
    :rtype: list

    Example::

        # Remove tag 'foo' from run 1
        >>> TestRun.remove_tag(1, 'foo')
        # Remove tag 'foo' and 'bar' from run list [1, 2]
        >>> TestRun.remove_tag([1, 2], ['foo', 'bar'])
        # Remove tag 'foo' and 'bar' from run list '1, 2' with String
        >>> TestRun.remove_tag('1, 2', 'foo, bar')
    """
    trs = TestRun.objects.filter(
        run_id__in=pre_process_ids(value=run_ids)
    )
    tgs = TestTag.objects.filter(
        name__in=TestTag.string_to_list(tags)
    )

    for tr in trs.iterator():
        for tg in tgs.iterator():
            try:
                tr.remove_tag(tag=tg)
            except ObjectDoesNotExist:
                pass

    return
コード例 #39
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def remove_tag(request, case_ids, tags):
    """
    Description: Remove a tag from a case.

    Params:      $case_ids - Integer/Array/String: An integer or alias representing the ID in the database,
                             an array of case_ids, or a string of comma separated case_ids.

                 $tags - String/Array - A single or multiple tag to be removed.

    Returns:     Array: Empty on success.

    Example:
    # Remove tag 'foo' from case 1234
    >>> TestCase.remove_tag(1234, 'foo')
    # Remove tag 'foo' and bar from cases list [56789, 12345]
    >>> TestCase.remove_tag([56789, 12345], ['foo', 'bar'])
    # Remove tag 'foo' and 'bar' from cases list '56789, 12345' with String
    >>> TestCase.remove_tag('56789, 12345', 'foo, bar')
    """
    tcs = TestCase.objects.filter(
        case_id__in=pre_process_ids(value=case_ids)
    )
    tgs = TestTag.objects.filter(
        name__in=TestTag.string_to_list(tags)
    )

    for tc in tcs.iterator():
        for tg in tgs.iterator():
            try:
                tc.remove_tag(tg)
            except ObjectDoesNotExist:
                pass
            except:
                raise

    return
コード例 #40
0
ファイル: test_utils.py プロジェクト: sugus86/Nitrate
 def test_pre_process_ids_with_list(self):
     ids = U.pre_process_ids(["1", "2", "3"])
     self.assertEqual(ids, [1, 2, 3])
コード例 #41
0
ファイル: test_utils.py プロジェクト: sugus86/Nitrate
    def test_pre_process_ids_with_str(self):
        ids = U.pre_process_ids("1")
        self.assertEqual(ids, [1])

        ids = U.pre_process_ids("1,2,3,4")
        self.assertEqual(ids, [1, 2, 3, 4])
コード例 #42
0
ファイル: test_utils.py プロジェクト: sugus86/Nitrate
 def test_pre_process_ids_with_int(self):
     ids = U.pre_process_ids(1)
     self.assertEqual(ids, [1])
コード例 #43
0
ファイル: testcase.py プロジェクト: jetlyb/Kiwi
def link_plan(case_ids, plan_ids):
    """
    Description: Link test cases to the given plan.

    Params:      $case_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of case_ids, or a string of comma separated case_ids.

                 $plan_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of plan_ids, or a string of comma separated plan_ids.

    Returns:     Array: empty on success or an array of hashes with failure
                        codes if a failure occurs

    Example:
    # Add case 1234 to plan id 54321
    >>> TestCase.link_plan(1234, 54321)
    # Add case ids list [56789, 12345] to plan list [1234, 5678]
    >>> TestCase.link_plan([56789, 12345], [1234, 5678])
    # Add case ids list 56789 and 12345 to plan list 1234 and 5678 with String
    >>> TestCase.link_plan('56789, 12345', '1234, 5678')
    """
    case_ids = pre_process_ids(value=case_ids)
    qs = TestCase.objects.filter(pk__in=case_ids)
    tcs_ids = qs.values_list('pk', flat=True)

    # Check the non-exist case ids.
    ids_diff = set(case_ids) - set(tcs_ids.iterator())
    if ids_diff:
        ids_str = ','.join(map(str, ids_diff))
        if len(ids_diff) > 1:
            err_msg = 'TestCases %s do not exist.' % ids_str
        else:
            err_msg = 'TestCase %s does not exist.' % ids_str
        raise ObjectDoesNotExist(err_msg)

    plan_ids = pre_process_ids(value=plan_ids)
    qs = TestPlan.objects.filter(pk__in=plan_ids)
    tps_ids = qs.values_list('pk', flat=True)

    # Check the non-exist plan ids.
    ids_diff = set(plan_ids) - set(tps_ids.iterator())
    if ids_diff:
        ids_str = ','.join(map(str, ids_diff))
        if len(ids_diff) > 1:
            err_msg = 'TestPlans %s do not exist.' % ids_str
        else:
            err_msg = 'TestPlan %s does not exist.' % ids_str
        raise ObjectDoesNotExist(err_msg)

    # (plan_id, case_id) pair might probably exist in test_case_plans table, so
    # skip the ones that do exist and create the rest.
    # note: this query returns a list of tuples!
    existing = TestCasePlan.objects.filter(plan__in=plan_ids,
                                           case__in=case_ids).values_list(
                                               'plan', 'case')

    # Link the plans to cases
    def _generate_link_plan_value():
        for plan_id in plan_ids:
            for case_id in case_ids:
                if (plan_id, case_id) not in existing:
                    yield plan_id, case_id

    TestCasePlan.objects.bulk_create([
        TestCasePlan(plan_id=_plan_id, case_id=_case_id)
        for _plan_id, _case_id in _generate_link_plan_value()
    ])
コード例 #44
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def update(request, case_ids, values):
    """
    Description: Updates the fields of the selected case or cases.

    Params:      $case_ids - Integer/String/Array
                             Integer: A single TestCase ID.
                             String:  A comma separates string of TestCase IDs for batch
                                      processing.
                             Array:   An array of case IDs for batch mode processing

                 $values   - Hash of keys matching TestCase fields and the new values
                             to set each field to.

    Returns:  Array: an array of case hashes. If the update on any particular
                     case failed, the has will contain a ERROR key and the
                     message as to why it failed.
        +-----------------------+----------------+-----------------------------------------+
        | Field                 | Type           | Null                                    |
        +-----------------------+----------------+-----------------------------------------+
        | case_status           | Integer        | Optional                                |
        | product               | Integer        | Optional(Required if changes category)  |
        | category              | Integer        | Optional                                |
        | priority              | Integer        | Optional                                |
        | default_tester        | String/Integer | Optional(str - user_name, int - user_id)|
        | estimated_time        | String         | Optional(2h30m30s(recommend) or HH:MM:SS|
        | is_automated          | Integer        | Optional(0 - Manual, 1 - Auto, 2 - Both)|
        | is_automated_proposed | Boolean        | Optional                                |
        | script                | String         | Optional                                |
        | arguments             | String         | Optional                                |
        | summary               | String         | Optional                                |
        | requirement           | String         | Optional                                |
        | alias                 | String         | Optional                                |
        | notes                 | String         | Optional                                |
        | extra_link            | String         | Optional(reference link)
        +-----------------------+----------------+-----------------------------------------+

    Example:
    # Update alias to 'tcms' for case 12345 and 23456
    >>> TestCase.update([12345, 23456], {'alias': 'tcms'})
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import UpdateCaseForm

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(values.get('estimated_time'))

    form = UpdateCaseForm(values)

    if values.get('category') and not values.get('product'):
        raise ValueError('Product ID is required for category')

    if values.get('product'):
        form.populate(product_id=values['product'])

    if form.is_valid():
        tcs = TestCase.update(
            case_ids=pre_process_ids(value=case_ids),
            values=form.cleaned_data,
        )
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': tcs.values_list('pk', flat=True)}
    return TestCase.to_xmlrpc(query)
コード例 #45
0
def create(request, values):
    """
    Description: Creates a new Test Run object and stores it in the database.

    Params:      $values - Hash: A reference to a hash with keys and values
                           matching the fields of the test run to be created.
      +-------------------+----------------+-----------+---------------------------------------+
      | Field             | Type           | Null      | Description                           |
      +-------------------+----------------+-----------+---------------------------------------+
      | plan              | Integer        | Required  | ID of test plan                       |
      | build             | Integer/String | Required  | ID of Build                           |
      | manager           | Integer        | Required  | ID of run manager                     |
      | summary           | String         | Required  |                                       |
      | product           | Integer        | Required  | ID of product                         |
      | product_version   | Integer        | Required  | ID of product version                 |
      | default_tester    | Integer        | Optional  | ID of run default tester              |
      | plan_text_version | Integer        | Optional  |                                       |
      | estimated_time    | String         | Optional  | 2h30m30s(recommend) or HH:MM:SS Format|
      | notes             | String         | Optional  |                                       |
      | status            | Integer        | Optional  | 0:RUNNING 1:STOPPED  (default 0)      |
      | case              | Array/String   | Optional  | list of case ids to add to the run    |
      | tag               | Array/String   | Optional  | list of tag to add to the run         |
      +-------------------+----------------+-----------+---------------------------------------+

    Returns:     The newly created object hash.

    Example:
    >>> values = {'build': 384,
        'manager': 137,
        'plan': 137,
        'product': 61,
        'product_version': 93,
        'summary': 'Testing XML-RPC for TCMS',
    }
    >>> TestRun.create(values)
    """
    from datetime import datetime
    from tcms.core import forms
    from tcms.testruns.forms import XMLRPCNewRunForm

    if not values.get('product'):
        raise ValueError('Value of product is required')
    # TODO: XMLRPC only accept HH:MM:SS rather than DdHhMm

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(
            values.get('estimated_time'))

    if values.get('case'):
        values['case'] = pre_process_ids(value=values['case'])

    form = XMLRPCNewRunForm(values)
    form.populate(product_id=values['product'])

    if form.is_valid():
        tr = TestRun.objects.create(
            product_version=form.cleaned_data['product_version'],
            plan_text_version=form.cleaned_data['plan_text_version'],
            stop_date=form.cleaned_data['status'] and datetime.now() or None,
            summary=form.cleaned_data['summary'],
            notes=form.cleaned_data['notes'],
            estimated_time=form.cleaned_data['estimated_time'],
            plan=form.cleaned_data['plan'],
            build=form.cleaned_data['build'],
            manager=form.cleaned_data['manager'],
            default_tester=form.cleaned_data['default_tester'],
        )

        if form.cleaned_data['case']:
            for c in form.cleaned_data['case']:
                tr.add_case_run(case=c)
                del c

        if form.cleaned_data['tag']:
            tags = form.cleaned_data['tag']
            if isinstance(tags, str):
                tags = [c.strip() for c in tags.split(',') if c]

            for tag in tags:
                t, c = TestTag.objects.get_or_create(name=tag)
                tr.add_tag(tag=t)
                del tag, t, c
    else:
        raise ValueError(forms.errors_to_list(form))

    return tr.serialize()
コード例 #46
0
ファイル: testcaserun.py プロジェクト: zumbi/Nitrate
def update(request, case_run_ids, values):
    """Updates the fields of the selected case-runs.

    :param case_run_ids: give one or more case run IDs. It could be an integer,
        a string containing comma separated IDs, or a list of int each of them
        is a case run ID.
    :type run_ids: int, str or list
    :param dict values: a mapping containing these data to update specified
        case runs.

        * build: (int)
        * assignee: (int)
        * case_run_status: (int)
        * notes: (str)
        * sortkey: (int)

    :return: In the case of a single object, it is returned. If a list was
        passed, it returns an array of object hashes. If the update on any
        particular object failed, the hash will contain a ERROR key and the
        message as to why it failed.

    Example::

        # Update alias to 'tcms' for case 12345 and 23456
        >>> TestCaseRun.update([12345, 23456], {'assignee': 2206})
    """
    from datetime import datetime
    from tcms.core import forms
    from tcms.testruns.forms import XMLRPCUpdateCaseRunForm

    pks_to_update = pre_process_ids(case_run_ids)

    tcrs = TestCaseRun.objects.filter(pk__in=pks_to_update)
    form = XMLRPCUpdateCaseRunForm(values)

    if form.is_valid():
        data = {}

        if form.cleaned_data['build']:
            data['build'] = form.cleaned_data['build']

        if form.cleaned_data['assignee']:
            data['assignee'] = form.cleaned_data['assignee']

        if form.cleaned_data['case_run_status']:
            data['case_run_status'] = form.cleaned_data['case_run_status']
            data['tested_by'] = request.user
            data['close_date'] = datetime.now()

        if 'notes' in values:
            if values['notes'] in (None, ''):
                data['notes'] = values['notes']
            if form.cleaned_data['notes']:
                data['notes'] = form.cleaned_data['notes']

        if form.cleaned_data['sortkey'] is not None:
            data['sortkey'] = form.cleaned_data['sortkey']

        tcrs.update(**data)

    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': pks_to_update}
    return TestCaseRun.to_xmlrpc(query)
コード例 #47
0
def update(request, plan_ids, values):
    """
    Description: Updates the fields of the selected test plan.

    Params:      $plan_ids - Integer: A single TestPlan ID.

                 $values - Hash of keys matching TestPlan fields and the new values
                           to set each field to.
      +-------------------------------------------+----------------+--------------------------------------------+
      | Field                                     | Type           | Description                                |
      +-------------------------------------------+----------------+--------------------------------------------+
      | product                                   | Integer        | ID of product                              |
      | name                                      | String         |                                            |
      | type                                      | Integer        | ID of plan type                            |
      | product_version(default_product_version)  | Integer        | ID of version, product_version(recommend), |
      |                                           |                | default_product_version will be deprecated |
      |                                           |                | in future release.                         |
      | owner                                     | String/Integer | user_name/user_id                          |
      | parent                                    | Integer        | Parent plan ID                             |
      | is_active                                 | Boolean        | True/False                                 |
      | env_group                                 | Integer        |                                            |
      +-------------------------+----------------+--------------------------------------------------------------+

    Returns:     Hash: The updated test plan object.

    Example:
    # Update product to 61 for plan 207 and 208
    >>> TestPlan.update([207, 208], {'product': 61})
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import EditPlanForm

    if values.get('default_product_version'):
        values['product_version'] = values.pop('default_product_version')

    form = EditPlanForm(values)

    if values.get('product_version') and not values.get('product'):
        raise ValueError('Field "product" is required by product_version')

    if values.get('product') and not values.get('product_version'):
        raise ValueError('Field "product_version" is required by product')

    if values.get('product_version') and values.get('product'):
        form.populate(product_id=values['product'])

    plan_ids = pre_process_ids(value=plan_ids)
    tps = TestPlan.objects.filter(pk__in=plan_ids)

    if form.is_valid():
        _values = dict()
        if form.cleaned_data['name']:
            _values['name'] = form.cleaned_data['name']

        if form.cleaned_data['type']:
            _values['type'] = form.cleaned_data['type']

        if form.cleaned_data['product']:
            _values['product'] = form.cleaned_data['product']

        if form.cleaned_data['product_version']:
            _values['product_version'] = form.cleaned_data['product_version']

        if form.cleaned_data['owner']:
            _values['owner'] = form.cleaned_data['owner']

        if form.cleaned_data['parent']:
            _values['parent'] = form.cleaned_data['parent']

        if not (values.get('is_active') is None):
            _values['is_active'] = form.cleaned_data['is_active']

        tps.update(**_values)

        if form.cleaned_data['env_group']:
            # NOTE: MyISAM does not support transaction, so no need to use
            # transaction.commit_on_success to control the commit.
            cursor = connection.writer_cursor
            in_condition = ','.join(itertools.repeat('%s', len(plan_ids)))
            del_env_group_sql = TP_CLEAR_ENV_GROUP % in_condition
            cursor.execute(del_env_group_sql, plan_ids)

            insert_values = ','.join(
                itertools.repeat('(%s, %s)', len(plan_ids)))
            insert_env_group_sql = TP_ADD_ENV_GROUP % insert_values
            args = list()
            for arg in itertools.izip(
                    plan_ids,
                    itertools.repeat(form.cleaned_data['env_group'].pk,
                                     len(plan_ids))):
                args.extend(arg)
            cursor.execute(insert_env_group_sql, args)
            transaction.commit_unless_managed()
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': tps.values_list('pk', flat=True)}
    return TestPlan.to_xmlrpc(query)
コード例 #48
0
def update(request, plan_ids, values):
    """Updates the fields of the selected test plan.

    :param plan_ids: give one or more plan IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a plan ID.
    :type plan_ids: int, str or list
    :param dict values: a mapping containing these plan data to update

        * product: (int) ID of product
        * name: (str)
        * type: (int) ID of plan type
        * product_version: (int) ID of version
        * default_product_version: (int) alternative version ID.
        * owner: (str)/(int) user_name/user_id
        * parent: (int) Parent plan ID
        * is_active: bool True/False
        * env_group: (int) New environment group ID

    :return: a mapping of updated :class:`TestPlan`.
    :rtype: dict

    Example::

        # Update product to 7 for plan 1 and 2
        TestPlan.update([1, 2], {'product': 7})

    .. deprecated:: x.y
       ``default_product_version`` is deprecated and will be removed.
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import EditPlanForm

    if values.get('default_product_version'):
        values['product_version'] = values.pop('default_product_version')

    form = EditPlanForm(values)

    if values.get('product_version') and not values.get('product'):
        raise ValueError('Field "product" is required by product_version')

    if values.get('product') and not values.get('product_version'):
        raise ValueError('Field "product_version" is required by product')

    if values.get('product_version') and values.get('product'):
        form.populate(product_id=values['product'])

    plan_ids = pre_process_ids(value=plan_ids)
    tps = TestPlan.objects.filter(pk__in=plan_ids)

    if form.is_valid():
        _values = dict()
        if form.cleaned_data['name']:
            _values['name'] = form.cleaned_data['name']

        if form.cleaned_data['type']:
            _values['type'] = form.cleaned_data['type']

        if form.cleaned_data['product']:
            _values['product'] = form.cleaned_data['product']

        if form.cleaned_data['product_version']:
            _values['product_version'] = form.cleaned_data['product_version']

        if form.cleaned_data['owner']:
            _values['owner'] = form.cleaned_data['owner']

        if form.cleaned_data['parent']:
            _values['parent'] = form.cleaned_data['parent']

        if not (values.get('is_active') is None):
            _values['is_active'] = form.cleaned_data['is_active']

        tps.update(**_values)

        # requested to update environment group for selected test plans
        if form.cleaned_data['env_group']:
            # prepare the list of new objects to be inserted into DB
            new_objects = [
                TCMSEnvPlanMap(plan_id=plan_pk,
                               group_id=form.cleaned_data['env_group'].pk)
                for plan_pk in plan_ids
            ]

            # first delete the old values (b/c many-to-many I presume ?)
            TCMSEnvPlanMap.objects.filter(plan__in=plan_ids).delete()
            # then create all objects with 1 INSERT
            TCMSEnvPlanMap.objects.bulk_create(new_objects)
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': tps.values_list('pk', flat=True)}
    return TestPlan.to_xmlrpc(query)
コード例 #49
0
def update(request, run_ids, values):
    """
    Description: Updates the fields of the selected test run.

    Params:      $run_ids - Integer/Array/String: An integer or alias representing the ID in the database,
                            an array of run_ids, or a string of comma separated run_ids.

                 $values - Hash of keys matching TestRun fields and the new values
                           to set each field to. See params of TestRun.create for description
    +-------------------+----------------+--------------------------------+
    | Field             | Type           | Description                    |
    +-------------------+----------------+--------------------------------+
    | plan              | Integer        | TestPlan.plan_id               |
    | product           | Integer        | Product.id                     |
    | build             | Integer        | Build.id                       |
    | manager           | Integer        | Auth.User.id                   |
    | default_tester    | Intege         | Auth.User.id                   |
    | summary           | String         |                                |
    | estimated_time    | TimeDelta      | 2h30m30s(recommend) or HH:MM:SS|
    | product_version   | Integer        |                                |
    | plan_text_version | Integer        |                                |
    | notes             | String         |                                |
    | status            | Integer        | 0:RUNNING 1:FINISHED           |
    +-------------------+----------------+ -------------------------------+
    Returns:     Hash: The updated test run object.

    Example:
    # Update status to finished for run 1193 and 1194
    >>> TestRun.update([1193, 1194], {'status': 1})
    """
    from datetime import datetime
    from tcms.core import forms
    from tcms.testruns.forms import XMLRPCUpdateRunForm

    if (values.get('product_version') and not values.get('product')):
        raise ValueError('Field "product" is required by product_version')

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(
            values.get('estimated_time'))

    form = XMLRPCUpdateRunForm(values)
    if values.get('product_version'):
        form.populate(product_id=values['product'])

    if form.is_valid():
        trs = TestRun.objects.filter(pk__in=pre_process_ids(value=run_ids))
        _values = dict()
        if form.cleaned_data['plan']:
            _values['plan'] = form.cleaned_data['plan']

        if form.cleaned_data['build']:
            _values['build'] = form.cleaned_data['build']

        if form.cleaned_data['manager']:
            _values['manager'] = form.cleaned_data['manager']

        if 'default_tester' in values:
            if values.get('default_tester') and \
                    form.cleaned_data['default_tester']:
                _values['default_tester'] = form.cleaned_data['default_tester']
            else:
                _values['default_tester'] = None

        if form.cleaned_data['summary']:
            _values['summary'] = form.cleaned_data['summary']

        if values.get('estimated_time') is not None:
            _values['estimated_time'] = form.cleaned_data['estimated_time']

        if form.cleaned_data['product_version']:
            _values['product_version'] = form.cleaned_data['product_version']

        if 'notes' in values:
            if values['notes'] in (None, ''):
                _values['notes'] = values['notes']
            if form.cleaned_data['notes']:
                _values['notes'] = form.cleaned_data['notes']

        if form.cleaned_data['plan_text_version']:
            _values['plan_text_version'] = form.cleaned_data[
                'plan_text_version']

        if isinstance(form.cleaned_data['status'], int):
            if form.cleaned_data['status']:
                _values['stop_date'] = datetime.now()
            else:
                _values['stop_date'] = None

        trs.update(**_values)
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': trs.values_list('pk', flat=True)}
    return TestRun.to_xmlrpc(query)
コード例 #50
0
ファイル: testplan.py プロジェクト: erichuanggit/Nitrate
def update(request, plan_ids, values):
    """
    Description: Updates the fields of the selected test plan.

    Params:      $plan_ids - Integer: A single TestPlan ID.

                 $values - Hash of keys matching TestPlan fields and the new values
                           to set each field to.
       +------------------------+----------------+------------------------------------+
      | Field                   | Type           | Description                        |
      +-------------------------+----------------+------------------------------------+
      | product                 | Integer        | ID of product                      |
      | name                    | String         |                                    |
      | type                    | Integer        | ID of plan type                    |
      | default_product_version | Integer        |                                    |
      | parent                  | Integer        | Parent plan ID                     |
      | is_active               | Boolean        | True/False                         |
      | env_group               | Integer        |                                    |
      +-------------------------+----------------+------------------------------------+

    Returns:     Hash: The updated test plan object.

    Example:
    # Update product to 61 for plan 207 and 208
    >>> TestPlan.update([207, 208], {'product': 61})
    """
    from tcms.core import forms
    from tcms.apps.testplans.forms import XMLRPCEditPlanForm

    if values.get('is_active') in (False, True):
        if values.get('is_active') == False:
            values['is_active'] = 0
        else:
            values['is_active'] = 1

    form = XMLRPCEditPlanForm(values)
    if values.get('default_product_version') and not values.get('product'):
        raise ValueError(
            'Product value is required by default product version')

    if values.get('default_product_version') and values.get('product'):
        form.populate(product_id=values['product'])

    tps = TestPlan.objects.filter(pk__in=pre_process_ids(value=plan_ids))

    if form.is_valid():
        _values = dict()
        if form.cleaned_data['name']:
            _values['name'] = form.cleaned_data['name']

        if form.cleaned_data['type']:
            _values['type'] = form.cleaned_data['type']

        if form.cleaned_data['product']:
            _values['product'] = form.cleaned_data['product']

        if form.cleaned_data['default_product_version']:
            _values['default_product_version'] = form.cleaned_data[
                'default_product_version']

        if form.cleaned_data['parent']:
            _values['parent'] = form.cleaned_data['parent']

        if isinstance(form.cleaned_data['is_active'], int):
            _values['is_active'] = form.cleaned_data['is_active']

        tps.update(**_values)

        if form.cleaned_data['env_group']:
            for tp in tps.iterator():
                tp.clear_env_groups()
                tp.add_env_group(form.cleaned_data['env_group'])
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': tps.values_list('pk', flat=True)}
    return TestPlan.to_xmlrpc(query)
コード例 #51
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def create(request, values):
    """
    Description: Creates a new Test Case object and stores it in the database.

    Params:      $values - Array/Hash: A reference to a hash or array of hashes with keys and values
                 matching the fields of the test case to be created.
      +----------------------------+----------------+-----------+---------------------------------------+
      | Field                      | Type           | Null      | Description                           |
      +----------------------------+----------------+-----------+---------------------------------------+
      | product                    | Integer        | Required  | ID of Product                         |
      | category                   | Integer        | Required  | ID of Category                        |
      | priority                   | Integer        | Required  | ID of Priority                        |
      | summary                    | String         | Required  |                                       |
      | case_status                | Integer        | Optional  | ID of case status                     |
      | plan                       | Array/Str/Int  | Optional  | ID or List of plan_ids                |
      | component                  | Integer/String | Optional  | ID of Priority                        |
      | default_tester             | String         | Optional  | Login of tester                       |
      | estimated_time             | String         | Optional  | 2h30m30s(recommend) or HH:MM:SS Format|
      | is_automated               | Integer        | Optional  | 0: Manual, 1: Auto, 2: Both           |
      | is_automated_proposed      | Boolean        | Optional  | Default 0                             |
      | script                     | String         | Optional  |                                       |
      | arguments                  | String         | Optional  |                                       |
      | requirement                | String         | Optional  |                                       |
      | alias                      | String         | Optional  | Must be unique                        |
      | action                     | String         | Optional  |                                       |
      | effect                     | String         | Optional  | Expected Result                       |
      | setup                      | String         | Optional  |                                       |
      | breakdown                  | String         | Optional  |                                       |
      | tag                        | Array/String   | Optional  | String Comma separated                |
      | bug                        | Array/String   | Optional  | String Comma separated                |
      | extra_link                 | String         | Optional  | reference link                        |
      +----------------------------+----------------+-----------+---------------------------------------+

    Returns:     Array/Hash: The newly created object hash if a single case was created, or
                             an array of objects if more than one was created. If any single case threw an
                             error during creation, a hash with an ERROR key will be set in its place.

    Example:
    # Minimal test case parameters
    >>> values = {
        'category': 135,
        'product': 61,
        'summary': 'Testing XML-RPC',
        'priority': 1,
    }
    >>> TestCase.create(values)
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import NewCaseForm

    if not (values.get('category') or values.get('summary')):
        raise ValueError()

    values['component'] = pre_process_ids(values.get('component', []))
    values['plan'] = pre_process_ids(values.get('plan', []))
    values['bug'] = pre_process_ids(values.get('bug', []))
    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(values.get('estimated_time'))

    form = NewCaseForm(values)
    form.populate(values.get('product'))

    if form.is_valid():
        # Create the case
        tc = TestCase.create(author=request.user, values=form.cleaned_data)

        # Add case text to the case
        tc.add_text(
            action=form.cleaned_data['action'] or '',
            effect=form.cleaned_data['effect'] or '',
            setup=form.cleaned_data['setup'] or '',
            breakdown=form.cleaned_data['breakdown'] or '',
        )

        # Add the case to specific plans
        for p in form.cleaned_data['plan']:
            tc.add_to_plan(plan=p)
            del p

        # Add components to the case
        for c in form.cleaned_data['component']:
            tc.add_component(component=c)
            del c

        # Add tag to the case
        for tag in TestTag.string_to_list(values.get('tag', [])):
            t, c = TestTag.objects.get_or_create(name=tag)
            tc.add_tag(tag=t)
    else:
        # Print the errors if the form is not passed validation.
        raise ValueError(forms.errors_to_list(form))

    return get(request, tc.case_id)
コード例 #52
0
def update(request, case_ids, values):
    """Updates the fields of the selected case or cases.

                 $values   - Hash of keys matching TestCase fields and the new values
                             to set each field to.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param dict values: a mapping containing these case data to update.

        * case_status: (ini) optional
        * product: (ini) optional (Required if changes category)
        * category: (ini) optional
        * priority: (ini) optional
        * default_tester: (str or int) optional (str - user_name, int - user_id)
        * estimated_time: (str) optional (2h30m30s(recommend) or HH:MM:SS
        * is_automated: (ini) optional (0 - Manual, 1 - Auto, 2 - Both)
        * is_automated_proposed: (bool) optional
        * script: (str) optional
        * arguments: (str) optional
        * summary: (str) optional
        * requirement: (str) optional
        * alias: (str) optional
        * notes: (str) optional
        * extra_link: (str) optional (reference link)

    :return: a list of mappings of updated :class:`TestCase`.
    :rtype: list(dict)

    Example::

        # Update alias to 'tcms' for case 1 and 2
        >>> TestCase.update([1, 2], {'alias': 'tcms'})
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import UpdateCaseForm

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(
            values.get('estimated_time'))

    form = UpdateCaseForm(values)

    if values.get('category') and not values.get('product'):
        raise ValueError('Product ID is required for category')

    if values.get('product'):
        form.populate(product_id=values['product'])

    if form.is_valid():
        tcs = TestCase.update(
            case_ids=pre_process_ids(value=case_ids),
            values=form.cleaned_data,
        )
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': tcs.values_list('pk', flat=True)}
    return TestCase.to_xmlrpc(query)
コード例 #53
0
ファイル: testcase.py プロジェクト: artjoman/Nitrate
def create(request, values):
    """Creates a new Test Case object and stores it in the database.

    :param values: a mapping or list of mappings containing these case
        information for creation.

        * product: (int) **Required** ID of Product
        * category: (int) **Required** ID of Category
        * priority: (int) **Required** ID of Priority
        * summary: (str) **Required**
        * case_status: (int) optional ID of case status
        * plan Array/Str/Int optional ID or List of plan_ids
        * component: (int)/str optional ID of Priority
        * default_tester: (str) optional Login of tester
        * estimated_time: (str) optional 2h30m30s(recommend) or HH:MM:SS Format|
        * is_automated: (int) optional 0: Manual, 1: Auto, 2: Both
        * is_automated_proposed: (bool) optional Default 0
        * script: (str) optional
        * arguments: (str) optional
        * requirement: (str) optional
        * alias: (str) optional Must be unique
        * action: (str) optional
        * effect: (str) optional Expected Result
        * setup: (str) optional
        * breakdown: (str) optional
        * tag Array/str optional String Comma separated
        * bug Array/str optional String Comma separated
        * extra_link: (str) optional reference link

    :return: a mapping of newly created test case if a single case was created,
        or a list of mappings of created cases if more than one are created.
    :rtype: dict of list[dict]

    Example::

        # Minimal test case parameters
        values = {
            'category': 1,
            'product': 1,
            'summary': 'Testing XML-RPC',
            'priority': 1,
        }
        TestCase.create(values)
    """
    from tcms.core import forms
    from tcms.xmlrpc.forms import NewCaseForm

    if not (values.get('category') or values.get('summary')):
        raise ValueError()

    values['component'] = pre_process_ids(values.get('component', []))
    values['plan'] = pre_process_ids(values.get('plan', []))
    values['bug'] = pre_process_ids(values.get('bug', []))
    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(values.get('estimated_time'))

    form = NewCaseForm(values)
    form.populate(values.get('product'))

    if form.is_valid():
        # Create the case
        tc = TestCase.create(author=request.user, values=form.cleaned_data)

        # Add case text to the case
        tc.add_text(
            action=form.cleaned_data['action'] or '',
            effect=form.cleaned_data['effect'] or '',
            setup=form.cleaned_data['setup'] or '',
            breakdown=form.cleaned_data['breakdown'] or '',
        )

        # Add the case to specific plans
        for p in form.cleaned_data['plan']:
            tc.add_to_plan(plan=p)
            del p

        # Add components to the case
        for c in form.cleaned_data['component']:
            tc.add_component(component=c)
            del c

        # Add tag to the case
        for tag in TestTag.string_to_list(values.get('tag', [])):
            t, c = TestTag.objects.get_or_create(name=tag)
            tc.add_tag(tag=t)
    else:
        # Print the errors if the form is not passed validation.
        raise ValueError(forms.errors_to_list(form))

    return get(request, tc.case_id)
コード例 #54
0
ファイル: testcaserun.py プロジェクト: zhangqiusheng/Nitrate
def update(request, case_run_ids, values):
    """
    Description: Updates the fields of the selected case-runs.

    Params:      $caserun_ids - Integer/String/Array
                        Integer: A single TestCaseRun ID.
                        String:  A comma separates string of TestCaseRun IDs for batch
                                 processing.
                        Array:   An array of TestCaseRun IDs for batch mode processing

                 $values - Hash of keys matching TestCaseRun fields and the new values
                 to set each field to.
                         +--------------------+----------------+
                         | Field              | Type           |
                         +--------------------+----------------+
                         | build              | Integer        |
                         | assignee           | Integer        |
                         | case_run_status    | Integer        |
                         | notes              | String         |
                         | sortkey            | Integer        |
                         +--------------------+----------------+

    Returns:     Hash/Array: In the case of a single object, it is returned. If a
                 list was passed, it returns an array of object hashes. If the
                 update on any particular object failed, the hash will contain a
                 ERROR key and the message as to why it failed.

    Example:
    # Update alias to 'tcms' for case 12345 and 23456
    >>> TestCaseRun.update([12345, 23456], {'assignee': 2206})
    """
    from datetime import datetime
    from tcms.core import forms
    from tcms.testruns.forms import XMLRPCUpdateCaseRunForm

    pks_to_update = pre_process_ids(case_run_ids)

    tcrs = TestCaseRun.objects.filter(pk__in=pks_to_update)
    form = XMLRPCUpdateCaseRunForm(values)

    if form.is_valid():
        data = {}

        if form.cleaned_data['build']:
            data['build'] = form.cleaned_data['build']

        if form.cleaned_data['assignee']:
            data['assignee'] = form.cleaned_data['assignee']

        if form.cleaned_data['case_run_status']:
            data['case_run_status'] = form.cleaned_data['case_run_status']
            data['tested_by'] = request.user
            data['close_date'] = datetime.now()

        if 'notes' in values:
            if values['notes'] in (None, ''):
                data['notes'] = values['notes']
            if form.cleaned_data['notes']:
                data['notes'] = form.cleaned_data['notes']

        if form.cleaned_data['sortkey'] is not None:
            data['sortkey'] = form.cleaned_data['sortkey']

        tcrs.update(**data)

    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': pks_to_update}
    return TestCaseRun.to_xmlrpc(query)
コード例 #55
0
ファイル: testcase.py プロジェクト: Aaln1986/Nitrate
def link_plan(request, case_ids, plan_ids):
    """"
    Description: Link test cases to the given plan.

    Params:      $case_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of case_ids, or a string of comma separated case_ids.

                 $plan_ids - Integer/Array/String: An integer representing the ID in the database,
                             an array of plan_ids, or a string of comma separated plan_ids.

    Returns:     Array: empty on success or an array of hashes with failure
                        codes if a failure occurs

    Example:
    # Add case 1234 to plan id 54321
    >>> TestCase.link_plan(1234, 54321)
    # Add case ids list [56789, 12345] to plan list [1234, 5678]
    >>> TestCase.link_plan([56789, 12345], [1234, 5678])
    # Add case ids list 56789 and 12345 to plan list 1234 and 5678 with String
    >>> TestCase.link_plan('56789, 12345', '1234, 5678')
    """
    case_ids = pre_process_ids(value=case_ids)
    qs = TestCase.objects.filter(pk__in=case_ids)
    tcs_ids = qs.values_list('pk', flat=True)

    # Check the non-exist case ids.
    ids_diff = set(case_ids) - set(tcs_ids.iterator())
    if ids_diff:
        ids_str = ','.join(imap(str, ids_diff))
        if len(ids_diff) > 1:
            err_msg = 'TestCases %s do not exist.' % ids_str
        else:
            err_msg = 'TestCase %s does not exist.' % ids_str
        raise ObjectDoesNotExist(err_msg)

    plan_ids = pre_process_ids(value=plan_ids)
    qs = TestPlan.objects.filter(pk__in=plan_ids)
    tps_ids = qs.values_list('pk', flat=True)

    # Check the non-exist plan ids.
    ids_diff = set(plan_ids) - set(tps_ids.iterator())
    if ids_diff:
        ids_str = ','.join(imap(str, ids_diff))
        if len(ids_diff) > 1:
            err_msg = 'TestPlans %s do not exist.' % ids_str
        else:
            err_msg = 'TestPlan %s does not exist.' % ids_str
        raise ObjectDoesNotExist(err_msg)

    # Link the plans to cases
    def _generate_link_plan_value():
        for plan_id in plan_ids:
            for case_id in case_ids:
                yield plan_id, case_id

    # (plan_id, case_id) pair might probably exist in test_case_plans table, so
    # IGNORE tell MySQL to insert other non-exist ones without error report
    # that will break whole INSERT INTO operation.
    sql = 'INSERT IGNORE INTO test_case_plans (plan_id, case_id) VALUES\n%s'
    sql = sql % ',\n'.join(str(value) for value in _generate_link_plan_value())
    cursor = connection.writer_cursor
    cursor.execute(sql)
    transaction.commit_unless_managed()
コード例 #56
0
ファイル: testcase.py プロジェクト: artjoman/Nitrate
def link_plan(request, case_ids, plan_ids):
    """"Link test cases to the given plan.

    :param case_ids: give one or more case IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a case ID.
    :type case_ids: int, str or list
    :param plan_ids: give one or more plan IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a plan ID.
    :type plan_ids: int, str or list
    :return: a list which is empty on success or a list of mappings with
        failure codes if a failure occured.
    :rtype: list or list[dict]

    Example::

        # Add case 1 to plan id 2
        TestCase.link_plan(1, 2)
        # Add case ids list [1, 2] to plan list [3, 4]
        TestCase.link_plan([1, 2], [3, 4])
        # Add case ids list 1 and 2 to plan list 3 and 4 with String
        TestCase.link_plan('1, 2', '3, 4')
    """
    case_ids = pre_process_ids(value=case_ids)
    qs = TestCase.objects.filter(pk__in=case_ids)
    tcs_ids = qs.values_list('pk', flat=True)

    # Check the non-exist case ids.
    ids_diff = set(case_ids) - set(tcs_ids.iterator())
    if ids_diff:
        ids_str = ','.join(map(str, ids_diff))
        if len(ids_diff) > 1:
            err_msg = 'TestCases %s do not exist.' % ids_str
        else:
            err_msg = 'TestCase %s does not exist.' % ids_str
        raise ObjectDoesNotExist(err_msg)

    plan_ids = pre_process_ids(value=plan_ids)
    qs = TestPlan.objects.filter(pk__in=plan_ids)
    tps_ids = qs.values_list('pk', flat=True)

    # Check the non-exist plan ids.
    ids_diff = set(plan_ids) - set(tps_ids.iterator())
    if ids_diff:
        ids_str = ','.join(map(str, ids_diff))
        if len(ids_diff) > 1:
            err_msg = 'TestPlans %s do not exist.' % ids_str
        else:
            err_msg = 'TestPlan %s does not exist.' % ids_str
        raise ObjectDoesNotExist(err_msg)

    # (plan_id, case_id) pair might probably exist in test_case_plans table, so
    # skip the ones that do exist and create the rest.
    # note: this query returns a list of tuples!
    existing = TestCasePlan.objects.filter(
        plan__in=plan_ids,
        case__in=case_ids
    ).values_list('plan', 'case')

    # Link the plans to cases
    def _generate_link_plan_value():
        for plan_id in plan_ids:
            for case_id in case_ids:
                if (plan_id, case_id) not in existing:
                    yield plan_id, case_id

    TestCasePlan.objects.bulk_create([
        TestCasePlan(plan_id=_plan_id, case_id=_case_id)
        for _plan_id, _case_id in _generate_link_plan_value()
    ])
コード例 #57
0
ファイル: testrun.py プロジェクト: sugus86/Nitrate
def create(request, values):
    """Creates a new Test Run object and stores it in the database.

    :param dict values: a mapping containing these data to create a test run.

        * plan: (int) **Required** ID of test plan
        * build: (int)/(str) **Required** ID of Build
        * manager: (int) **Required** ID of run manager
        * summary: (str) **Required**
        * product: (int) **Required** ID of product
        * product_version: (int) **Required** ID of product version
        * default_tester: (int) optional ID of run default tester
        * plan_text_version: (int) optional
        * estimated_time: (str) optional, could be in format ``2h30m30s``, which is recommended or ``HH:MM:SS``.
        * notes: (str) optional
        * status: (int) optional 0:RUNNING 1:STOPPED  (default 0)
        * case: list or (str) optional list of case ids to add to the run
        * tag: list or (str) optional list of tag to add to the run

    :return: a mapping representing newly created :class:`TestRun`.
    :rtype: dict

    .. versionchanged:: 4.5
       Argument ``errata_id`` is removed.

    Example::

        values = {
            'build': 2,
            'manager': 1,
            'plan': 1,
            'product': 1,
            'product_version': 2,
            'summary': 'Testing XML-RPC for TCMS',
        }
        TestRun.create(values)
    """
    from datetime import datetime
    from tcms.core import forms
    from tcms.testruns.forms import XMLRPCNewRunForm

    if not values.get('product'):
        raise ValueError('Value of product is required')
    # TODO: XMLRPC only accept HH:MM:SS rather than DdHhMm

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(
            values.get('estimated_time'))

    if values.get('case'):
        values['case'] = pre_process_ids(value=values['case'])

    form = XMLRPCNewRunForm(values)
    form.populate(product_id=values['product'])

    if form.is_valid():
        tr = TestRun.objects.create(
            product_version=form.cleaned_data['product_version'],
            plan_text_version=form.cleaned_data['plan_text_version'],
            stop_date=form.cleaned_data['status'] and datetime.now() or None,
            summary=form.cleaned_data['summary'],
            notes=form.cleaned_data['notes'],
            estimated_time=form.cleaned_data['estimated_time'],
            plan=form.cleaned_data['plan'],
            build=form.cleaned_data['build'],
            manager=form.cleaned_data['manager'],
            default_tester=form.cleaned_data['default_tester'],
        )

        if form.cleaned_data['case']:
            for c in form.cleaned_data['case']:
                tr.add_case_run(case=c)
                del c

        if form.cleaned_data['tag']:
            tags = form.cleaned_data['tag']
            if isinstance(tags, str):
                tags = [c.strip() for c in tags.split(',') if c]

            for tag in tags:
                t, c = TestTag.objects.get_or_create(name=tag)
                tr.add_tag(tag=t)
                del tag, t, c
    else:
        raise ValueError(forms.errors_to_list(form))

    return tr.serialize()
コード例 #58
0
ファイル: testrun.py プロジェクト: sugus86/Nitrate
def update(request, run_ids, values):
    """Updates the fields of the selected test run.

    :param run_ids: give one or more run IDs. It could be an integer, a
        string containing comma separated IDs, or a list of int each of them is
        a run ID.
    :type run_ids: int, str or list
    :param dict values: a mapping containing these data to update specified
        runs.

        * plan: (int) TestPlan.plan_id
        * product: (int) Product.id
        * build: (int) Build.id
        * manager: (int) Auth.User.id
        * default_tester: Intege Auth.User.id
        * summary: (str)
        * estimated_time: (TimeDelta) in format ``2h30m30s`` which is recommended or ``HH:MM:SS``.
        * product_version: (int)
        * plan_text_version: (int)
        * notes: (str)
        * status: (int) 0:RUNNING 1:FINISHED

    :return: list of mappings of the updated test runs.
    :rtype: list[dict]

    .. versionchanged:: 4.5
       Argument ``errata_id`` is removed.

    Example::

        # Update status to finished for run 1 and 2
        TestRun.update([1, 2], {'status': 1})
    """
    from datetime import datetime
    from tcms.core import forms
    from tcms.testruns.forms import XMLRPCUpdateRunForm

    if (values.get('product_version') and not values.get('product')):
        raise ValueError('Field "product" is required by product_version')

    if values.get('estimated_time'):
        values['estimated_time'] = pre_process_estimated_time(
            values.get('estimated_time'))

    form = XMLRPCUpdateRunForm(values)
    if values.get('product_version'):
        form.populate(product_id=values['product'])

    if form.is_valid():
        trs = TestRun.objects.filter(pk__in=pre_process_ids(value=run_ids))
        _values = dict()
        if form.cleaned_data['plan']:
            _values['plan'] = form.cleaned_data['plan']

        if form.cleaned_data['build']:
            _values['build'] = form.cleaned_data['build']

        if form.cleaned_data['manager']:
            _values['manager'] = form.cleaned_data['manager']

        if 'default_tester' in values:
            default_tester = form.cleaned_data['default_tester']
            if values.get('default_tester') and default_tester:
                _values['default_tester'] = default_tester
            else:
                _values['default_tester'] = None

        if form.cleaned_data['summary']:
            _values['summary'] = form.cleaned_data['summary']

        if values.get('estimated_time') is not None:
            _values['estimated_time'] = form.cleaned_data['estimated_time']

        if form.cleaned_data['product_version']:
            _values['product_version'] = form.cleaned_data['product_version']

        if 'notes' in values:
            if values['notes'] in (None, ''):
                _values['notes'] = values['notes']
            if form.cleaned_data['notes']:
                _values['notes'] = form.cleaned_data['notes']

        if form.cleaned_data['plan_text_version']:
            _values['plan_text_version'] = form.cleaned_data[
                'plan_text_version']

        if isinstance(form.cleaned_data['status'], int):
            if form.cleaned_data['status']:
                _values['stop_date'] = datetime.now()
            else:
                _values['stop_date'] = None

        trs.update(**_values)
    else:
        raise ValueError(forms.errors_to_list(form))

    query = {'pk__in': trs.values_list('pk', flat=True)}
    return TestRun.to_xmlrpc(query)
コード例 #59
0
ファイル: testplan.py プロジェクト: jetlyb/Kiwi
def update(plan_ids, values):
    """
    Description: Updates the fields of the selected test plan.

    Params:      $plan_ids - Integer: A single (or list of) TestPlan ID.

                 $values - Hash of keys matching TestPlan fields and the new values
                           to set each field to.
      +---------------------------+----------------+--------------------------------------------+
      | Field                     | Type           | Description                                |
      +---------------------------+----------------+--------------------------------------------+
      | product                   | Integer        | ID of product                              |
      | name                      | String         |                                            |
      | type                      | Integer        | ID of plan type                            |
      | product_version           | Integer        | ID of version, product_version(recommend), |
      |  (default_product_version)|                | default_product_version will be deprecated |
      |                           |                | in future release.                         |
      | owner                     | String/Integer | user_name/user_id                          |
      | parent                    | Integer        | Parent plan ID                             |
      | is_active                 | Boolean        | True/False                                 |
      | env_group                 | Integer        | New environment group ID                   |
      +---------------------------+-------------------------------------------------------------+

    Returns:     Hash: The updated test plan object.

    Example:
    # Update product to 61 for plan 207 and 208
    >>> TestPlan.update([207, 208], {'product': 61})
    """
    from tcms.xmlrpc.forms import EditPlanForm

    if values.get('default_product_version'):
        values['product_version'] = values.pop('default_product_version')

    form = EditPlanForm(values)

    if values.get('product_version') and not values.get('product'):
        raise ValueError('Field "product" is required by product_version')

    if values.get('product') and not values.get('product_version'):
        raise ValueError('Field "product_version" is required by product')

    if values.get('product_version') and values.get('product'):
        form.populate(product_id=values['product'])

    plan_ids = pre_process_ids(value=plan_ids)
    tps = TestPlan.objects.filter(pk__in=plan_ids)

    if form.is_valid():
        _values = dict()
        if form.cleaned_data['name']:
            _values['name'] = form.cleaned_data['name']

        if form.cleaned_data['type']:
            _values['type'] = form.cleaned_data['type']

        if form.cleaned_data['product']:
            _values['product'] = form.cleaned_data['product']

        if form.cleaned_data['product_version']:
            _values['product_version'] = form.cleaned_data[
                'product_version']

        if form.cleaned_data['owner']:
            _values['owner'] = form.cleaned_data['owner']

        if form.cleaned_data['parent']:
            _values['parent'] = form.cleaned_data['parent']

        if not (values.get('is_active') is None):
            _values['is_active'] = form.cleaned_data['is_active']

        tps.update(**_values)

        # requested to update environment group for selected test plans
        if form.cleaned_data['env_group']:
            # prepare the list of new objects to be inserted into DB
            new_objects = [
                TCMSEnvPlanMap(
                    plan_id=plan_pk,
                    group_id=form.cleaned_data['env_group'].pk
                ) for plan_pk in plan_ids
            ]

            # first delete the old values (b/c many-to-many I presume ?)
            TCMSEnvPlanMap.objects.filter(plan__in=plan_ids).delete()
            # then create all objects with 1 INSERT
            TCMSEnvPlanMap.objects.bulk_create(new_objects)
    else:
        raise ValueError(form_errors_to_list(form))

    query = {'pk__in': tps.values_list('pk', flat=True)}
    return TestPlan.to_xmlrpc(query)
コード例 #60
0
    def test_pre_process_ids_with_others(self):
        with self.assertRaisesRegex(TypeError, 'Unrecognizable type of ids'):
            U.pre_process_ids((1,))

        with self.assertRaisesRegex(TypeError, 'Unrecognizable type of ids'):
            U.pre_process_ids({'a': 1})