登录golang测试好吗?或者是没有登录测试的做法?

时间:2018-03-14 08:15:14

标签: testing go integration-testing

登录golang测试是否可以?或者是没有登录测试的做法?

我的测试目前看起来像这样。我不确定我是否做得对,需要建议在golang进行测试的最佳实践。这是一个集成测试btw。

日志问题主要在初始化步骤TestMain,其中输入是* testing.M,没有日志功能。

var testDB *DB

func clearTable(name string) {
        var err error
        _, err = testDB.Exec(fmt.Sprintf("DELETE FROM %s", name))
        if err != nil {
                log.Fatalf("[FATA] Failed to clear a table in database. name=%q err=%q", name, err)
        }
        _, err = testDB.Exec(fmt.Sprintf("ALTER SEQUENCE %s_id_seq RESTART WITH 1", name))
        if err != nil {
                log.Fatalf("[FATA] Failed to reset ID sequence of a table in database. name=%q err=%q", name, err)
        }
}

func TestMain(m *testing.M) {
        var err error
        testDB, err = NewDB(fmt.Sprintf("dbname=%s sslmode=disable", testDBName))
        if err != nil {
                log.Fatalf("[FATA] Failed to initialize test database. dbName=%q err=%q", testDBName, err)
        }
        defer testDB.Close()
        code := m.Run()
        clearTable("worker")
        os.Exit(code)
}

func TestCreateWorker(t *testing.T) {
        clearTable("worker")

        createdWorkers := make(map[int]*Worker, 10)
        for i := 0; i < 10; i++ {
                username := strings.Join([]string{"worker", strconv.Itoa(i)}, "")
                email := strings.Join([]string{username, "@gmail.com"}, "")
                passwordHash := strings.Join([]string{username, "PasswordHash"}, "")
                worker := Worker {
                        Username: username, 
                        Email: email,
                        PasswordHash: passwordHash,
                }
                err := testDB.CreateWorker(&worker)
                if err != nil {
                        t.Errorf("[ERRO] Failed to create a new worker in database. username=%q email=%q passwordHash=%q err=%q", username, email, passwordHash, err)
                }
                createdWorkers[i+1] = &worker
        }

        rows, err := testDB.Query("SELECT * FROM worker")
        if err != nil {
                t.Errorf("[ERRO] Failed to get all workers from database. err=%q", err)
        }
        defer rows.Close()
        for rows.Next() {
                returnedWorker := new(Worker)
                err := rows.Scan(&returnedWorker.ID, &returnedWorker.Username, &returnedWorker.Email, &returnedWorker.PasswordHash, &returnedWorker.CreatedAt)
                if err != nil {
                        t.Errorf("[ERRO] Failed to scan returned row into worker struct. err=%q", err)
                }
                createdWorker := createdWorkers[returnedWorker.ID]
                if !reflect.DeepEqual(&createdWorker, &returnedWorker) {
                        t.Errorf("[ERRO] Worker created in database and worker returned from database are different. createdWorker=%v returnedWorker=%v", createdWorker, returnedWorker)
                }
        }
}

任何好的Golang github仓库能做好记录来学习吗?

1 个答案:

答案 0 :(得分:2)

登录测试完全没问题;这就是为什么* testing.T有Log和Logf方法的原因。

您应该将测试结构传递给辅助函数并让测试失败,而不是调用log.Fatalf:

func clearTable(t *testing.T, name string) {
    t.Helper() // optional; identifies our caller as the culprit if test fails

    _, err := testDB.Exec(fmt.Sprintf("DELETE FROM %s", name))
    if err != nil {
            t.Fatalf("[FATA] Failed to clear a table in database. name=%q err=%q", name, err)
    }
    _, err = testDB.Exec(fmt.Sprintf("ALTER SEQUENCE %s_id_seq RESTART WITH 1", name))
    if err != nil {
            t.Fatalf("[FATA] Failed to reset ID sequence of a table in database. name=%q err=%q", name, err)
    }
}

正如您在评论中已经提到的,这不适用于TestMain函数。

您应该避免定义TestMain,这很少是必要的。相反,在每个测试中调用setup和teardown函数。这使得测试自成一体,并且更容易理解正在发生的事情。

func TestCreateWorker(t *testing.T) {
    clearTable(t, "worker")
    defer clearTable(t, "worker")

    // test follows
}

除此之外:想想你是否想在每次测试后调用clearTable都很长。第一次调用是多余的,会破坏测试失败的所有证据,并使调试更加困难。

如果你想保持你的TestMain,定义一个不依赖于测试的不同辅助函数.T。