示例#1
0
def update_result(result_id):
    """Update an individual result."""
    orig = Result.objects(id=result_id).first()
    update_event = events.UpdateEvent(before=orig)
    update = read_request()
    print((repr(update)))

    if 'status' in update and update['status'] != None and update['status'] != orig.status:
        atomic_update = {
            'dec__summary__resultsByStatus__' + orig.status: 1,
            'inc__summary__resultsByStatus__' + update['status']: 1
        }
        update_testrun_event = None
        testrun = None
        if app.config['events']:
            testrun = Testrun.objects(id=orig.testrun.testrunId).first()
            update_testrun_event = events.UpdateEvent(before=testrun)
        Testrun.objects(id=orig.testrun.testrunId).update_one(**atomic_update)
        if app.config['events']:
            testrun.reload()
            update_testrun_event.after(testrun)
    deserialize_that(update, orig)
    apply_triage_notes(orig)
    orig.save()
    update_event.after(orig)
    return JsonResponse(orig)
示例#2
0
def cancel_individual_result(result_id):
    """Reschedule a single result, only works on a result that was originally scheduled."""
    orig = Result.objects(id=result_id).first()
    orig_status = orig.status
    if orig_status == "NO_RESULT":
        decrement_orig_status_by = "dec__summary__resultsByStatus__" + orig_status
        increment_skipped_status_by = "inc__summary__resultsByStatus__SKIPPED"
        Testrun.objects(id=orig.testrun.testrunId).update_one(**{decrement_orig_status_by: 1, increment_skipped_status_by: 1})
    Result.objects(id=result_id).update(runstatus="FINISHED", status="SKIPPED", reason="Run cancelled from slick.")
    orig.reload()
    return JsonResponse(orig)
示例#3
0
def reschedule_individual_result(result_id):
    """Reschedule a single result, only works on a result that was originally scheduled."""
    orig = Result.objects(id=result_id).first()
    orig_status = orig.status
    if orig_status != "NO_RESULT":
        decrement_orig_status_by = "dec__summary__resultsByStatus__" + orig_status
        increment_noresult_status_by = "inc__summary__resultsByStatus__NO_RESULT"
        Testrun.objects(id=orig.testrun.testrunId).update_one(**{decrement_orig_status_by: 1, increment_noresult_status_by: 1})
    Result.objects(id=result_id).update(log=[], files=[], runstatus="SCHEDULED", status="NO_RESULT",
                                        unset__hostname=True, unset__started=True, unset__finished=True,
                                        unset__runlength=True, unset__reason=True)
    orig.reload()
    return JsonResponse(orig)
示例#4
0
def cancel_results_from_testrun(testrun_id):
    """Cancel all results that are scheduled for this testrun."""
    testrun = Testrun.objects(id=testrun_id).first()
    results_to_cancel = Result.objects(testrun__testrunId=testrun.id, status='NO_RESULT', runstatus__in=['SCHEDULED', 'TO_BE_RUN'])
    for result in results_to_cancel:
        cancel_individual_result(result.id)
    return JsonResponse(Result.objects(testrun__testrunId=testrun.id, status="FINISHED", runstatus="SKIPPED"))
示例#5
0
def get_build_reports(project_name, release_name):
    """Get all summary of all the builds for a particular release."""
    limit = 15
    if request.args.get("limit"):
        try:
            limit = int(request.args.get("limit"))
        except:
            pass
    groupType = "SERIAL"
    if request.args.get("groupType"):
        groupType = request.args.get("groupType")
    project_id, release_id, build_id = Project.lookup_project_release_build_ids(project_name, release_name, None, get_all_builds=True, limit=limit)
    report = {}
    report['name'] = "Release Report for {} {}".format(project_name, release_name)
    report['builds'] = []
    report['grouptype'] = groupType
    if build_id is None:
        return JsonResponse({})
    for build_object in build_id:
        testrun_group = TestrunGroup()
        testrun_group.name = "Build Report for {} {} Build {}".format(project_name, release_name, build_object['name'])
        testrun_group.grouptype = groupType
        testrun_group.testruns = Testrun.objects(build__buildId=build_object['id']).order_by("-dateCreated")
        report['builds'].append(testrun_group)
    return JsonResponse(report)
