Exemple #1
0
    def test_get_selected_testcases_works_with_both_string_and_int_pks(self):
        """
        Assures that tcms.testcases.views.get_selected_testcases
        returns the same results, regardless of whether the
        passed request contains the case pks as strings or
        integers, as long as they are the same in both occasions.
        """

        case_int_pks = [
            self.case.pk, self.case_1.pk, self.case_2.pk, self.case_3.pk
        ]
        case_str_pks = []

        for _pk in case_int_pks:
            case_str_pks.append(str(_pk))

        int_pk_query = get_selected_testcases(RequestFactory().post(
            reverse('testcases-clone'), {'case': case_int_pks}))

        str_pk_query = get_selected_testcases(RequestFactory().post(
            reverse('testcases-clone'), {'case': case_str_pks}))

        for case in TestCase.objects.filter(pk__in=case_int_pks):
            self.assertTrue(case in int_pk_query)
            self.assertTrue(case in str_pk_query)
Exemple #2
0
def _write_cases_to_test_plan(request, plan_id):
    try:
        test_plan = TestPlan.objects.get(pk=int(plan_id))
    except ObjectDoesNotExist:
        raise Http404

    test_runs = TestRun.objects.filter(plan=plan_id).values('pk',
                                                            'summary',
                                                            'build__name',
                                                            'manager__username')

    # Ready to write cases to test plan
    test_cases = get_selected_testcases(request).values('pk', 'summary',
                                                        'author__username',
                                                        'create_date',
                                                        'category__name',
                                                        'priority__value', )

    context_data = {
        'plan_id': plan_id,
        'plan': test_plan,
        'test_runs': test_runs.iterator(),
        'test_cases': test_cases.iterator(),
    }
    return render(request, 'plan/choose_testrun.html', context_data)
Exemple #3
0
    def get(self, request, plan_id):
        plan = TestPlan.objects.filter(
            pk=int(plan_id)).defer('product_version').first()
        if plan is None:
            raise Http404

        # TODO: replace with plan.run.values(...)
        runs = TestRun.objects.filter(plan=plan_id).values(
            'pk', 'summary', 'build__name', 'manager__username')

        cases = get_selected_testcases(request).values('pk', 'summary',
                                                       'author__username',
                                                       'create_date',
                                                       'category__name',
                                                       'priority__value')

        return render(request,
                      self.template_name,
                      context={
                          'module': MODULE_NAME,
                          'sub_module': self.SUB_MODULE_NAME,
                          'plan_id': plan_id,
                          'plan': plan,
                          'test_runs': runs.iterator(),
                          'test_cases': cases,
                      })
Exemple #4
0
    def post(self, request, plan_id):
        plan = get_object_or_404(TestPlan.objects.only('pk'), pk=int(plan_id))

        if 'case' not in request.POST:
            return JsonResponse({
                'rc': 1,
                'response': 'At least one case is required to delete.'
            })

        cases = get_selected_testcases(request).only('pk')
        for case in cases:
            plan.delete_case(case=case)

        return JsonResponse({'rc': 0, 'response': 'ok'})
Exemple #5
0
        def delete_cases(self):
            if not request.POST.get('case'):
                ajax_response['rc'] = 1
                ajax_response['response'] = 'At least one case is required to delete.'
                return JsonResponse(ajax_response)

            tcs = get_selected_testcases(request)

            # Log Action
            tp_log = TCMSLog(model=tp)
            for tc in tcs:
                tp_log.make(who=request.user,
                            action='Remove case %s from plan %s' % (tc.case_id, tp.plan_id))
                tc.log_action(who=request.user, action='Remove from plan %s' % tp.plan_id)
                tp.delete_case(case=tc)

            return JsonResponse(ajax_response)
