Exemple #1
0
    def filter_plans(self):
        search_form = SearchPlanForm(self.request.GET)
        product_id = self.request.GET.get('product')
        search_form.populate(int(product_id) if product_id else None)

        plans = TestPlan.objects.none()

        if search_form.is_valid():
            # Determine the query is the user's plans and change the sub module value
            author = self.request.GET.get('author__email__startswith')
            req_user = self.request.user
            if req_user.is_authenticated and author in (req_user.username,
                                                        req_user.email):
                self.SUB_MODULE_NAME = "my_plans"

            plans = (TestPlan.list(search_form.cleaned_data).select_related(
                'author', 'type', 'product').order_by('-create_date'))

            plans = TestPlan.apply_subtotal(
                plans,
                cases_count=True,
                runs_count=True,
                children_count=True,
            )

        return search_form, plans
    def test_to_xmlrpc(self):
        result = TestPlan.to_xmlrpc(query={'pk__in': self.plan_pks})
        self.assertEqual(len(result), 2)

        # Verify fields
        sample_testplan = result[0]
        sample_fields = set(name for name in sample_testplan.keys())
        test_fields = set(self.test_fields)
        test_result = list(sample_fields ^ test_fields)
        self.assertEqual(test_result, [])

        result = dict([(item['plan_id'], item) for item in result])

        plan = result[self.plan_pks[0]]
        sample_plan = TestPlan.objects.get(pk=self.plan_pks[0])

        self.assertEqual(plan['name'], sample_plan.name)
        self.assertEqual(plan['is_active'], sample_plan.is_active)
        self.assertEqual(plan['product_version_id'],
                         sample_plan.product_version_id)

        components = plan['component']
        components.sort()
        sample_components = [item.pk for item in sample_plan.component.all()]
        sample_components.sort()
        self.assertEqual(components, sample_components)

        plan = result[self.plan_pks[1]]
        sample_plan = TestPlan.objects.get(pk=self.plan_pks[1])

        self.assertEqual(plan['name'], sample_plan.name)
        self.assertEqual(plan['is_active'], sample_plan.is_active)
        self.assertEqual(plan['product_version_id'],
                         sample_plan.product_version_id)
Exemple #3
0
    def generate_status_matrix(build_ids):
        matrix_dataset = {}
        # TODO: replace defaultdict with GroupByResult
        status_total_line = defaultdict(int)

        rows = TestCaseRun.objects.filter(build__in=build_ids).values(
            'run__plan', 'run__plan__name', 'run', 'run__summary',
            'case_run_status__name').annotate(
                total_count=Count('pk')).order_by('run__plan', 'run')

        for row in rows:
            plan_id = row['run__plan']
            plan_name = row['run__plan__name']
            run_id = row['run']
            run_summary = row['run__summary']
            status_name = row['case_run_status__name']
            status_count = row['total_count']

            plan = TestPlan(pk=plan_id, name=plan_name)
            plan_node = matrix_dataset.setdefault(plan, {})

            run = TestRun(pk=run_id, summary=run_summary)
            run_node = plan_node.setdefault(run, defaultdict(int))

            run_node[status_name] = status_count
            run_node['TOTAL'] += status_count

            # calculate the last total line
            status_total_line[status_name] += status_count
            status_total_line['TOTAL'] += status_count

        # Add total line to final data set
        matrix_dataset[None] = status_total_line
        return matrix_dataset
Exemple #4
0
    def status_matrix(self, form):
        status_matrix = GroupByResult()
        query = self._filter_query(
            form,
            TestCaseRun.objects.values(
                'run__plan',
                'run__plan__name',
                'case_run_status__name'
            ).filter(
                case_run_status__name__in=('PASSED', 'FAILED')
            ).annotate(
                total_count=Count('run', distinct=True)
            )
        )

        for row in query:
            plan_id = row['run__plan']
            plan_name = row['run__plan__name']
            status_name = row['case_run_status__name']
            total_count = row['total_count']
            plan = TestPlan(pk=plan_id, name=plan_name)
            status_subtotal = status_matrix.setdefault(plan, GroupByResult())
            status_subtotal[status_name] = total_count

        return status_matrix
Exemple #5
0
    def status_matrix(self, form):
        status_matrix = GroupByResult()
        query = self._filter_query(
            form,
            TestCaseRun.objects.values(
                'build', 'build__name', 'run__plan__tag', 'run__plan',
                'run__plan__name', 'run', 'run__summary',
                'case_run_status__name').annotate(total_count=Count('pk')))

        for row in query:
            tag_id = row['run__plan__tag']
            build_id = row['build']
            build_name = row['build__name']
            plan_id = row['run__plan']
            plan_name = row['run__plan__name']
            run_id = row['run']
            run_summary = row['run__summary']
            status_name = row['case_run_status__name']
            total_count = row['total_count']

            builds = status_matrix.setdefault(tag_id, GroupByResult())
            plans = builds.setdefault(Build(pk=build_id, name=build_name),
                                      GroupByResult())
            runs = plans.setdefault(TestPlan(pk=plan_id, name=plan_name),
                                    GroupByResult())
            status_subtotal = runs.setdefault(
                TestRun(pk=run_id, summary=run_summary), GroupByResult())
            status_subtotal[status_name] = total_count

        return status_matrix