示例#6
0
def cancel_individual_result(result_id):
    """Reschedule a single result, only works on a result that was originally scheduled."""
    orig = Result.objects(id=result_id).first()
    orig_status = orig.status
    if orig_status == "NO_RESULT":
        decrement_orig_status_by = "dec__summary__resultsByStatus__" + orig_status
        increment_skipped_status_by = "inc__summary__resultsByStatus__SKIPPED"
        Testrun.objects(id=orig.testrun.testrunId).update_one(**{decrement_orig_status_by: 1, increment_skipped_status_by: 1})
        testrun = Testrun.objects(id=orig.testrun.testrunId).first()
        if testrun and testrun.summary.resultsByStatus.NO_RESULT == 0:
            # finish testrun
            testrun.runFinished = datetime.datetime.utcnow()
            testrun.state = "FINISHED"
            Testrun.objects(id=orig.testrun.testrunId).update_one(runFinished=testrun.runFinished, state=testrun.state)
    reason = request.args.get("reason") if request.args.get("reason") else "Run cancelled from slick."
    Result.objects(id=result_id).update(runstatus="FINISHED", status="SKIPPED", reason=reason)
    orig.reload()
    return JsonResponse(orig)
示例#7
0
def find_testrun_by_reference(ref):
    """Find a testrun using a testrun reference instance.

    A testrun reference contains the name and the id, and those will be used to find
    the testrun.

    :param ref: a slickqaweb.model.testrunReference.TestrunReference instance
    :return: An instance of Testrun from mongo if found, None otherwise
    """
    if ref is None:
        return None
    assert isinstance(ref, TestrunReference)
    retval = None
    if ref.testrunId is not None:
        retval = Testrun.objects(id=ref.testrunId).first()
    if retval is None and ref.name is not None and ref.name != '':
        retval = Testrun.objects(name=ref.name).first()
    return retval
示例#8
0
def add_testrun_to_testrun_group(testrungroup_id, testrun_id):
    """Add a testrun to a testrun group"""
    orig = TestrunGroup.objects(id=ObjectId(testrungroup_id)).first()
    testrun = Testrun.objects(id=ObjectId(testrun_id)).first()
    if (not hasattr(orig, 'testruns')) or orig.testruns is None:
        orig.testruns = []
    orig.testruns.append(testrun)
    orig.save()
    return JsonResponse(orig)
示例#9
0
def update_testrun(testrun_id):
    """Update the properties of a testrun."""
    orig = Testrun.objects(id=testrun_id).first()
    update_event = events.UpdateEvent(before=orig)
    deserialize_that(read_request(), orig)
    if orig.state == "FINISHED" and is_not_provided(orig, 'runFinished'):
        orig.runFinished = datetime.datetime.utcnow()
    orig.save()
    update_event.after(orig)
    return JsonResponse(orig)
示例#10
0
def reschedule_results_with_status_on_build(project_name, release_name, build_name, status):
    """Reschedule all results with a particular status for a build."""
    project_id, release_id, build_id = Project.lookup_project_release_build_ids(project_name, release_name, build_name)

    rescheduled_results = []
    if build_id is None:
        return JsonResponse(None)
    for testrun in Testrun.objects(build__buildId=build_id).order_by("-dateCreated"):
        results_to_reschedule = Result.objects(testrun__testrunId=testrun.id, status=status)
        rescheduled_results.extend(results_to_reschedule)
        for result in results_to_reschedule:
            reschedule_individual_result(result.id)
    return JsonResponse(rescheduled_results)
示例#11
0
def cancel_results_for_build(project_name, release_name, build_name):
    """Cancel all results that are scheduled for this build."""
    project_id, release_id, build_id = Project.lookup_project_release_build_ids(project_name, release_name, build_name)

    canceled_results = []
    if build_id is None:
        return JsonResponse(None)
    for testrun in Testrun.objects(build__buildId=build_id).order_by("-dateCreated"):
        results_to_cancel = Result.objects(testrun__testrunId=testrun.id, status='NO_RESULT', runstatus__in=['SCHEDULED', 'TO_BE_RUN'])
        canceled_results.extend(results_to_cancel)
        for result in results_to_cancel:
            cancel_individual_result(result.id)
    return JsonResponse(canceled_results)
示例#12
0
def delete_testrun(testrun_id):
    """Remove a testrun."""
    orig = Testrun.objects(id=testrun_id).first()

    # delete the reference from any testrun groups
    trdbref = bson.DBRef('testruns', bson.ObjectId("531e4d26ded43258823d9c3a"))
    TestrunGroup.objects(__raw__={'testruns': {'$elemMatch': trdbref}}).update(pull__testruns=trdbref)

    # add an event
    events.DeleteEvent(orig)

    orig.delete()
    return JsonResponse(orig)
