Golang - 測試用例示例代碼


目錄結構

在這裏插入圖片描述


代碼示例

split.go

package split

import "strings"

// 定義一個切割字符串的包

// Split 按照 sep 分割 s, a:b:c --> a b c
func Split(s, sep string) []string {
	// 得到字符串中分隔符的數量
	sepNum := strings.Count(s, sep)
	// 按照分隔符數量申請內存
	r := make([]string, 0, sepNum+1)

	index := strings.Index(s, sep)
	for index >= 0 {
		r = append(r, s[:index])
		s = s[index+len(sep):]
		index = strings.Index(s, sep)
	}

	r = append(r, s)
	return r
}


split_test.go

package split

import (
	"fmt"
	"os"
	"reflect"
	"testing"
)

// 子測試集
func TestNormalSplit(t *testing.T) {
	get := Split("a:b:c", ":")
	want := []string{"a", "b", "c"}

	if ok := reflect.DeepEqual(get, want); !ok {
		t.Fatalf("期望結果: %v, 實際結果: %v\n", want, get)
	}
}

func TestMultiSplit(t *testing.T) {
	// 這裏是 setup 和 teardown 的使用實例
	f := setupT(t)
	defer f(t)

	get := Split("a::b::c", "::")
	want := []string{"a", "b", "c"}

	if ok := reflect.DeepEqual(get, want); !ok {
		t.Fatalf("期望結果: %v, 實際結果: %v\n", want, get)
	} else {
		t.Log("pass test...")
	}
}

func TestNumSplit(t *testing.T) {
	get := Split("1231", "1")
	want := []string{"", "23", ""}

	if ok := reflect.DeepEqual(get, want); !ok {
		t.Fatalf("期望結果: %v, 實際結果: %v\n", want, get)
	}
}

// 子測試組
func TestSplitGroup(t *testing.T) {

	// 存放測試的結構體
	type test struct {
		str  string
		sep  string
		want []string
	}

	// 將測試用例都實例化到 map 中
	items := map[string]test{
		"normal": test{
			str:  "a:b:c",
			sep:  ":",
			want: []string{"a", "b", "c"},
		},
		"multi": test{
			str:  "a::b::c",
			sep:  "::",
			want: []string{"a", "b", "c"},
		},
		"num": test{
			str:  "1231",
			sep:  "1",
			want: []string{"", "23", ""},
		},
	}

	for k, i := range items {
		t.Run(k, func(t *testing.T) {
			get := Split(i.str, i.sep)
			if ok := reflect.DeepEqual(i.want, get); !ok {
				t.Fatalf("測試關鍵字: %v, 期望結果: %v, 實際結果: %v\n", k, i.want, get)
			}
		})
	}
}

// 性能測試 - 基礎版
func BenchmarkSplit(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Split("a:b:c", ":")
	}
}

// 性能測試 - 併發版
func BenchmarkParallelSplit(b *testing.B) {
	// 設置 cpu 數量
	// b.SetParallelism(1)

	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			Split("1231", "1")
		}
	})
}

// 在全局加前後操作
func TestMain(m *testing.M) {
	fmt.Println("start test...")
	r := m.Run()
	fmt.Println("end test...")
	os.Exit(r)
}

// 給單一測試用例加前後操作, 如果是性能測試, t 改 b 即可
func setupT(t *testing.T) func(t *testing.T) {
	t.Log("start test...")      // 測試前執行
	return func(t *testing.T) { // 返回函數名, 使用時 defer 調用
		t.Log("end test...")
	}
}


fib.go

package fib

// Fib 計算斐波那契數列
func Fib(n int) int {
	if n < 2 {
		return n
	}

	return Fib(n-1) + Fib(n-2)
}


fib_test.go

package fib

import "testing"

// 性能測試 - 性能對比, 根據數據量不同進行分析
func benchmarkFib(b *testing.B, n int) {
	// 清除耗時
	// b.ResetTimer()

	for i := 0; i < b.N; i++ {
		Fib(n)
	}
}

func BenchmarkFib2(b *testing.B) {
	benchmarkFib(b, 2)
}

func BenchmarkFib10(b *testing.B) {
	benchmarkFib(b, 10)
}

func BenchmarkFib20(b *testing.B) {
	benchmarkFib(b, 20)
}


運行結果

split code

xxx@xxx split % go test -v
testMain start test...
=== RUN   TestNormalSplit
--- PASS: TestNormalSplit (0.00s)
=== RUN   TestMultiSplit
--- PASS: TestMultiSplit (0.00s)
    split_test.go:111: setupT start test...
    split_test.go:30: pass test...
    split_test.go:113: setupT end test...
=== RUN   TestNumSplit
--- PASS: TestNumSplit (0.00s)
=== RUN   TestSplitGroup
=== RUN   TestSplitGroup/normal
=== RUN   TestSplitGroup/multi
=== RUN   TestSplitGroup/num
--- PASS: TestSplitGroup (0.00s)
    --- PASS: TestSplitGroup/normal (0.00s)
    --- PASS: TestSplitGroup/multi (0.00s)
    --- PASS: TestSplitGroup/num (0.00s)
PASS
testMain end test...
ok      xxx/split   0.013s


fib code

xxx@xxx Fib % go test -bench=. -v
goos: darwin
goarch: amd64
pkg: code.oldboy.com/Fib
BenchmarkFib2-4         100000000               10.9 ns/op
BenchmarkFib10-4         2000000               695 ns/op
BenchmarkFib20-4           20000             90912 ns/op
PASS
ok      xxx/Fib     5.728s

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章