Exemple #6
0
        def delete_cases(self):
            if not request.POST.get('case'):
                ajax_response['rc'] = 1
                ajax_response['response'] = 'At least one case is required to delete.'
                return JsonResponse(ajax_response)

            tcs = get_selected_testcases(request)

            # Log Action
            tp_log = TCMSLog(model=tp)
            for tc in tcs:
                tp_log.make(who=request.user,
                            action='Remove case %s from plan %s' % (tc.case_id, tp.plan_id))
                tc.log_action(who=request.user, action='Remove from plan %s' % tp.plan_id)
                tp.delete_case(case=tc)

            return JsonResponse(ajax_response)
Exemple #7
0
    def post(self, request, plan_id):
        plan = get_object_or_404(TestPlan.objects.only('pk'), pk=int(plan_id))

        if 'case' not in request.POST:
            return JsonResponseBadRequest(
                {'message': 'At least one case is required to delete.'})

        cases = get_selected_testcases(request).only('pk')

        # Log Action
        plan_log = TCMSLog(model=plan)
        for case in cases:
            plan_log.make(
                who=request.user,
                new_value=f'Remove case {case.pk} from plan {plan.pk}')
            case.log_action(who=request.user,
                            new_value=f'Remove from plan {plan.pk}')
            plan.delete_case(case=case)

        return JsonResponse({})
Exemple #8
0
    def post(self, request, plan_id):
        plan = get_object_or_404(TestPlan.objects.only('pk'), pk=int(plan_id))

        if 'case' not in request.POST:
            return JsonResponse({
                'rc': 1,
                'response': 'At least one case is required to delete.'
            })

        cases = get_selected_testcases(request).only('pk')

        # Log Action
        plan_log = TCMSLog(model=plan)
        for case in cases:
            plan_log.make(
                who=request.user,
                action='Remove case {} from plan {}'.format(case.pk, plan.pk))
            case.log_action(who=request.user,
                            action='Remove from plan {}'.format(plan.pk))
            plan.delete_case(case=case)

        return JsonResponse({'rc': 0, 'response': 'ok'})
Exemple #9
0
    def post(self, request, plan_id):
        plan = get_object_or_404(TestPlan.objects.only('pk'), pk=int(plan_id))

        if 'case' not in request.POST:
            return JsonResponse({
                'rc': 1,
                'response': 'At least one case is required to delete.'
            })

        cases = get_selected_testcases(request).only('pk')

        # Log Action
        plan_log = TCMSLog(model=plan)
        for case in cases:
            plan_log.make(
                who=request.user,
                new_value='Remove case {} from plan {}'.format(case.pk, plan.pk))
            case.log_action(
                who=request.user,
                new_value='Remove from plan {}'.format(plan.pk))
            plan.delete_case(case=case)

        return JsonResponse({'rc': 0, 'response': 'ok'})
Exemple #10
0
        def case(self):
            from tcms.testcases.views import get_selected_testcases

            return self.template_name, get_selected_testcases(self.request)