示例#13
0
def reschedule_individual_result(result_id):
    """Reschedule a single result, only works on a result that was originally scheduled."""
    orig = Result.objects(id=result_id).first()
    orig_status = orig.status
    log = []
    if orig.log:
        log = orig.log
    if 'retry_count' in orig.attributes:
        orig.attributes['retry_count'] = str(int(orig.attributes['retry_count']) + 1)
    else:
        orig.attributes['retry_count'] = "1"
    if 'max_retry' not in orig.attributes:
        orig.attributes['max_retry'] = "3"
    if orig_status != "NO_RESULT":
        decrement_orig_status_by = "dec__summary__resultsByStatus__" + orig_status
        increment_noresult_status_by = "inc__summary__resultsByStatus__NO_RESULT"
        Testrun.objects(id=orig.testrun.testrunId).update_one(**{decrement_orig_status_by: 1, increment_noresult_status_by: 1})
    log.append({"entryTime": datetime.datetime.utcnow(), "level": "INFO", "loggerName": "slick.note", "message": "Rescheduled. Count: {}. Max: {}    {}    {}".format(orig.attributes['retry_count'], orig.attributes['max_retry'], orig.hostname, orig.reason), "exceptionMessage": ""})
    Result.objects(id=result_id).update(log=log, files=[], links=[], runstatus="SCHEDULED", status="NO_RESULT", recorded=datetime.datetime.utcnow(),
                                        unset__hostname=True, unset__started=True, unset__finished=True,
                                        unset__runlength=True, unset__reason=True, attributes=orig.attributes)
    orig.reload()
    return JsonResponse(orig)
示例#14
0
def get_build_report(project_name, release_name, build_name):
    """Get all summary of all the testruns run against a particular build."""
    project_id, release_id, build_id = Project.lookup_project_release_build_ids(project_name, release_name, build_name)

    report = TestrunGroup()
    report.name = "Build Report for {} {} Build {}".format(project_name, release_name, build_name)
    report.grouptype = "PARALLEL"
    report.testruns = []
    testplans = []
    for testrun in Testrun.objects(build__buildId=build_id).order_by("-dateCreated"):
        assert isinstance(testrun, Testrun)
        if testrun.testplanId not in testplans:
            report.testruns.append(testrun)
            testplans.append(testrun.testplanId)

    return JsonResponse(report)
示例#15
0
def get_tps_report(project_name, release_name, testplan_name):
    """Get all summary of all the testruns run against a particular build."""
    project_id, release_id, _ = Project.lookup_project_release_build_ids(project_name, release_name, None)
    testplan = TestPlan.objects(project__id=project_id, name=testplan_name)
    if len(testplan) > 0:
        testplan = testplan[0]
        report = TestrunGroup()
        report.name = "{} Summary for {}".format(testplan_name, release_name)
        report.grouptype = "SERIAL"
        report.testruns = []
        report.testruns.extend(Testrun.objects(project__id=project_id, release__releaseId=release_id, testplanId=testplan.id).order_by('-dateCreated').limit(50))
        report.testruns.reverse()

        return JsonResponse(report)
    else:
        return JsonResponse({})
示例#16
0
def reschedule_results_with_status_on_testrun(testrun_id, status):
    """Reschedule all results with a particular status for a testrun."""
    testrun = Testrun.objects(id=testrun_id).first()
    results_to_reschedule = Result.objects(testrun__testrunId=testrun.id, status=status)
    for result in results_to_reschedule:
        reschedule_individual_result(result.id)

    # how_many = Result.objects(testrun__testrunId=testrun.id, status=status).update(log=[], files=[],
    #                                                                                runstatus="SCHEDULED",
    #                                                                                status="NO_RESULT",
    #                                                                                unset__hostname=True,
    #                                                                                unset__started=True,
    #                                                                                unset__finished=True,
    #                                                                                unset__runlength=True,
    #                                                                                unset__reason=True)
    # setattr(testrun.summary.resultsByStatus, status, getattr(testrun.summary.resultsByStatus, status) - how_many)
    # testrun.summary.resultsByStatus.NO_RESULT += how_many
    # testrun.save()
    return JsonResponse(Result.objects(testrun__testrunId=testrun.id, status="NO_RESULT", runstatus="SCHEDULED"))
示例#17
0
def get_build_report(project_name, release_name, build_name):
    """Get all summary of all the testruns run against a particular build."""
    project_id, release_id, build_id = Project.lookup_project_release_build_ids(project_name, release_name, build_name)

    report = TestrunGroup()
    report.name = "Build Report for {} {} Build {}".format(project_name, release_name, build_name)
    report.grouptype = "PARALLEL"
    report.testruns = []
    testplans = []
    if build_id is None:
        return JsonResponse(None)
    for testrun in Testrun.objects(build__buildId=build_id).order_by("-dateCreated"):
        assert isinstance(testrun, Testrun)
        if testrun.testplanId not in testplans:
            report.testruns.append(testrun)
            testplans.append(testrun.testplanId)
    if report.state() == "FINISHED" and not report.finished:
        report.finished = datetime.datetime.utcnow()
        # report.save() Warning, be careful not to do this, build reports don't get saved
        # this will create a new testrungroup every time the build report is
        # queried
    return JsonResponse(report)
