def _report_data_context(self): data = {} form = self._get_search_form() if form.is_valid(): summary_header_data = super(CustomDetailReport, self)._report_data_context() data.update(summary_header_data) build_ids = [build.pk for build in data['builds']] # TODO: remove this after upgrading MySQL-python to 1.2.5 build_ids = tuple(workaround_single_value_for_in_clause(build_ids)) status_matrix = self.walk_matrix_row_by_row( self._data.generate_status_matrix(build_ids)) # TODO: remove this after upgrading MySQL-python to 1.2.5 status_ids = workaround_single_value_for_in_clause( (TestCaseRunStatus.name_to_id('FAILED'),)) failed_case_runs = self.read_case_runs(build_ids, status_ids) # TODO: remove this after upgrading MySQL-python to 1.2.5 status_ids = workaround_single_value_for_in_clause( (TestCaseRunStatus.name_to_id('BLOCKED'),)) blocked_case_runs = self.read_case_runs(build_ids, status_ids) data.update({ 'status_matrix': status_matrix, 'failed_case_runs': failed_case_runs, 'blocked_case_runs': blocked_case_runs, }) else: data['report_errors'] = form.errors data['form'] = form return data
def _report_data_context(self): data = {} form = self._get_search_form() if form.is_valid(): summary_header_data = super()._report_data_context() data.update(summary_header_data) build_ids = [build.pk for build in data['builds']] # TODO: remove this after upgrading MySQL-python to 1.2.5 build_ids = tuple(workaround_single_value_for_in_clause(build_ids)) status_matrix = self.walk_matrix_row_by_row( self._data.generate_status_matrix(build_ids)) # TODO: remove this after upgrading MySQL-python to 1.2.5 status_ids = workaround_single_value_for_in_clause( (TestCaseRunStatus.name_to_id('FAILED'),)) failed_case_runs = self.read_case_runs(build_ids, status_ids) # TODO: remove this after upgrading MySQL-python to 1.2.5 status_ids = workaround_single_value_for_in_clause( (TestCaseRunStatus.name_to_id('BLOCKED'),)) blocked_case_runs = self.read_case_runs(build_ids, status_ids) data.update({ 'status_matrix': status_matrix, 'failed_case_runs': failed_case_runs, 'blocked_case_runs': blocked_case_runs, }) else: data['report_errors'] = form.errors data['form'] = form return data
def calculate_associated_data(runs: QuerySet) -> None: """Calculate associated data and set to each run in place The associated data include: * completed progress of each test run * the environment of each test run """ run_ids = [run.pk for run in runs] qs = (TestCaseRun.objects.filter( case_run_status=TestCaseRunStatus.name_to_id('FAILED'), run__in=run_ids).values('run', 'case_run_status').annotate( count=Count('pk')).order_by('run', 'case_run_status')) failure_subtotal = magic_convert(qs, key_name='run', value_name='count') completed_status_ids = TestCaseRunStatus.completed_status_ids() qs = (TestCaseRun.objects.filter( case_run_status__in=completed_status_ids, run__in=run_ids).values( 'run', 'case_run_status').annotate(count=Count('pk')).order_by( 'run', 'case_run_status')) completed_subtotal = { run_id: sum((item['count'] for item in stats_rows)) for run_id, stats_rows in itertools.groupby(qs.iterator(), key=itemgetter('run')) } qs = (TestCaseRun.objects.filter(run__in=run_ids).values('run').annotate( cases_count=Count('case'))) cases_subtotal = magic_convert(qs, key_name='run', value_name='cases_count') # Relative env groups to runs result = (TCMSEnvGroup.objects.filter(plans__run__in=run_ids).values( 'plans__run', 'name')) runs_env_groups = {item['plans__run']: item['name'] for item in result} for run in runs: run_id = run.pk cases_count = cases_subtotal.get(run_id, 0) if cases_count: completed_percent = completed_subtotal.get( run_id, 0) * 1.0 / cases_count * 100 failure_percent = failure_subtotal.get(run_id, 0) * 1.0 / cases_count * 100 else: completed_percent = failure_percent = 0 run.associated_data = { 'stats': { 'cases': cases_count, 'completed_percent': completed_percent, 'failure_percent': failure_percent, }, 'env_group': runs_env_groups.get(run_id), }
def case_runs_filter_criteria(self, form): filter_criteria = {} priority = form.cleaned_data['priority'] if priority: filter_criteria['case__priority__pk'] = priority tester = form.cleaned_data['tester'] if tester is not None: if tester == 0: filter_criteria['tested_by'] = None else: filter_criteria['tested_by__pk'] = tester status = form.cleaned_data['status'] if status: status_id = TestCaseRunStatus.name_to_id(status.upper()) filter_criteria['case_run_status'] = status_id return filter_criteria
def case_runs_filter_criteria(self, form): filter_criteria = {} priority = form.cleaned_data['priority'] if priority: filter_criteria['case__priority__pk'] = priority tester = form.cleaned_data['tester'] if tester is not None: if tester == 0: filter_criteria['tested_by'] = None else: filter_criteria['tested_by__pk'] = tester status = form.cleaned_data['status'] if status: status_id = TestCaseRunStatus.name_to_id(status.upper()) filter_criteria['case_run_status'] = status_id return filter_criteria
def _report_data_context(self): form = self._get_search_form() context = {'form': form} if not form.is_valid(): context.update({'builds': ()}) return context _data = self.data_class(form) self._data = _data builds = _data._get_builds() build_ids = [build.pk for build in builds] # TODO: remove this after upgrading MySQL-python to 1.2.5 build_ids = workaround_single_value_for_in_clause(build_ids) if build_ids: # Summary header data runs_subtotal = _data.runs_subtotal() plans_subtotal = _data.plans_subtotal() case_runs_subtotal = _data.case_runs_subtotal() isautomated_subtotal = _data.cases_isautomated_subtotal() # Staus matrix used to render progress bar for each build case_runs_status_matrix = _data.status_matrix() # FIXME: this would raise KeyError once status names are modified # to other ones. passed_id = TestCaseRunStatus.name_to_id('PASSED') failed_id = TestCaseRunStatus.name_to_id('FAILED') for build in builds: bid = build.pk build.runs_count = runs_subtotal.get(bid, 0) build.plans_count = plans_subtotal.get(bid, 0) build.case_runs_count = case_runs_subtotal.get(bid, 0) status_subtotal = case_runs_status_matrix.get(bid, {}) passed_count = status_subtotal.get(passed_id, 0) failed_count = status_subtotal.get(failed_id, 0) c = case_runs_subtotal.get(bid, 0) if c: build.passed_case_runs_percent = passed_count * 100.0 / c build.failed_case_runs_percent = failed_count * 100.0 / c else: build.passed_case_runs_percent = .0 build.failed_case_runs_percent = .0 build.passed_case_runs_count = passed_count build.failed_case_runs_count = failed_count build.case_runs_count = c context.update({ # method invocation. 'total_runs_count': runs_subtotal.total, 'total_plans_count': plans_subtotal.total, 'total_count': isautomated_subtotal.total, 'manual_count': isautomated_subtotal.get(0, 0), 'auto_count': isautomated_subtotal.get(1, 0), 'both_count': isautomated_subtotal.get(2, 0), }) context.update({'builds': builds}) return context
def load_runs_of_one_plan(request, plan_id, template_name='plan/common/json_plan_runs.txt'): """A dedicated view to return a set of runs of a plan This view is used in a plan detail page, for the contained testrun tab. It replaces the original solution, with a paginated resultset in return, serves as a performance healing. Also, in order for user to locate the data, it accepts field lookup parameters collected from the filter panel in the UI. """ column_names = [ '', 'run_id', 'summary', 'manager__username', 'default_tester__username', 'start_date', 'build__name', 'stop_date', 'total_num_caseruns', 'failure_caseruns_percent', 'successful_caseruns_percent', ] tp = TestPlan.objects.get(plan_id=plan_id) form = PlanFilterRunForm(request.GET) if form.is_valid(): queryset = tp.run.filter(**form.cleaned_data) queryset = queryset.select_related('build', 'manager', 'default_tester').order_by('-pk') dt = DataTableResult(request.GET, queryset, column_names) response_data = dt.get_response_data() searched_runs = response_data['querySet'] # Get associated statistics data run_filters = { f'run__{key}': value for key, value in form.cleaned_data.items() } qs = TestCaseRun.objects.filter( case_run_status=TestCaseRunStatus.name_to_id('FAILED'), **run_filters).values('run', 'case_run_status').annotate( count=Count('pk')).order_by('run', 'case_run_status') failure_subtotal = magic_convert(qs, key_name='run', value_name='count') qs = TestCaseRun.objects.filter( case_run_status=TestCaseRunStatus.name_to_id('PASSED'), **run_filters).values('run', 'case_run_status').annotate( count=Count('pk')).order_by('run', 'case_run_status') success_subtotal = magic_convert(qs, key_name='run', value_name='count') qs = TestCaseRun.objects.filter(**run_filters).values('run').annotate( count=Count('case')).order_by('run') cases_subtotal = magic_convert(qs, key_name='run', value_name='count') for run in searched_runs: run_id = run.pk cases_count = cases_subtotal.get(run_id, 0) if cases_count: failure_percent = failure_subtotal.get( run_id, 0) * 1.0 / cases_count * 100 success_percent = success_subtotal.get( run_id, 0) * 1.0 / cases_count * 100 else: failure_percent = success_percent = 0 run.nitrate_stats = { 'cases': cases_count, 'failure_percent': failure_percent, 'success_percent': success_percent, } else: response_data = { 'sEcho': int(request.GET.get('sEcho', 0)), 'iTotalRecords': 0, 'iTotalDisplayRecords': 0, 'querySet': TestRun.objects.none(), } resp_data = get_template(template_name).render(response_data, request) return JsonResponse(json.loads(resp_data))
def _report_data_context(self): form = self._get_search_form() context = {'form': form} if not form.is_valid(): context.update({'builds': ()}) return context _data = self.data_class(form) self._data = _data builds = _data._get_builds() build_ids = [build.pk for build in builds] # TODO: remove this after upgrading MySQL-python to 1.2.5 build_ids = workaround_single_value_for_in_clause(build_ids) if build_ids: # Summary header data runs_subtotal = _data.runs_subtotal() plans_subtotal = _data.plans_subtotal() case_runs_subtotal = _data.case_runs_subtotal() isautomated_subtotal = _data.cases_isautomated_subtotal() # Staus matrix used to render progress bar for each build case_runs_status_matrix = _data.status_matrix() # FIXME: this would raise KeyError once status names are modified # to other ones. passed_id = TestCaseRunStatus.name_to_id('PASSED') failed_id = TestCaseRunStatus.name_to_id('FAILED') for build in builds: bid = build.pk build.runs_count = runs_subtotal.get(bid, 0) build.plans_count = plans_subtotal.get(bid, 0) build.case_runs_count = case_runs_subtotal.get(bid, 0) status_subtotal = case_runs_status_matrix.get(bid, {}) passed_count = status_subtotal.get(passed_id, 0) failed_count = status_subtotal.get(failed_id, 0) c = case_runs_subtotal.get(bid, 0) if c: build.passed_case_runs_percent = passed_count * 100.0 / c build.failed_case_runs_percent = failed_count * 100.0 / c else: build.passed_case_runs_percent = .0 build.failed_case_runs_percent = .0 build.passed_case_runs_count = passed_count build.failed_case_runs_count = failed_count build.case_runs_count = c context.update({ # method invocation. 'total_runs_count': runs_subtotal.total, 'total_plans_count': plans_subtotal.total, 'total_count': isautomated_subtotal.total, 'manual_count': isautomated_subtotal.get(0, 0), 'auto_count': isautomated_subtotal.get(1, 0), 'both_count': isautomated_subtotal.get(2, 0), }) context.update({'builds': builds}) return context