Exemple #11
0
    def post(self, request):
        # If from_plan does not exist will redirect to plans for select a plan
        plan_id = request.POST.get('from_plan')
        if not plan_id:
            messages.add_message(
                request, messages.ERROR,
                _('Creating a TestRun requires a TestPlan, select one'))
            return HttpResponseRedirect(reverse('plans-search'))

        if not request.POST.get('case'):
            messages.add_message(
                request, messages.ERROR,
                _('Creating a TestRun requires at least one TestCase'))
            return HttpResponseRedirect(
                reverse('test_plan_url_short', args=[plan_id]))

        # Ready to write cases to test plan
        test_cases = get_selected_testcases(request)
        test_plan = TestPlan.objects.get(pk=plan_id)

        # note: ordered by pk for test_show_create_new_run_page()
        tcs_values = test_cases.select_related('author', 'case_status',
                                               'category',
                                               'priority').order_by('pk')

        if request.POST.get('POSTING_TO_CREATE'):
            form = NewRunForm(request.POST)
            form.populate(product_id=test_plan.product_id)

            if form.is_valid():
                # Process the data in form.cleaned_data
                default_tester = form.cleaned_data['default_tester']

                test_run = TestRun.objects.create(
                    product_version=test_plan.product_version,
                    stop_date=None,
                    summary=form.cleaned_data.get('summary'),
                    notes=form.cleaned_data.get('notes'),
                    plan=test_plan,
                    build=form.cleaned_data['build'],
                    manager=form.cleaned_data['manager'],
                    default_tester=default_tester,
                )

                loop = 1
                for case in form.cleaned_data['case']:
                    try:
                        tcp = TestCasePlan.objects.get(plan=test_plan,
                                                       case=case)
                        sortkey = tcp.sortkey
                    except ObjectDoesNotExist:
                        sortkey = loop * 10

                    test_run.create_execution(case=case,
                                              sortkey=sortkey,
                                              assignee=default_tester)
                    loop += 1

                return HttpResponseRedirect(
                    reverse('testruns-get', args=[
                        test_run.pk,
                    ]))

        else:
            form = NewRunForm(
                initial={
                    'summary': 'Test run for %s' % test_plan.name,
                    'manager': test_plan.author.email,
                    'default_tester': request.user.email,
                    'notes': '',
                })
            form.populate(product_id=test_plan.product_id)

        context_data = {
            'test_plan': test_plan,
            'test_cases': tcs_values,
            'form': form,
        }
        return render(request, self.template_name, context_data)
Exemple #12
0
def new(request):
    """Display the create test run page."""

    # If from_plan does not exist will redirect to plans for select a plan
    if not request.POST.get('from_plan'):
        messages.add_message(
            request, messages.ERROR,
            _('Creating a TestRun requires a TestPlan, select one'))
        return HttpResponseRedirect(reverse('plans-search'))

    plan_id = request.POST.get('from_plan')
    # case is required by a test run
    # NOTE: currently this is handled in JavaScript but in the TestRun creation
    # form cases can be deleted
    if not request.POST.get('case'):
        messages.add_message(
            request, messages.ERROR,
            _('Creating a TestRun requires at least one TestCase'))
        return HttpResponseRedirect(
            reverse('test_plan_url_short', args=[plan_id]))

    # Ready to write cases to test plan
    test_cases = get_selected_testcases(request)
    test_plan = TestPlan.objects.get(plan_id=plan_id)

    # note: ordered by case_id for test_show_create_new_run_page()
    tcs_values = test_cases.select_related('author', 'case_status', 'category',
                                           'priority').order_by('case_id')

    if request.POST.get('POSTING_TO_CREATE'):
        form = NewRunForm(request.POST)
        form.populate(product_id=test_plan.product_id)

        if form.is_valid():
            # Process the data in form.cleaned_data
            default_tester = form.cleaned_data['default_tester']

            test_run = TestRun.objects.create(
                product_version=test_plan.product_version,
                stop_date=None,
                summary=form.cleaned_data.get('summary'),
                notes=form.cleaned_data.get('notes'),
                plan=test_plan,
                build=form.cleaned_data['build'],
                manager=form.cleaned_data['manager'],
                default_tester=default_tester,
            )

            try:
                assignee_tester = User.objects.get(username=default_tester)
            except ObjectDoesNotExist:
                assignee_tester = None

            loop = 1
            for case in form.cleaned_data['case']:
                try:
                    tcp = TestCasePlan.objects.get(plan=test_plan, case=case)
                    sortkey = tcp.sortkey
                except ObjectDoesNotExist:
                    sortkey = loop * 10

                test_run.add_case_run(case=case,
                                      sortkey=sortkey,
                                      assignee=assignee_tester)
                loop += 1

            return HttpResponseRedirect(
                reverse('testruns-get', args=[
                    test_run.run_id,
                ]))

    else:
        form = NewRunForm(
            initial={
                'summary': 'Test run for %s' % test_plan.name,
                'manager': test_plan.author.email,
                'default_tester': request.user.email,
                'notes': '',
            })
        form.populate(product_id=test_plan.product_id)

    context_data = {
        'test_plan': test_plan,
        'test_cases': tcs_values,
        'form': form,
    }
    return render(request, 'testruns/mutable.html', context_data)