示例#18
0
def add_result(testrun_id=None):
    """Create a new result."""
    raw = read_request()
    new_result = deserialize_that(raw, Result())
    assert isinstance(new_result, Result)

    # validate --------------------------------------------------------------
    # you must have a testcase reference (some info about the testcase) and a
    # status for the result.  Otherwise it's not really a result.
    errors = []
    if is_not_provided(new_result, 'status'):
        errors.append("status must be set")
    if is_not_provided(new_result, 'testcase') or (is_not_provided(new_result.testcase, 'name') and
                                               is_not_provided(new_result.testcase, 'testcaseId') and
                                               is_not_provided(new_result.testcase, 'automationId') and
                                               is_not_provided(new_result.testcase, 'automationKey')):
        errors.append("testcase must be provided with at least one identifying piece of data")
    if len(errors) > 0:
        return Response('\r\n'.join(errors), status=400, mimetype="text/plain")

    # fill in defaults -------------------------------------------------------
    # a few fields can easily be inferred or set to a default

    if is_not_provided(new_result, 'runstatus'):
        if new_result.status == "NO_RESULT":
            new_result.runstatus = "TO_BE_RUN"
        else:
            new_result.runstatus = "FINISHED"
    if is_not_provided(new_result, 'recorded'):
        new_result.recorded = datetime.datetime.utcnow()

    # resolve references -----------------------------------------------------
    testrun = None
    project = None
    testcase = None
    release = None
    build = None
    component = None
    configuration = None

    if testrun_id is not None:
        testrun = Testrun.objects(id=testrun_id).first()
        if testrun is not None:
            new_result.testrun = create_testrun_reference(testrun)

    # the order in this section is important.  We try to find information any way we can,
    # so if it's not provided in the result, we look at the testrun, if it's not in the testrun,
    # but it is in the testcase we get it from there.

    # first lookup the testrun and resolve it if we can
    if is_provided(new_result, 'testrun') and testrun is None:
        testrun = find_testrun_by_reference(new_result.testrun)
        # don't create a new testrun if it's null, we'll do that later after we resolve the other
        # pieces of information

    # try to resolve the testcase, we won't try to create it if it's none yet.
    # for that we need to resolve as much of the other information we can.
    testcase = find_testcase_by_reference(new_result.testcase)

    # try to find the project from the data provided in the result.  If that doesn't work,
    # and we do have a testrun, see if we can get it from there.  If we do have a name of a
    # project and we still haven't found the project, create it!
    if is_provided(new_result, 'project'):
        project = find_project_by_reference(new_result.project)
        if project is None and testrun is not None and is_provided(testrun, 'project'):
            project = find_project_by_reference(testrun.project)
        if project is None and is_provided(new_result.project, 'name'):
            project = Project()
            project.name = new_result.project.name
            project.save()

    # if they didn't provide any project data, but did provide testrun data, try
    # to resolve the project from the testrun
    if project is None and testrun is not None and is_provided(testrun, 'project'):
        project = find_project_by_reference(testrun.project)

    # if we couldn't resolve the project previously, but we can resolve the testcase
    # see if we can get the project from the testcase
    if project is None and testcase is not None and is_provided(testcase, 'project'):
        project = find_project_by_reference(testcase.project)


    # finally, make sure that the reference we have in the result has all the info in it
    if project is not None:
        new_result.project = create_project_reference(project)

    # resolve the component
    if is_provided(new_result, 'component'):
        if project is not None:
            component = find_component_by_reference(project, new_result.component)
            if component is None:
                component = Component()
                component.id = ObjectId()
                component.name = new_result.component.name
                if is_provided(new_result.component, 'code'):
                    component.code = new_result.component.code
                else:
                    component.code = component.name.lower().replace(' ', '-')
                project.components.append(component)
                project.save()
    if component is not None:
        new_result.component = create_component_reference(component)

    # create a testcase if needed
    if testcase is None and is_not_provided(new_result.testcase, 'name'):
        return Response('Existing testcase not found, please provide a testcase name if you want one to be created.\n', status=400, mimetype="text/plain")
    elif testcase is None:
        testcase = Testcase()
        testcase.created = datetime.datetime.utcnow()
        testcase.name = new_result.testcase.name
        if is_provided(new_result.testcase, 'automationId'):
            testcase.automationId = new_result.testcase.automationId
        if is_provided(new_result.testcase, 'automationKey'):
            testcase.automationKey = new_result.testcase.automationKey
        if project is not None:
            testcase.project = create_project_reference(project)
        if component is not None:
            testcase.component = create_component_reference(component)
        testcase.save()
    testcase_changed = False
    if 'steps' in raw['testcase']:
        testcase.steps = []
        for raw_step in raw['testcase']['steps']:
            step = deserialize_that(raw_step, Step())
            testcase.steps.append(step)
        testcase_changed = True
    if 'purpose' in raw['testcase']:
        testcase.purpose = raw['testcase']['purpose']
        testcase_changed = True
    if 'requirements' in raw['testcase']:
        testcase.requirements = raw['testcase']['requirements']
        testcase_changed = True
    if 'author' in raw['testcase']:
        testcase.author = raw['testcase']['author']
        testcase_changed = True
    # TODO: feature and automationTool

    if testcase_changed:
        testcase.save()

    # no matter what testcase should not be None at this point, but just in case I made a mistake
    if testcase is None:
        return Response('Somehow I was unable to find or create a testcase for this result.\n', status=400, mimetype="text/plain")
    new_result.testcase = create_testcase_reference(testcase)

    # dereference release and build if possible
    if is_provided(new_result, 'release') and project is not None:
        release = find_release_by_reference(project, new_result.release)
    if release is None and testrun is not None and project is not None and is_provided(testrun, 'release'):
        release = find_release_by_reference(project, testrun.release)
    if release is None and project is not None and is_provided(new_result, 'release') and is_provided(new_result.release, 'name'):
        release = Release()
        release.id = ObjectId()
        release.name = new_result.release.name
        project.releases.append(release)
        project.save()
    if release is not None:
        new_result.release = create_release_reference(release)
        if is_provided(new_result, 'build'):
            build = find_build_by_reference(release, new_result.build)
        if build is None and testrun is not None and is_provided(testrun, 'build'):
            build = find_build_by_reference(release, testrun.build)
        if build is None and project is not None and is_provided(new_result, 'build') and is_provided(new_result.build, 'name'):
            build = Build()
            build.id = ObjectId()
            build.name = new_result.build.name
            build.built = datetime.datetime.utcnow()
            release.builds.append(build)
            project.save()
        if build is not None:
            new_result.build = create_build_reference(build)

    # dereference configuration
    if is_provided(new_result, 'config'):
        configuration = find_configuration_by_reference(new_result.config)
    if configuration is None and testrun is not None and is_provided(testrun, 'config'):
        configuration = find_configuration_by_reference(testrun.config)
    if configuration is None and is_provided(new_result, 'config') and is_provided(new_result.config, 'name'):
        configuration = Configuration()
        configuration.name = new_result.config.name
        if is_provided(new_result.config, 'filename'):
            configuration.filename = new_result.config.filename
        configuration.save()
    if configuration is not None:
        new_result.config = create_configuration_reference(configuration)

    # if there is no testrun, create one with the information provided
    if testrun is None:
        testrun = Testrun()
        if is_provided(new_result, 'testrun') and is_provided(new_result.testrun, 'name'):
            testrun.name = new_result.testrun.name
        else:
            testrun.name = 'Testrun starting %s' % str(datetime.datetime.utcnow())
        if project is not None:
            testrun.project = create_project_reference(project)
        if configuration is not None:
            testrun.config = create_configuration_reference(configuration)
        if release is not None:
            testrun.release = create_release_reference(release)
        if build is not None:
            testrun.build = create_build_reference(build)
        testrun.dateCreated = datetime.datetime.utcnow()
        testrun.runStarted = datetime.datetime.utcnow()
        testrun.state = 'RUNNING'
        testrun.save()

    if testrun is not None:
        new_result.testrun = create_testrun_reference(testrun)

        status_name = "inc__summary__resultsByStatus__" + new_result.status
        Testrun.objects(id=testrun.id).update_one(**{status_name: 1})

    apply_triage_notes(new_result, testcase)
    new_result.history, estimatedRuntime = find_history(new_result)
    if new_result.attributes is None:
        new_result.attributes = {}
    new_result.attributes['estimatedRuntime'] = str(estimatedRuntime)
    new_result.save()

    events.CreateEvent(new_result)
    return JsonResponse(new_result)
示例#19
0
def get_testrun_by_id(testrun_id):
    """Retrieve a testrun using it's id."""
    return JsonResponse(Testrun.objects(id=testrun_id).first())