Exemple #6
0
    def generate_status_matrix(self, build_ids):
        matrix_dataset = {}
        # TODO: replace defaultdict with GroupByResult
        status_total_line = defaultdict(int)

        rows = SQLExecution(sqls.custom_details_status_matrix,
                            params=(build_ids,),
                            with_field_name=False).rows

        for row in rows:
            plan_id, plan_name, run_id, run_summary, \
                status_name, status_count = row
            plan = TestPlan(pk=plan_id, name=plan_name)
            plan_node = matrix_dataset.setdefault(plan, {})

            run = TestRun(pk=run_id, summary=run_summary)
            run_node = plan_node.setdefault(run, defaultdict(int))

            run_node[status_name] = status_count
            run_node['TOTAL'] += status_count

            # calculate the last total line
            status_total_line[status_name] += status_count
            status_total_line['TOTAL'] += status_count

        # Add total line to final data set
        matrix_dataset[None] = status_total_line
        return matrix_dataset
Exemple #7
0
def filter(request, values={}):
    """Performs a search and returns the resulting list of test plans.

    :param dict values: a mapping containing these criteira.

        * author: ForeignKey: Auth.User
        * attachment: ForeignKey: Attachment
        * case: ForeignKey: TestCase
        * create_date: DateTime
        * env_group: ForeignKey: Environment Group
        * name: (str)
        * plan_id: (int)
        * product: ForeignKey: Product
        * product_version: ForeignKey: Version
        * tag: ForeignKey: TestTag
        * text: ForeignKey: Test Plan Text
        * type: ForeignKey: Test Plan Type

    :return: list of mappings of found :class:`TestPlan`.
    :rtype: list[dict]

    Example::

        # Get all of plans contain 'TCMS' in name
        >>> TestPlan.filter({'name__icontain': 'TCMS'})
        # Get all of plans create by xkuang
        >>> TestPlan.filter({'author__username': '******'})
        # Get all of plans the author name starts with x
        >>> TestPlan.filter({'author__username__startswith': 'x'})
        # Get plans contain the case ID 1, 2, 3
        >>> TestPlan.filter({'case__case_id__in': [1, 2, 3]})
    """
    return TestPlan.to_xmlrpc(values)
Exemple #8
0
def filter(request, values={}):
    """Performs a search and returns the resulting list of test plans.

    :param dict values: a mapping containing these criteira.

        * author: ForeignKey: Auth.User
        * attachment: ForeignKey: Attachment
        * case: ForeignKey: TestCase
        * create_date: DateTime
        * env_group: ForeignKey: Environment Group
        * name: (str)
        * plan_id: (int)
        * product: ForeignKey: Product
        * product_version: ForeignKey: Version
        * tag: ForeignKey: TestTag
        * text: ForeignKey: Test Plan Text
        * type: ForeignKey: Test Plan Type

    :return: list of mappings of found :class:`TestPlan`.
    :rtype: list[dict]

    Example::

        # Get all of plans contain 'TCMS' in name
        TestPlan.filter({'name__icontain': 'TCMS'})
        # Get all of plans create by xkuang
        TestPlan.filter({'author__username': '******'})
        # Get all of plans the author name starts with x
        TestPlan.filter({'author__username__startswith': 'x'})
        # Get plans contain the case ID 1, 2, 3
        TestPlan.filter({'case__case_id__in': [1, 2, 3]})
    """
    return TestPlan.to_xmlrpc(values)
Exemple #9
0
def ajax_search(request, template_name='plan/common/json_plans.txt'):
    """Display all testplans"""
    # If it's not a search the page will be blank
    test_plans = TestPlan.objects.none()
    # if it's a search request the request will be full
    if request.GET:
        search_form = SearchPlanForm(request.GET)
        search_form.populate(product_id=request.GET.get('product'))

        if search_form.is_valid():
            # Detemine the query is the user's plans and change the sub
            # module value
            author = request.GET.get('author__email__startswith')
            if author and len(search_form.changed_data) == 1:
                if request.user.is_authenticated:
                    if author == request.user.username or author == request.user.email:
                        query = Q(author__email__startswith=author) | \
                            Q(owner__email__startswith=author)
                        test_plans = TestPlan.objects.filter(query).distinct()
            else:
                test_plans = TestPlan.list(search_form.cleaned_data)
                test_plans = test_plans.select_related('author', 'owner',
                                                       'type', 'product')

    # columnIndexNameMap is required for correct sorting behavior, 5 should
    # be product, but we use run.build.product
    column_names = [
        'plan_id', 'name', 'author__username', 'owner__username', 'product',
        'product_version', 'type', 'num_cases', 'num_runs', ''
    ]
    return ajax_response(request, test_plans, column_names, template_name)