Exemple #13
0
 def get_update_targets(self):
     self._update_objects = get_selected_testcases(self.request)
     return self._update_objects
Exemple #14
0
def choose_run(request, plan_id, template_name='plan/choose_testrun.html'):
    """Choose one run to add cases"""

    # Define the default sub module
    SUB_MODULE_NAME = 'runs'
    if request.method == 'GET':
        try:
            plan_id = int(plan_id)
            tp = TestPlan.objects.filter(
                pk=plan_id).defer('product_version')[0]
        except IndexError:
            raise Http404

        testruns = TestRun.objects.filter(plan=plan_id).values(
            'pk', 'summary', 'build__name', 'manager__username')

        # Ready to write cases to test plan
        tcs = get_selected_testcases(request)
        tcs = tcs.values(
            'pk',
            'summary',
            'author__username',
            'create_date',
            'category__name',
            'priority__value',
        )

        context_data = {
            'module': MODULE_NAME,
            'sub_module': SUB_MODULE_NAME,
            'plan_id': plan_id,
            'plan': tp,
            'test_runs': testruns.iterator(),
            'test_cases': tcs.iterator(),
        }
        return render(request, template_name, context=context_data)

    # Add cases to runs
    if request.method == 'POST':
        choosed_testrun_ids = request.POST.getlist('testrun_ids')
        to_be_added_cases = TestCase.objects.filter(
            pk__in=request.POST.getlist('case_ids'))

        # cases and runs are required in this process
        if not len(choosed_testrun_ids) or not len(to_be_added_cases):
            return HttpResponse(
                Prompt.render(
                    request=request,
                    info_type=Prompt.Info,
                    info=
                    'At least one test run and one case is required to add cases to runs.',
                    next=reverse('plan-get', args=[plan_id]),
                ))

        # Adding cases to runs by recursion
        for tr_id in choosed_testrun_ids:
            testrun = get_object_or_404(TestRun, run_id=tr_id)
            cases = TestCaseRun.objects.filter(run=tr_id)
            exist_cases_id = cases.values_list('case', flat=True)

            for testcase in to_be_added_cases:
                if testcase.case_id not in exist_cases_id:
                    testrun.add_case_run(case=testcase)

            estimated_time = six.moves.reduce(
                lambda x, y: x + y,
                [nc.estimated_time for nc in to_be_added_cases])
            testrun.estimated_time = testrun.estimated_time + estimated_time
            testrun.save()

        return HttpResponseRedirect(reverse('plan-get', args=[plan_id]))
Exemple #15
0
 def case(self):
     return self.template_name, get_selected_testcases(self.request)
Exemple #16
0
    def get_testcases(self):
        from tcms.testcases.views import get_selected_testcases

        return get_selected_testcases(self.request)
