wisedog/ladybug

View on GitHub
controllers/testexecs.go

Summary

Maintainability
B
4 hrs
Test Coverage
package controllers

import (
    "net/http"
    "strconv"
    "strings"

    "github.com/gorilla/mux"
    "github.com/wisedog/ladybug/errors"
    "github.com/wisedog/ladybug/interfacer"
    "github.com/wisedog/ladybug/models"

    log "gopkg.in/inconshreveable/log15.v2"
)

//ExecIndex renders A page to show all test executions
func ExecIndex(c *interfacer.AppContext, w http.ResponseWriter, r *http.Request) error {

    var prj models.Project
    if err := c.Db.Where("name = ?", c.ProjectName).First(&prj); err.Error != nil {
        log.Error("TestPlan", "type", "database", "msg ", err.Error)
        return errors.HttpError{Status: http.StatusInternalServerError,
            Desc: "An error while find project in ExecIndex.Index"}
    }

    var testexecs []models.Execution

    c.Db.Preload("Plan").Preload("Executor").Preload("TargetBuild").Where("project_id = ?", prj.ID).Find(&testexecs)

    //Update progress
    for idx := 0; idx < len(testexecs); idx++ {
        prg := float32(testexecs[idx].PassCaseNum+testexecs[idx].FailCaseNum) / float32(testexecs[idx].TotalCaseNum) * 100
        testexecs[idx].Progress = int(prg)
    }

    items := map[string]interface{}{
        "TestExecs":  testexecs,
        "Active_idx": 5,
    }
    return Render2(c, w, items, "views/base.tmpl", "views/testexecs/execindex.tmpl")
}

// ExecDone is a POST Handler for Done button of test execution.
// This function ensures that all test cases are executed.
func ExecDone(c *interfacer.AppContext, w http.ResponseWriter, r *http.Request) error {

    if err := r.ParseForm(); err != nil {
        log.Error("TestExec", "type", "http", "msg ", err)
        return errors.HttpError{Status: http.StatusInternalServerError, Desc: "ParseForm failed"}
    }

    execID := r.FormValue("exec_id")
    //comment := r.FormValue("comment")

    var prj models.Project

    if err := c.Db.Where("name = ?", c.ProjectName).First(&prj); err.Error != nil {
        log.Error("TestExec", "type", "database", "msg ", err.Error)
        return RenderJSONWithStatus(w, Resp{Msg: "Find Project failed in TestExecs.Done"}, http.StatusInternalServerError)
    }

    var testexec models.Execution
    if err := c.Db.Preload("Plan").Where("id = ?", execID).First(&testexec); err.Error != nil {
        log.Error("TestExec", "type", "database", "msg ", err.Error)
        return RenderJSONWithStatus(w, Resp{Msg: "Find Test Execution entity failed in TestExecs.Done"},
            http.StatusInternalServerError)
    }

    // validation this execution is finished.
    // first, just verify that (PassCaseNum + FailCaseNum == TotalCaseNum)
    if testexec.PassCaseNum+testexec.FailCaseNum < testexec.TotalCaseNum {
        return RenderJSONWithStatus(w, Resp{Msg: "Not complete test execution."}, http.StatusInternalServerError)
    }
    // TODO below second, find all test results of this test execution and count
    count := 0
    c.Db.Model(&models.TestCaseResult{}).Count(&count)
    if count != testexec.TotalCaseNum {
        return RenderJSONWithStatus(w, Resp{Msg: "Not complete test execution."}, http.StatusInternalServerError)
    }

    if testexec.FailCaseNum > 0 {
        testexec.Status = models.ExecStatusFail
    } else {
        testexec.Status = models.ExecStatusPass
    }

    if err := c.Db.Model(&testexec).Update("status", testexec.Status); err.Error != nil {
        log.Error("TestExec", "type", "database", "msg ", err.Error)
        return RenderJSONWithStatus(w, Resp{Msg: "Update Test Execution entity failed in TestExecs.Done"},
            http.StatusInternalServerError)
    }

    return RenderJSONWithStatus(w, Resp{Msg: "OK"}, http.StatusOK)
}