Exemple #10
0
    def test_to_xmlrpc(self):
        result = TestPlan.to_xmlrpc(query={'pk__in': self.plan_pks})
        self.assertEqual(len(result), 2)

        # Verify fields
        sample_testplan = result[0]
        sample_fields = set(name for name in sample_testplan.keys())
        test_fields = set(self.test_fields)
        test_result = list(sample_fields ^ test_fields)
        self.assertEqual(test_result, [])

        result = dict([(item['plan_id'], item) for item in result])

        plan = result[self.plan_pks[0]]
        sample_plan = TestPlan.objects.get(pk=self.plan_pks[0])

        self.assertEqual(plan['name'], sample_plan.name)
        self.assertEqual(plan['is_active'], sample_plan.is_active)
        self.assertEqual(plan['product_version_id'],
                         sample_plan.product_version_id)

        components = plan['component']
        components.sort()
        sample_components = [item.pk for item in sample_plan.component.all()]
        sample_components.sort()
        self.assertEqual(components, sample_components)

        plan = result[self.plan_pks[1]]
        sample_plan = TestPlan.objects.get(pk=self.plan_pks[1])

        self.assertEqual(plan['name'], sample_plan.name)
        self.assertEqual(plan['is_active'], sample_plan.is_active)
        self.assertEqual(plan['product_version_id'],
                         sample_plan.product_version_id)
Exemple #11
0
 def runs_subtotal(self, form):
     sql, params = self._prepare_sql(form, sqls.by_plan_build_runs_subtotal)
     rows = SQLExecution(sql, params, with_field_name=False).rows
     result = GroupByResult()
     for plan_id, plan_name, runs_count in rows:
         plan = TestPlan(pk=plan_id, name=plan_name)
         result[plan] = runs_count
     return result
Exemple #12
0
def get_all(request):  # pylint: disable=missing-permission-required
    """Display all testplans"""
    # TODO: this function should be deleted
    # todo: this function can be replaced with the existing JSON-RPC search
    # TODO: this function now only performs a forward feature, no queries
    # need here. All of it will be removed in the future.
    # If it's not a search the page will be blank
    tps = TestPlan.objects.none()
    query_result = False
    order_by = request.GET.get('order_by', 'create_date')
    asc = bool(request.GET.get('asc', None))
    # if it's a search request the page will be fill
    if request.GET:
        search_form = SearchPlanForm(request.GET)
        search_form.populate(product_id=request.GET.get('product'))

        if search_form.is_valid():
            query_result = True
            # build a QuerySet:
            tps = TestPlan.list(search_form.cleaned_data)
            tps = tps.select_related('author', 'type', 'product')
            tps = order_plan_queryset(tps, order_by, asc)
    else:
        # Set search active plans only by default
        search_form = SearchPlanForm(initial={'is_active': True})

    template_name = 'non-existing.html'

    # used in tree preview only
    # fixme: must be replaced by JSON RPC and the
    # JavaScript dialog that displays the preview
    # should be converted to Patternfly
    # todo: when this is done SearchPlanForm must contain only the
    # fields which are used in search.html
    if request.GET.get('t') == 'html':
        if request.GET.get('f') == 'preview':
            template_name = 'plan/preview.html'

    query_url = remove_from_request_path(request, 'order_by')
    if asc:
        query_url = remove_from_request_path(query_url, 'asc')
    else:
        query_url = '%s&asc=True' % query_url
    page_type = request.GET.get('page_type', 'pagination')
    query_url_page_type = remove_from_request_path(request, 'page_type')
    if query_url_page_type:
        query_url_page_type = remove_from_request_path(query_url_page_type,
                                                       'page')

    context_data = {
        'test_plans': tps,
        'query_result': query_result,
        'search_plan_form': search_form,
        'query_url': query_url,
        'query_url_page_type': query_url_page_type,
        'page_type': page_type
    }
    return render(request, template_name, context_data)
Exemple #13
0
 def status_matrix(self, form):
     sql, params = self._prepare_sql(form, sqls.by_plan_build_status_matrix)
     rows = SQLExecution(sql, params, with_field_name=False).rows
     status_matrix = GroupByResult()
     for plan_id, plan_name, status_name, total_count in rows:
         plan = TestPlan(pk=plan_id, name=plan_name)
         status_subtotal = status_matrix.setdefault(plan, GroupByResult())
         status_subtotal[status_name] = total_count
     return status_matrix
Exemple #14
0
    def runs_subtotal(self, form):
        result = GroupByResult()
        query = self._filter_query(
            form,
            TestCaseRun.objects.values(
                'run__plan', 'run__plan__name').annotate(
                    total_count=Count('run', distinct=True)))

        for row in query:
            plan_id = row['run__plan']
            plan_name = row['run__plan__name']
            runs_count = row['total_count']
            plan = TestPlan(pk=plan_id, name=plan_name)
            result[plan] = runs_count
        return result