Exemple #17
0
def choose_run(request, plan_id, template_name='plan/choose_testrun.html'):
    '''Choose one run to add cases'''

    if request.method == 'GET':
        try:
            plan_id = int(plan_id)
            tp = TestPlan.objects.filter(pk=plan_id).defer('product_version')[0]
        except IndexError:
            raise Http404

        testruns = TestRun.objects.filter(plan=plan_id).values('pk',
                                                               'summary',
                                                               'build__name',
                                                               'manager__username')

        # Ready to write cases to test plan
        tcs = get_selected_testcases(request)
        tcs = tcs.values('pk', 'summary',
                         'author__username',
                         'create_date',
                         'category__name',
                         'priority__value', )

        context_data = {
            'plan_id': plan_id,
            'plan': tp,
            'test_runs': testruns.iterator(),
            'test_cases': tcs.iterator(),
        }
        return render(request, template_name, context_data)

    # Add cases to runs
    if request.method == 'POST':
        chosen_testrun_ids = request.POST.getlist('testrun_ids')
        to_be_added_cases = TestCase.objects.filter(pk__in=request.POST.getlist('case_ids'))

        # Adding cases to runs by recursion
        cases_selected = 0
        for tr_id in chosen_testrun_ids:
            testrun = get_object_or_404(TestRun, run_id=tr_id)
            cases = TestCaseRun.objects.filter(run=tr_id)
            existing_cases = cases.values_list('case', flat=True)

            for testcase in to_be_added_cases:
                # counter used as a flag that runs or cases were selected
                # in the form, regardless of whether or not they were actually added
                # used to produce an error message if user clicked the Update button
                # without selecting anything on the screen
                cases_selected += 1
                if testcase.case_id not in existing_cases:
                    testrun.add_case_run(case=testcase)

            estimated_time = reduce(lambda x, y: x + y,
                                    [nc.estimated_time for nc in to_be_added_cases])
            testrun.estimated_time = testrun.estimated_time + estimated_time
            testrun.save()
        else:
            if not cases_selected:
                messages.add_message(request,
                                     messages.ERROR,
                                     _('Select at least one TestRun and one TestCase'))

        return HttpResponseRedirect(reverse('test_plan_url_short', args=[plan_id]))
Exemple #18
0
 def case(self):
     return self.template_name, get_selected_testcases(self.request)
