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)
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
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
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
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
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)
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)
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)
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
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)
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
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
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, })
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)
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)
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)
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)
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})
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})
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')
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)
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)
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
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})
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)
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
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 })
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})
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})
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)
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
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))
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)
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)
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)
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)
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)
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)
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)