Exemple #15
0
def recent(request, username):
    """List the recent plan/run"""

    if username != request.user.username:
        return http.HttpResponseRedirect(reverse('nitrate-login'))

    plans_subtotal = {
        item['is_active']: item['count']
        for item in TestPlan.objects.values('is_active').annotate(
            count=Count('pk'))
    }
    plans_count = sum(plans_subtotal.values())
    disabled_plans_count = plans_subtotal.get(False, 0)

    plans = (TestPlan.objects.filter(
        Q(author=request.user) | Q(owner=request.user),
        is_active=True).select_related('product',
                                       'type').order_by('-plan_id').only(
                                           'name', 'is_active', 'type__name',
                                           'product__name'))

    plans = TestPlan.apply_subtotal(plans, runs_count=True)

    runs = (TestRun.list({
        'people': request.user,
        'is_active': True,
        'status': 'running'
    }).only('summary', 'start_date').order_by('-run_id'))

    first_15_runs = runs[:15]

    subtotal = stats_case_runs_status([item.pk for item in first_15_runs])
    for run in first_15_runs:
        run.case_runs_subtotal = subtotal[run.pk]

    return render(request,
                  'profile/recent.html',
                  context={
                      'module': MODULE_NAME,
                      'user_profile': {
                          'user': request.user
                      },
                      'test_plans_count': plans_count,
                      'test_plans_disable_count': disabled_plans_count,
                      'test_runs_count': runs.count(),
                      'last_15_test_plans': plans[:15],
                      'last_15_test_runs': first_15_runs,
                  })
Exemple #16
0
def filter(query=None):  # pylint: disable=redefined-builtin
    """
    .. function:: XML-RPC TestPlan.filter(query)

        Perform a search and return the resulting list of test plans.

        :param query: Field lookups for :class:`tcms.testplans.models.TestPlan`
        :type query: dict
        :return: List of serialized :class:`tcms.testplans.models.TestPlan` objects
        :rtype: list(dict)
    """

    if query is None:
        query = {}

    return TestPlan.to_xmlrpc(query)
Exemple #17
0
def get_plans(case_id):
    """
    Description: Get the list of plans that this case is linked to.

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

    Returns:     Array: An array of test plan object hashes.

    Example:
    >>> TestCase.get_plans(12345)
    """
    test_case = TestCase.objects.get(case_id=case_id)

    plan_ids = test_case.plan.values_list('plan_id', flat=True)
    query = {'plan_id__in': plan_ids}
    return TestPlan.to_xmlrpc(query)
Exemple #18
0
def get_plans(request, case_id):
    """Get the list of plans that this case is linked to.

    :param case_id: case ID.
    :type case_id: int or str
    :return: a list of mappings of :class:`TestPlan`.
    :rtype: list[dict]

    Example::

        TestCase.get_plans(1)
    """
    tc = TestCase.objects.get(case_id=case_id)

    plan_ids = tc.plan.values_list('plan_id', flat=True)
    query = {'plan_id__in': plan_ids}
    return TestPlan.to_xmlrpc(query)
Exemple #19
0
def get_plans(request, case_id):
    """Get the list of plans that this case is linked to.

    :param case_id: case ID.
    :type case_id: int or str
    :return: a list of mappings of :class:`TestPlan`.
    :rtype: list[dict]

    Example::

        >>> TestCase.get_plans(1)
    """
    tc = TestCase.objects.get(case_id=case_id)

    plan_ids = tc.plan.values_list('plan_id', flat=True)
    query = {'plan_id__in': plan_ids}
    return TestPlan.to_xmlrpc(query)
Exemple #20
0
def unlink_plan(case_id, plan_id):
    """
    Description: Unlink a test case from the given plan.
                 If only one plan is linked, this will delete the test case.

    Params:     $case_id - Integer/String: An integer or alias representing the ID in the database.
                $plan_id - Integer: An integer representing the ID in the database.

    Returns:    Array: Array of plans hash still linked if any, empty if not.

    Example:
    >>> TestCase.unlink_plan(12345, 137)
    """
    TestCasePlan.objects.filter(case=case_id, plan=plan_id).delete()
    plan_pks = TestCasePlan.objects.filter(case=case_id).values_list('plan',
                                                                     flat=True)
    return TestPlan.to_xmlrpc(query={'pk__in': plan_pks})
Exemple #21
0
def unlink_plan(requst, case_id, plan_id):
    """
    Description: Unlink a test case from the given plan. If only one plan is linked, this will delete
                 the test case.

    Params:      $case_id - Integer/String: An integer or alias representing the ID in the database.
                 $plan_id - Integer: An integer representing the ID in the database.

    Returns:     Array: Array of plans hash still linked if any, empty if not.

    Example:
    >>> TestCase.unlink_plan(12345, 137)
    """
    TestCasePlan.objects.filter(case=case_id, plan=plan_id).delete()
    plan_pks = TestCasePlan.objects.filter(case=case_id).values_list('plan',
                                                                     flat=True)
    return TestPlan.to_xmlrpc(query={'pk__in': plan_pks})