Exemple #19
0
def new(request, template_name='run/new.html'):
    """Display the create test run page."""

    # If from_plan does not exist will redirect to plans for select a plan
    if not request.POST.get('from_plan'):
        return HttpResponseRedirect(reverse('plans-all'))

    plan_id = request.POST.get('from_plan')
    # case is required by a test run
    # NOTE: currently this is handled in JavaScript but in the TestRun creation
    # form cases can be deleted
    if not request.POST.get('case'):
        messages.add_message(
            request, messages.ERROR,
            _('Creating a TestRun requires at least one TestCase'))
        return HttpResponseRedirect(
            reverse('test_plan_url_short', args=[plan_id]))

    # Ready to write cases to test plan
    confirm_status = TestCaseStatus.get_CONFIRMED()
    test_cases = get_selected_testcases(request)
    # FIXME: optimize this query, only get necessary columns, not all fields
    # are necessary
    test_plan = TestPlan.objects.select_related().get(plan_id=plan_id)
    test_case_runs = TestCaseRun.objects.filter(
        case_run_id__in=request.POST.getlist('case_run_id'))

    num_unconfirmed_cases = test_cases.exclude(
        case_status=confirm_status).count()
    estimated_time = datetime.timedelta(seconds=0)

    tcs_values = test_cases.select_related('author', 'case_status', 'category',
                                           'priority')
    # note: ordered for test_show_create_new_run_page() on PostgreSQL
    tcs_values = tcs_values.only('case_id', 'summary', 'estimated_time',
                                 'author__email', 'create_date',
                                 'category__name', 'priority__value',
                                 'case_status__name').order_by('case_id')

    if request.POST.get('POSTING_TO_CREATE'):
        form = NewRunForm(request.POST)
        form.populate(
            product_id=request.POST.get('product', test_plan.product_id))

        if form.is_valid():
            # Process the data in form.cleaned_data
            default_tester = form.cleaned_data['default_tester']

            test_run = TestRun.objects.create(
                product_version=form.cleaned_data['product_version'],
                stop_date=None,
                summary=form.cleaned_data.get('summary'),
                notes=form.cleaned_data.get('notes'),
                plan=test_plan,
                build=form.cleaned_data['build'],
                manager=form.cleaned_data['manager'],
                default_tester=default_tester,
                estimated_time=form.cleaned_data['estimated_time'],
                auto_update_run_status=form.
                cleaned_data['auto_update_run_status'])

            keep_status = form.cleaned_data['keep_status']
            keep_assign = form.cleaned_data['keep_assignee']

            try:
                assignee_tester = User.objects.get(username=default_tester)
            except ObjectDoesNotExist:
                assignee_tester = None

            loop = 1

            # not reserve assignee and status, assignee will default set to
            # default_tester
            if not keep_assign and not keep_status:
                for case in form.cleaned_data['case']:
                    try:
                        tcp = TestCasePlan.objects.get(plan=test_plan,
                                                       case=case)
                        sortkey = tcp.sortkey
                    except ObjectDoesNotExist:
                        sortkey = loop * 10

                    test_run.add_case_run(case=case,
                                          sortkey=sortkey,
                                          assignee=assignee_tester)
                    loop += 1

            # Add case to the run
            for test_case_run in test_case_runs:
                if (keep_status and keep_assign):
                    test_run.add_case_run(
                        case=test_case_run.case,
                        assignee=test_case_run.assignee,
                        case_run_status=test_case_run.case_run_status,
                        sortkey=test_case_run.sortkey or loop * 10)
                    loop += 1
                elif keep_status and not keep_assign:
                    test_run.add_case_run(
                        case=test_case_run.case,
                        case_run_status=test_case_run.case_run_status,
                        sortkey=test_case_run.sortkey or loop * 10)
                    loop += 1
                elif keep_assign and not keep_status:
                    test_run.add_case_run(case=test_case_run.case,
                                          assignee=test_case_run.assignee,
                                          sortkey=test_case_run.sortkey
                                          or loop * 10)
                    loop += 1

            # Write the values into tcms_env_run_value_map table
            env_property_id_set = set(request.POST.getlist("env_property_id"))
            if env_property_id_set:
                args = list()
                for property_id in env_property_id_set:
                    checkbox_name = 'select_property_id_%s' % property_id
                    select_name = 'select_property_value_%s' % property_id
                    checked = request.POST.getlist(checkbox_name)
                    if checked:
                        env_values = request.POST.getlist(select_name)
                        if not env_values:
                            continue

                        if len(env_values) != len(checked):
                            raise ValueError('Invalid number of env values.')

                        for value_id in env_values:
                            args.append(
                                EnvRunValueMap(run=test_run,
                                               value_id=value_id))

                EnvRunValueMap.objects.bulk_create(args)

            return HttpResponseRedirect(
                reverse('testruns-get', args=[
                    test_run.run_id,
                ]))

    else:
        estimated_time = reduce(lambda x, y: x + y,
                                (tc.estimated_time for tc in tcs_values))
        form = NewRunForm(
            initial={
                'summary':
                'Test run for %s on %s' %
                (test_plan.name, test_plan.env_group.all()
                 and test_plan.env_group.all()[0] or 'Unknown environment'),
                'estimated_time':
                estimated_time,
                'manager':
                test_plan.author.email,
                'default_tester':
                request.user.email,
                'product':
                test_plan.product_id,
                'product_version':
                test_plan.product_version_id,
            })
        form.populate(product_id=test_plan.product_id)

    # FIXME: pagination cases within Create New Run page.
    context_data = {
        'from_plan': plan_id,
        'test_plan': test_plan,
        'test_cases': tcs_values,
        'form': form,
        'num_unconfirmed_cases': num_unconfirmed_cases,
        'run_estimated_time': estimated_time.total_seconds(),
    }
    return render(request, template_name, context_data)