// ExecUpdateResult updates the result of each test case
func ExecUpdateResult(c *interfacer.AppContext, w http.ResponseWriter, r *http.Request) error {
    var rv models.TestCaseResult

    if err := r.ParseForm(); err != nil {
        log.Error("TestExec", "type", "http", "msg ", err)
        return errors.HttpError{Status: http.StatusInternalServerError, Desc: "ParseForm failed"}
    }

    execIDStr := r.FormValue("exec_id")
    execID, _ := strconv.Atoi(execIDStr)
    caseIDStr := r.FormValue("case_id")
    caseID, _ := strconv.Atoi(caseIDStr)
    resultStr := r.FormValue("result")
    result, _ := strconv.ParseBool(resultStr)
    actual := r.FormValue("actual")
    caseVerStr := r.FormValue("case_ver")
    caseVer, _ := strconv.Atoi(caseVerStr)

    var exec models.Execution

    if err := c.Db.Where("id = ?", execID).First(&exec); err.Error != nil {
        log.Error("An error while on finding test result in TestExecs.calculateProgress")
        return RenderJSONWithStatus(w, Resp{Msg: "An error while on finding test result in TestExecs.calculateProgress"},
            http.StatusInternalServerError)
    }

    var rvTmp []models.TestCaseResult

    c.Db.Where("exec_id = ? and test_case_id = ?", execID, caseID).Find(&rvTmp)

    // if there is no exist test result
    if len(rvTmp) == 0 {
        rv.TestCaseID = caseID
        rv.ExecID = execID
        rv.Status = result
        rv.Actual = actual
        rv.TestCaseVer = caseVer

        //TODO validation
        c.Db.NewRecord(rv)

        if err := c.Db.Create(&rv); err.Error != nil {
            log.Error("Insert operation failed in TestExecs.UpdateResult")
            return RenderJSONWithStatus(w, Resp{Msg: "Insert operation failed in TestExecs.UpdateResult"},
                http.StatusInternalServerError)
        }

        //set exec's status ready to in progress
        exec.Status = models.ExecStatusInProgress
        if rv.Status == true {
            exec.PassCaseNum = exec.PassCaseNum + 1
        } else {
            exec.FailCaseNum = exec.FailCaseNum + 1
        }

        c.Db.Save(&exec)

    } else {
        if err := c.Db.Where("exec_id = ? and test_case_id = ?", execID, caseID).First(&rv); err.Error != nil {
            log.Error("Select operation failed in TestExecs.UpdateResult")
            return RenderJSONWithStatus(w, Resp{Msg: "Select operation failed in TestExecs.UpdateResult"},
                http.StatusInternalServerError)
        }

        if rv.Status == true {
            if result == true {
                // same value. not updated
            } else {
                // update. decrease execution.passcounter and increase failcounter
                exec.PassCaseNum = exec.PassCaseNum - 1
                exec.FailCaseNum = exec.FailCaseNum + 1
            }
        } else {
            if result == true {
                // update increase execution.passcounter and decrease failcounter
                exec.PassCaseNum = exec.PassCaseNum + 1
                exec.FailCaseNum = exec.FailCaseNum - 1
            } else {
                // same value. not updated
            }
        }
        rv.Status = result
        rv.Actual = actual
        rv.TestPlanID = exec.PlanID

        // update testcase result
        if err := c.Db.Save(&rv); err.Error != nil {
            log.Error("Update operation failed in TestExecs.UpdateResult")
            return RenderJSONWithStatus(w, Resp{Msg: "Update operation failed in TestExecs.UpdateResult"},
                http.StatusInternalServerError)
        }

        // update exec
        //db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
        if err := c.Db.Model(&exec).Updates(
            map[string]interface{}{
                "pass_case_num": exec.PassCaseNum,
                "fail_case_num": exec.FailCaseNum,
                "status":        exec.Status}); err.Error != nil {
            log.Error("Update operation failed in TestExecs.UpdateResult")
            return RenderJSONWithStatus(w, Resp{Msg: "Update operation failed in TestExecs.UpdateResult"},
                http.StatusInternalServerError)
        }
    }

    return RenderJSONWithStatus(w, Resp{Msg: "OK"}, http.StatusOK)
}

// ExecRun renders a test running page.
func ExecRun(c *interfacer.AppContext, w http.ResponseWriter, r *http.Request) error {

    vars := mux.Vars(r)
    id := vars["id"] // test execution id

    var testexec models.Execution
    var prj models.Project

    if err := c.Db.Where("name = ?", c.ProjectName).First(&prj); err.Error != nil {
        log.Error("TestExec", "type", "database", "msg ", err)
        return errors.HttpError{Status: http.StatusInternalServerError, Desc: "ParseForm failed"}
    }

    c.Db.Preload("Plan").Preload("TargetBuild").Where("id = ?", id).First(&testexec)

    arr := strings.Split(testexec.Plan.ExecuteCases, ",")

    // Question. Could the test execution have no testcase?
    var cases []models.TestCase
    c.Db.Where("id in (?)", arr).Find(&cases)

    var results []models.TestCaseResult
    c.Db.Order("test_case_id").Where("exec_id = ?", id).Find(&results)

    passCounter := 0
    failCounter := 0
    for _, k := range results {
        if k.Status == true {
            passCounter++
        } else {
            failCounter++
        }
    }

    items := map[string]interface{}{
        "TestExec":    testexec,
        "Cases":       cases,
        "Results":     results,
        "PassCounter": passCounter,
        "FailCounter": failCounter,
        "Active_idx":  5,
    }

    return Render2(c, w, items, "views/base.tmpl", "views/testexecs/exec_run.tmpl")
}

// ExecRemove is a POST handler and deletes test execution entity.
func ExecRemove(c *interfacer.AppContext, w http.ResponseWriter, r *http.Request) error {

    if err := r.ParseForm(); err != nil {
        log.Error("TestExec", "type", "http", "msg ", err)
        return errors.HttpError{Status: http.StatusInternalServerError, Desc: "ParseForm failed"}
    }

    id := r.FormValue("id")

    if err := c.Db.Where("id = ?", id).Delete(models.Execution{}); err.Error != nil {
        return RenderJSONWithStatus(w, Resp{Msg: "Problem while deleting execution"},
            http.StatusInternalServerError)
    }
    return RenderJSON(w, Resp{Msg: "ok"})
}

//ExecDeny makes the test execution denied
func ExecDeny(c *interfacer.AppContext, w http.ResponseWriter, r *http.Request) error {

    if err := r.ParseForm(); err != nil {
        log.Error("TestExec", "type", "http", "msg ", err)
        return errors.HttpError{Status: http.StatusInternalServerError, Desc: "ParseForm failed"}
    }

    id := r.FormValue("id")
    msg := r.FormValue("msg")

    var testexec models.Execution
    if err := c.Db.Where("id = ?", id).First(&testexec); err.Error != nil {
        return RenderJSONWithStatus(w, Resp{Msg: "Not found Test Execution"}, http.StatusInternalServerError)
    }

    testexec.Status = models.ExecStatusDeny
    testexec.Message = msg
    if err := c.Db.Save(testexec); err.Error != nil {
        return RenderJSONWithStatus(w, Resp{Msg: "Error while saving"}, http.StatusInternalServerError)
    }

    return RenderJSON(w, Resp{Msg: "ok"})
}