Exemple #22
0
def ajax_search(request, template_name='plan/common/json_plans.txt'):
    """Display all testplans"""
    # Define the default sub module

    # If it's not a search the page will be blank
    tps = TestPlan.objects.none()
    # if it's a search request the page will be fill
    if list(request.GET.items()):
        search_form = SearchPlanForm(request.GET)
        if request.GET.get('product'):
            search_form.populate(product_id=request.GET['product'])
        else:
            search_form.populate()
        if search_form.is_valid():
            # Detemine the query is the user's plans and change the sub
            # module value
            author = request.GET.get('author__email__startswith')
            if author and len(search_form.changed_data) == 1:
                if request.user.is_authenticated():
                    if author == request.user.username or author == request.user.email:
                        q = Q(author__email__startswith=author) | \
                            Q(owner__email__startswith=author)
                        tps = TestPlan.objects.filter(q).distinct()
            else:
                tps = TestPlan.list(search_form.cleaned_data)
                tps = tps.select_related('author', 'owner', 'type', 'product')

    # columnIndexNameMap is required for correct sorting behavior, 5 should
    # be product, but we use run.build.product
    column_names = [
        '',
        'plan_id',
        'name',
        'author__username',
        'owner__username',
        'product',
        'product_version',
        'type',
        'num_cases',
        'num_runs',
        ''
    ]
    return ajax_response(request, tps, column_names,
                         'plan/common/json_plans.txt')
Exemple #23
0
def get_plans(request, case_id):
    """
    Description: Get the list of plans that this case is linked to.

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

    Returns:     Array: An array of test plan object hashes.

    Example:
    >>> TestCase.get_plans(12345)
    """
    try:
        tc = TestCase.objects.get(case_id=case_id)
    except:
        raise

    plan_ids = tc.plan.values_list('plan_id', flat=True)
    query = {'plan_id__in': plan_ids}
    return TestPlan.to_xmlrpc(query)
Exemple #24
0
def get_plans(request, product):
    """Get the list of plans associated with this product.

    :param product: product ID or name.
    :type product: int or str
    :return: a list of mappings of :class:`TestPlan`.
    :rtype: list

    Example::

        # Get with product id
        >>> Product.get_plans(61)
        # Get with product name
        >>> Product.get_plans('product name')
    """
    from tcms.testplans.models import TestPlan

    p = pre_check_product(values=product)
    query = {'product': p}
    return TestPlan.to_xmlrpc(query)
Exemple #25
0
def get_plans(request, product):
    """Get the list of plans associated with this product.

    :param product: product ID or name.
    :type product: int or str
    :return: a list of mappings of :class:`TestPlan`.
    :rtype: list

    Example::

        # Get with product id
        >>> Product.get_plans(61)
        # Get with product name
        >>> Product.get_plans('product name')
    """
    from tcms.testplans.models import TestPlan

    p = pre_check_product(values=product)
    query = {'product': p}
    return TestPlan.to_xmlrpc(query)
Exemple #26
0
    def status_matrix(self, form):
        query = self._filter_query(
            form,
            TestCaseRun.objects.values(
                'run__plan', 'run__plan__name', 'build', 'build__name', 'run',
                'run__summary',
                'case_run_status__name').annotate(total_count=Count('pk')))
        status_matrix = GroupByResult()

        for row in query:
            plan = TestPlan(pk=row['run__plan'], name=row['run__plan__name'])
            builds = status_matrix.setdefault(plan, GroupByResult())

            build = Build(pk=row['build'], name=row['build__name'])
            runs = builds.setdefault(build, GroupByResult())

            run = TestRun(pk=row['run'], summary=row['run__summary'])
            status_subtotal = runs.setdefault(run, GroupByResult())
            status_subtotal[row['case_run_status__name']] = row['total_count']

        return status_matrix
Exemple #27
0
def unlink_plan(requst, case_id, plan_id):
    """
    Description: Unlink a test case from the given plan. If only one plan is linked, this will delete
                 the test case.

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

    Returns:     Array: Array of plans hash still linked if any, empty if not.

    Example:
    >>> TestCase.unlink_plan(12345, 137)
    """
    sql = 'DELETE FROM test_case_plans WHERE plan_id = %s and case_id = %s'
    cursor = connection.writer_cursor
    cursor.execute(sql, [int(plan_id), int(case_id)])
    transaction.commit_unless_managed()

    plan_pks = TestCasePlan.objects.filter(case=case_id).values_list('plan',
                                                                     flat=True)
    return TestPlan.to_xmlrpc(query={'pk__in': plan_pks})
Exemple #28
0
def get_plans(request, product):
    """
    Description: Get the list of plans associated with this product.

    Params:      $product - Integer/String
                            Integer: product_id of the product in the Database
                            String: Product name

    Returns:     Array: Returns an array of Test Plan objects.

    Example:
    # Get with product id
    >>> Product.get_plans(61)
    # Get with product name
    >>> Product.get_plans('Red Hat Enterprise Linux 5')
    """
    from tcms.testplans.models import TestPlan

    p = pre_check_product(values=product)
    query = {'product': p}
    return TestPlan.to_xmlrpc(query)
