コード例 #1
0
ファイル: result.py プロジェクト: slickqa/slickqaweb
def apply_triage_notes(result, testcase=None):
    """This function checks to see if a result should have triage notes, and adds them if need be.
    If the result's status is a non-final result, then it will be ignored.

    You can optionally pass in a testcase (if you have already looked one up), if you do not, it will be looked up.

    :param result: The result to check
    :type result: slickqa.model.result.Result
    :param testcase: A testcase that has been looked up from the database.
    :type testcase: slickqa.model.testcase.Testcase
    :returns: Nothing
    """
    # if the test isn't finished yet just return
    if result.status in NON_FINAL_STATUS:
        return

    # if the test is finished, but they didn't pass in the testcase, find it
    if testcase is None:
        testcase = find_testcase_by_reference(result.testcase)

    # if we still don't know the testcase we can't apply any triage notes
    if testcase is None:
        return

    assert isinstance(testcase, Testcase)

    # if there are no active notes on the testcase, move on
    if is_not_provided(testcase, 'activeNotes'):
        return

    # go through each active triage note, check to see if it matches
    notes_to_remove = []
    for activeNote in testcase.activeNotes:
        assert isinstance(activeNote, RecurringNote)
        # check to see if the environment matches
        if is_provided(activeNote, 'environment'):
            if is_not_provided(result, 'config') or is_not_provided(result.config, 'configId') or \
               activeNote.environment.configId != result.config.configId:
                continue

        # check to see if the release matches
        if is_provided(activeNote, 'release'):
            if is_not_provided(result, 'release') or is_not_provided(result.release, 'releaseId') or \
               activeNote.release.releaseId != result.release.releaseId:
                continue

        # at this point it matches
        if result.status == 'PASS':
            # update the note to be inactive
            notes_to_remove.append(activeNote)
        else:
            # apply the triage note
            if is_not_provided(result, 'log'):
                result.log = []
            logentry = LogEntry()
            logentry.entryTime = datetime.datetime.now()
            logentry.level = 'WARN'
            logentry.loggerName = 'slick.note'
            logentry.message = activeNote.message
            if is_provided(activeNote, 'url'):
                logentry.exceptionMessage = activeNote.url
            result.log.append(logentry)

    # move any notes that are no longer active (because the test passed) to the inactiveNotes section
    if len(notes_to_remove) > 0:
        # if we are modifying the testcase we need to generate an event
        update_event = events.UpdateEvent(before=testcase)
        for note in notes_to_remove:
            # remove from activeNotes and put in inactiveNotes
            testcase.activeNotes.remove(note)
            if is_not_provided(testcase, 'inactiveNotes'):
                testcase.inactiveNotes = []
            testcase.inactiveNotes.append(note)
            # set the inactivatedBy field to this result
            note.inactivatedBy = create_result_reference(result)
        update_event.after(testcase)
        testcase.save()
コード例 #2
0
ファイル: result.py プロジェクト: slickqa/slickqaweb
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)