Exemple #20
0
def choose_run(request, plan_id, template_name='plan/choose_testrun.html'):
    '''Choose one run to add cases'''

    # Define the default sub module
    SUB_MODULE_NAME = 'runs'
    if request.method == 'GET':
        try:
            plan_id = int(plan_id)
            tp = TestPlan.objects.filter(pk=plan_id).defer('product_version')[0]
        except IndexError:
            raise Http404

        testruns = TestRun.objects.filter(plan=plan_id).values('pk',
                                                               'summary',
                                                               'build__name',
                                                               'manager__username')

        # Ready to write cases to test plan
        tcs = get_selected_testcases(request)
        tcs = tcs.values('pk', 'summary',
                         'author__username',
                         'create_date',
                         'category__name',
                         'priority__value', )

        context_data = {
            'module': MODULE_NAME,
            'sub_module': SUB_MODULE_NAME,
            'plan_id': plan_id,
            'plan': tp,
            'test_runs': testruns.iterator(),
            'test_cases': tcs.iterator(),
        }
        return render_to_response(template_name, context_data,
                                  context_instance=RequestContext(request))

    # Add cases to runs
    if request.method == 'POST':
        choosed_testrun_ids = request.POST.getlist('testrun_ids')
        to_be_added_cases = TestCase.objects.filter(pk__in=request.POST.getlist('case_ids'))

        # cases and runs are required in this process
        if not len(choosed_testrun_ids) or not len(to_be_added_cases):
            return HttpResponse(Prompt.render(
                request=request,
                info_type=Prompt.Info,
                info='At least one test run and one case is required to add cases to runs.',
                next=reverse('tcms.testplans.views.get', args=[plan_id]),
            ))

        # Adding cases to runs by recursion
        for tr_id in choosed_testrun_ids:
            testrun = get_object_or_404(TestRun, run_id=tr_id)
            cases = TestCaseRun.objects.filter(run=tr_id)
            exist_cases_id = cases.values_list('case', flat=True)

            for testcase in to_be_added_cases:
                if testcase.case_id not in exist_cases_id:
                    testrun.add_case_run(case=testcase)

            estimated_time = reduce(lambda x, y: x + y,
                                    [nc.estimated_time for nc in to_be_added_cases])
            testrun.estimated_time = testrun.estimated_time + estimated_time
            testrun.save()

        return HttpResponseRedirect(reverse('tcms.testplans.views.get', args=[plan_id]))
Exemple #21
0
 def get_testcases(self):
     from tcms.testcases.views import get_selected_testcases
     return get_selected_testcases(self.request)