Exemple #29
0
    def status_matrix(self, form):
        sql, params = self._prepare_sql(form,
                                        sqls.by_plan_tags_detail_status_matrix)
        rows = SQLExecution(sql, params, with_field_name=False).rows

        status_matrix = GroupByResult()

        for row in rows:
            (tag_id, build_id, build_name, plan_id, plan_name, run_id,
             run_summary, status_name, total_count) = row

            builds = status_matrix.setdefault(tag_id, GroupByResult())
            plans = builds.setdefault(TestBuild(pk=build_id, name=build_name),
                                      GroupByResult())
            runs = plans.setdefault(TestPlan(pk=plan_id, name=plan_name),
                                    GroupByResult())
            status_subtotal = runs.setdefault(
                TestRun(pk=run_id, summary=run_summary), GroupByResult())
            status_subtotal[status_name] = total_count

        return status_matrix
Exemple #30
0
def construct_plans_treeview(request, plan_id):
    """Construct a plan's tree view"""
    plan = get_object_or_404(TestPlan, pk=plan_id)

    tree_plan_ids = plan.get_ancestor_ids() + plan.get_descendant_ids()
    tree_plan_ids.append(plan.pk)

    plans = (TestPlan.objects.filter(pk__in=tree_plan_ids).only(
        'pk', 'name', 'parent_id').order_by('parent_id', 'pk'))

    plans = TestPlan.apply_subtotal(plans,
                                    cases_count=True,
                                    runs_count=True,
                                    children_count=True)

    return render(request,
                  'plan/get_treeview.html',
                  context={
                      'current_plan_id': plan_id,
                      'plans': plans
                  })
Exemple #31
0
def get_plans(request, product):
    """
    Description: Get the list of plans associated with this product.

    Params:      $product - Integer/String
                            Integer: product_id of the product in the Database
                            String: Product name

    Returns:     Array: Returns an array of Test Plan objects.

    Example:
    # Get with product id
    >>> Product.get_plans(61)
    # Get with product name
    >>> Product.get_plans('Red Hat Enterprise Linux 5')
    """
    from tcms.testplans.models import TestPlan

    p = pre_check_product(values=product)
    query = {'product': p}
    return TestPlan.to_xmlrpc(query)
Exemple #32
0
def unlink_plan(requst, case_id, plan_id):
    """
    Unlink a test case from the given plan. If only one plan is linked, this
    will delete the test case.

    :param case_id: case ID.
    :type case_id: int or str
    :param int plan_id: plan ID from where to unlink the specified case.
    :return: a list of mappings of test plans that are still linked to the
        specified case. If there is no linked test plans, empty list will be
        returned.
    :rtype: list[dict]

    Example::

        # Unlink case 100 from plan 10
        TestCase.unlink_plan(100, 10)
    """
    TestCasePlan.objects.filter(case=case_id, plan=plan_id).delete()
    plan_pks = TestCasePlan.objects.filter(case=case_id).values_list('plan',
                                                                     flat=True)
    return TestPlan.to_xmlrpc(query={'pk__in': plan_pks})
Exemple #33
0
def unlink_plan(requst, case_id, plan_id):
    """
    Unlink a test case from the given plan. If only one plan is linked, this
    will delete the test case.

    :param case_id: case ID.
    :type case_id: int or str
    :param int plan_id: plan ID from where to unlink the specified case.
    :return: a list of mappings of test plans that are still linked to the
        specified case. If there is no linked test plans, empty list will be
        returned.
    :rtype: list[dict]

    Example::

        # Unlink case 100 from plan 10
        >>> TestCase.unlink_plan(100, 10)
    """
    TestCasePlan.objects.filter(case=case_id, plan=plan_id).delete()
    plan_pks = TestCasePlan.objects.filter(case=case_id).values_list('plan',
                                                                     flat=True)
    return TestPlan.to_xmlrpc(query={'pk__in': plan_pks})
Exemple #34
0
def filter(request, values={}):
    """
    Description: Performs a search and returns the resulting list of test plans.

    Params:      $values - Hash: keys must match valid search fields.

        +------------------------------------------------------------+
        |                   Plan Search Parameters                   |
        +----------------------------------------------------------+
        |        Key              |          Valid Values            |
        | author                  | ForeignKey: Auth.User            |
        | attachment              | ForeignKey: Attachment           |
        | case                    | ForeignKey: Test Case            |
        | create_date             | DateTime                         |
        | env_group               | ForeignKey: Environment Group    |
        | name                    | String                           |
        | plan_id                 | Integer                          |
        | product                 | ForeignKey: Product              |
        | product_version         | ForeignKey: Version              |
        | tag                     | ForeignKey: Tag                  |
        | text                    | ForeignKey: Test Plan Text       |
        | type                    | ForeignKey: Test Plan Type       |
        +------------------------------------------------------------+

    Returns:     Array: Matching test plans are retuned in a list of plan object hashes.

    Example:
    # Get all of plans contain 'TCMS' in name
    >>> TestPlan.filter({'name__icontain': 'TCMS'})
    # Get all of plans create by xkuang
    >>> TestPlan.filter({'author__username': '******'})
    # Get all of plans the author name starts with x
    >>> TestPlan.filter({'author__username__startswith': 'x'})
    # Get plans contain the case ID 12345, 23456, 34567
    >>> TestPlan.filter({'case__case_id__in': [12345, 23456, 34567]})
    """
    return TestPlan.to_xmlrpc(values)
Exemple #35
0
def filter(request, values={}):
    """
    Description: Performs a search and returns the resulting list of test plans.

    Params:      $values - Hash: keys must match valid search fields.

        +------------------------------------------------------------+
        |                   Plan Search Parameters                   |
        +----------------------------------------------------------+
        |        Key              |          Valid Values            |
        | author                  | ForeignKey: Auth.User            |
        | attachment              | ForeignKey: Attachment           |
        | case                    | ForeignKey: Test Case            |
        | create_date             | DateTime                         |
        | env_group               | ForeignKey: Environment Group    |
        | name                    | String                           |
        | plan_id                 | Integer                          |
        | product                 | ForeignKey: Product              |
        | product_version         | ForeignKey: Version              |
        | tag                     | ForeignKey: Tag                  |
        | text                    | ForeignKey: Test Plan Text       |
        | type                    | ForeignKey: Test Plan Type       |
        +------------------------------------------------------------+

    Returns:     Array: Matching test plans are retuned in a list of plan object hashes.

    Example:
    # Get all of plans contain 'TCMS' in name
    >>> TestPlan.filter({'name__icontain': 'TCMS'})
    # Get all of plans create by xkuang
    >>> TestPlan.filter({'author__username': '******'})
    # Get all of plans the author name starts with x
    >>> TestPlan.filter({'author__username__startswith': 'x'})
    # Get plans contain the case ID 12345, 23456, 34567
    >>> TestPlan.filter({'case__case_id__in': [12345, 23456, 34567]})
    """
    return TestPlan.to_xmlrpc(values)
Exemple #36
0
    def status_matrix(self, form):
        status_matrix = GroupByResult()
        query = self._filter_query(
            form,
            TestCaseRun.objects.values(
                'build', 'build__name', 'run__plan__tag', 'run__plan',
                'run__plan__name', 'run', 'run__summary',
                'status__name').annotate(total_count=Count('pk')))

        for row in query:
            builds = status_matrix.setdefault(row['run__plan__tag'],
                                              GroupByResult())
            plans = builds.setdefault(
                Build(pk=row['build'], name=row['build__name']),
                GroupByResult())
            runs = plans.setdefault(
                TestPlan(pk=row['run__plan'], name=row['run__plan__name']),
                GroupByResult())
            status_subtotal = runs.setdefault(
                TestRun(pk=row['run'], summary=row['run__summary']),
                GroupByResult())
            status_subtotal[row['status__name']] = row['total_count']

        return status_matrix
Exemple #37
0
def all(request, template_name='plan/all.html'):
    '''Display all testplans'''
    # Define the default sub module
    SUB_MODULE_NAME = 'plans'
    # TODO: this function now only performs a forward feature, no queries
    # need here. All of it will be removed in the future.
    # If it's not a search the page will be blank
    tps = TestPlan.objects.none()
    query_result = False
    order_by = request.GET.get('order_by', 'create_date')
    asc = bool(request.GET.get('asc', None))
    # if it's a search request the page will be fill
    if request.GET.items():
        search_form = SearchPlanForm(request.GET)
        if request.GET.get('product'):
            search_form.populate(product_id=request.GET['product'])
        else:
            search_form.populate()

        if search_form.is_valid():
            # Detemine the query is the user's plans and change the sub
            # module value
            author = request.GET.get('author')
            if author and request.user.is_authenticated():
                if author == request.user.username or author == request.user.email:
                    SUB_MODULE_NAME = "my_plans"

            query_result = True
            # build a QuerySet:
            tps = TestPlan.list(search_form.cleaned_data)
            tps = tps.select_related('author', 'type', 'product')

            # We want to get the number of cases and runs, without doing
            # lots of per-test queries.
            #
            # Ideally we would get the case/run counts using m2m field tricks
            # in the ORM
            # Unfortunately, Django's select_related only works on ForeignKey
            # relationships, not on ManyToManyField attributes
            # See http://code.djangoproject.com/ticket/6432

            # SQLAlchemy can handle this kind of thing in several ways.
            # Unfortunately we're using Django

            # The cleanest way I can find to get it into one query is to
            # use QuerySet.extra()
            # See http://docs.djangoproject.com/en/dev/ref/models/querysets
            tps = tps.extra(select={
                'num_cases': RawSQL.num_cases,
                'num_runs': RawSQL.num_runs,
                'num_children': RawSQL.num_plans,
            })
            tps = order_plan_queryset(tps, order_by, asc)
    else:
        # Set search active plans only by default
        # I wish to use 'default' argument, as the same as in ModelForm
        # But it does not seem to work
        search_form = SearchPlanForm(initial={'is_active': True})

    if request.GET.get('action') == 'clone_case':
        template_name = 'case/clone_select_plan.html'
        tps = tps.order_by('name')

    if request.GET.get('t') == 'ajax':
        return HttpResponse(serializers.serialize(
            request.GET.get('f', 'json'),
            tps,
            extras=('num_cases', 'num_runs', 'num_children', 'get_url_path')
        ))

    if request.GET.get('t') == 'html':
        if request.GET.get('f') == 'preview':
            template_name = 'plan/preview.html'

    query_url = remove_from_request_path(request, 'order_by')
    if asc:
        query_url = remove_from_request_path(query_url, 'asc')
    else:
        query_url = '%s&asc=True' % query_url
    page_type = request.GET.get('page_type', 'pagination')
    query_url_page_type = remove_from_request_path(request, 'page_type')
    if query_url_page_type:
        query_url_page_type = remove_from_request_path(query_url_page_type, 'page')

    context_data = {
        'module': MODULE_NAME,
        'sub_module': SUB_MODULE_NAME,
        'test_plans': tps,
        'query_result': query_result,
        'search_plan_form': search_form,
        'query_url': query_url,
        'query_url_page_type': query_url_page_type,
        'page_type': page_type
    }
    return render_to_response(template_name, context_data,
                              context_instance=RequestContext(request))