Exemple #22
0
def new(request, template_name='run/new.html'):
    """Display the create test run page."""

    SUB_MODULE_NAME = "new_run"

    # If from_plan does not exist will redirect to plans for select a plan
    if not request.POST.get('from_plan'):
        return HttpResponseRedirect(reverse('plans-all'))

    plan_id = request.POST.get('from_plan')
    # Case is required by a test run
    if not request.POST.get('case'):
        return prompt.info(request, 'At least one case is required by a run.',
                           reverse('plan-get', args=[plan_id]))

    # Ready to write cases to test plan
    confirm_status = TestCaseStatus.get('CONFIRMED')
    tcs = get_selected_testcases(request)
    # FIXME: optimize this query, only get necessary columns, not all fields
    # are necessary
    tp = TestPlan.objects.select_related().get(plan_id=plan_id)
    tcrs = TestCaseRun.objects.filter(
        case_run_id__in=request.POST.getlist('case_run_id'))

    num_unconfirmed_cases = tcs.exclude(case_status=confirm_status).count()
    estimated_time = datetime.timedelta(seconds=0)

    tcs_values = tcs.select_related('author', 'case_status',
                                    'category', 'priority').only(
                                        'case_id', 'summary', 'create_date',
                                        'estimated_time', 'author__email',
                                        'case_status__name', 'priority__value',
                                        'category__name').order_by('case_id')

    if request.POST.get('POSTING_TO_CREATE'):
        form = NewRunForm(request.POST)
        if request.POST.get('product'):
            form.populate(product_id=request.POST['product'])
        else:
            form.populate(product_id=tp.product_id)

        if form.is_valid():
            # Process the data in form.cleaned_data
            default_tester = form.cleaned_data['default_tester']

            tr = TestRun.objects.create(
                product_version=form.cleaned_data['product_version'],
                plan_text_version=tp.latest_text()
                and tp.latest_text().plan_text_version or 0,
                stop_date=None,
                summary=form.cleaned_data.get('summary'),
                notes=form.cleaned_data.get('notes'),
                plan=tp,
                build=form.cleaned_data['build'],
                manager=form.cleaned_data['manager'],
                default_tester=default_tester,
                estimated_time=form.cleaned_data['estimated_time'],
                auto_update_run_status=form.
                cleaned_data['auto_update_run_status'])

            keep_status = form.cleaned_data['keep_status']
            keep_assign = form.cleaned_data['keep_assignee']

            try:
                assignee_tester = User.objects.get(username=default_tester)
            except ObjectDoesNotExist:
                assignee_tester = None

            loop = 1

            # not reserve assignee and status, assignee will default set to
            # default_tester
            if not keep_assign and not keep_status:
                for case in form.cleaned_data['case']:
                    try:
                        tcp = TestCasePlan.objects.get(plan=tp, case=case)
                        sortkey = tcp.sortkey
                    except ObjectDoesNotExist:
                        sortkey = loop * 10

                    tr.add_case_run(case=case,
                                    sortkey=sortkey,
                                    assignee=assignee_tester)
                    loop += 1

            # Add case to the run
            for tcr in tcrs:
                if (keep_status and keep_assign):
                    tr.add_case_run(case=tcr.case,
                                    assignee=tcr.assignee,
                                    case_run_status=tcr.case_run_status,
                                    sortkey=tcr.sortkey or loop * 10)
                    loop += 1
                elif keep_status and not keep_assign:
                    tr.add_case_run(case=tcr.case,
                                    case_run_status=tcr.case_run_status,
                                    sortkey=tcr.sortkey or loop * 10)
                    loop += 1
                elif keep_assign and not keep_status:
                    tr.add_case_run(case=tcr.case,
                                    assignee=tcr.assignee,
                                    sortkey=tcr.sortkey or loop * 10)
                    loop += 1

            # Write the values into tcms_env_run_value_map table
            env_property_id_set = set(request.POST.getlist("env_property_id"))
            if env_property_id_set:
                args = list()
                for property_id in env_property_id_set:
                    checkbox_name = 'select_property_id_%s' % property_id
                    select_name = 'select_property_value_%s' % property_id
                    checked = request.POST.getlist(checkbox_name)
                    if checked:
                        env_values = request.POST.getlist(select_name)
                        if not env_values:
                            continue

                        if len(env_values) != len(checked):
                            raise ValueError('Invalid number of env values.')

                        for value_id in env_values:
                            args.append(
                                TCMSEnvRunValueMap(run=tr, value_id=value_id))

                TCMSEnvRunValueMap.objects.bulk_create(args)

            return HttpResponseRedirect(reverse('run-get', args=[tr.run_id]))

    else:
        estimated_time = functools.reduce(operator.add, (tc.estimated_time
                                                         for tc in tcs_values))
        form = NewRunForm(
            initial={
                'summary':
                'Test run for {} on {}'.format(
                    tp.name,
                    tp.env_group.all() and tp.env_group.all()[0]
                    or 'Unknown environment'),
                'estimated_time':
                format_timedelta(estimated_time),
                'manager':
                tp.author.email,
                'default_tester':
                request.user.email,
                'product':
                tp.product_id,
                'product_version':
                tp.product_version_id,
            })
        form.populate(product_id=tp.product_id)

    # FIXME: pagination cases within Create New Run page.
    context_data = {
        'module': MODULE_NAME,
        'sub_module': SUB_MODULE_NAME,
        'from_plan': plan_id,
        'test_plan': tp,
        'test_cases': tcs_values,
        'form': form,
        'num_unconfirmed_cases': num_unconfirmed_cases,
        'run_estimated_time': estimated_time,
    }
    return render(request, template_name, context=context_data)