Exemple #38
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)
Exemple #39
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)
Exemple #40
0
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)
Exemple #41
0
def all(request, template_name='plan/all.html'):
    '''Display all testplans'''
    # TODO: this function now only performs a forward feature, no queries
    # need here. All of it will be removed in the future.
    # If it's not a search the page will be blank
    tps = TestPlan.objects.none()
    query_result = False
    order_by = request.GET.get('order_by', 'create_date')
    asc = bool(request.GET.get('asc', None))
    # if it's a search request the page will be fill
    if request.GET:
        search_form = SearchPlanForm(request.GET)
        if request.GET.get('product'):
            search_form.populate(product_id=request.GET['product'])
        else:
            search_form.populate()

        if search_form.is_valid():
            query_result = True
            # build a QuerySet:
            tps = TestPlan.list(search_form.cleaned_data)
            tps = tps.select_related('author', 'type', 'product')

            # We want to get the number of cases and runs, without doing
            # lots of per-test queries.
            #
            # Ideally we would get the case/run counts using m2m field tricks
            # in the ORM
            # Unfortunately, Django's select_related only works on ForeignKey
            # relationships, not on ManyToManyField attributes
            # See http://code.djangoproject.com/ticket/6432

            # SQLAlchemy can handle this kind of thing in several ways.
            # Unfortunately we're using Django

            # The cleanest way I can find to get it into one query is to
            # use QuerySet.extra()
            # See http://docs.djangoproject.com/en/dev/ref/models/querysets
            tps = tps.extra(select={
                'num_cases': RawSQL.num_cases,
                'num_runs': RawSQL.num_runs,
                'num_children': RawSQL.num_plans,
            })
            tps = order_plan_queryset(tps, order_by, asc)
    else:
        # Set search active plans only by default
        search_form = SearchPlanForm(initial={'is_active': True})

    if request.GET.get('action') == 'clone_case':
        template_name = 'case/clone_select_plan.html'
        tps = tps.order_by('name')

    if request.GET.get('t') == 'ajax':
        results = []
        for obj in tps:
            dict_obj = model_to_dict(obj, fields=('name', 'parent', 'is_active'))

            for attr in ['pk', 'num_cases', 'num_cases', 'num_runs', 'num_children']:
                dict_obj[attr] = getattr(obj, attr)
            dict_obj['get_url_path'] = obj.get_url_path()

            results.append(dict_obj)
        return JsonResponse(results, safe=False)

    if request.GET.get('t') == 'html':
        if request.GET.get('f') == 'preview':
            template_name = 'plan/preview.html'

    query_url = remove_from_request_path(request, 'order_by')
    if asc:
        query_url = remove_from_request_path(query_url, 'asc')
    else:
        query_url = '%s&asc=True' % query_url
    page_type = request.GET.get('page_type', 'pagination')
    query_url_page_type = remove_from_request_path(request, 'page_type')
    if query_url_page_type:
        query_url_page_type = remove_from_request_path(query_url_page_type, 'page')

    context_data = {
        'test_plans': tps,
        'query_result': query_result,
        'search_plan_form': search_form,
        'query_url': query_url,
        'query_url_page_type': query_url_page_type,
        'page_type': page_type
    }
    return render(request, template_name, context_data)
Exemple #42
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)
Exemple #43
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)
Exemple #44
0
def update(request, 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(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        | 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.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)