在 golang 中测试函数

标签 testing go

所以我决定在 golang 中为我的函数编写测试。该函数本身如下所示:

func Insert(slice []int, element int, index int) []int {
    n := len(slice)
    slice = slice[:(n + 1)]
    for i := index; i < n; i++ {
        slice[i+1] = slice[i]
    }
    slice[index] = element
    return slice
} 

因此它需要一个 slice ,将其长度扩展 1 并在给定索引处插入一个元素。现在,在调用它之前,我必须做两件事:

size := somevalue
array := make([]int, size, size+1)

然后是f.e array = Insert(array, 1, len(array)/2 。现在我写了insert_test.go :

package sdizo

import "testing"

func benchmarkInsert(size int, b *testing.B) {  
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
        array := make([]int, size, size+1)
        array = Insert(array, 1, len(array)/2)
    }
}
func BenchmarkInsert10k(b *testing.B) { benchmarkInsert(10000, b) }
func BenchmarkInsert20k(b *testing.B) { benchmarkInsert(20000, b) }
func BenchmarkInsert30k(b *testing.B) { benchmarkInsert(30000, b) }
func BenchmarkInsert40k(b *testing.B) { benchmarkInsert(40000, b) }
func BenchmarkInsert50k(b *testing.B) { benchmarkInsert(50000, b) }

问题是,测试循环中有 2 个操作。我无法移动 make()在循环上方,因为每次尝试向其中插入内容时都必须创建一个新数组(不想弄乱容量)。它有效,它给了我输出,但我很好奇这是否 make()不会扰乱时间测量,我想问你是否可以以某种方式仅测量 Insert() 的时间

P.S 有没有一种方便的方法将基准测试的结果写入文件?

最佳答案

例如(从 Go 1.7 开始),使用您的 Insert 算法,

package sdizo

import (
    "strconv"
    "testing"
)

func Insert(slice []int, element int, index int) []int {
    n := len(slice)
    slice = slice[:(n + 1)]
    for i := index; i < n; i++ {
        slice[i+1] = slice[i]
    }
    slice[index] = element
    return slice
}

func BenchmarkInsert(b *testing.B) {
    for size := 10000; size <= 50000; size += 10000 {

        b.Run(strconv.Itoa(size/1000)+"k",

            func(b *testing.B) {
                a := make([]int, size, size+1)
                b.ReportAllocs()
                b.ResetTimer()
                for i := 0; i < b.N; i++ {
                    a = a[:size]
                    a = Insert(a, 1, len(a)/2)
                }
                b.StopTimer()
            },
        )
    }
}

输出:

$ go test -bench=.
goos: linux
goarch: amd64
pkg: sdizo
BenchmarkInsert/10k-4         50000      32502 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/20k-4         20000      64364 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/30k-4         20000      97310 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/40k-4         10000     129196 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/50k-4         10000     161427 ns/op       0 B/op      0 allocs/op
PASS
ok      so/sdizo    9.778s
$ 

现在我们可以对您的Insert 算法进行基准测试,我们可以利用这些知识来改进算法。例如,

package sdizo

import (
    "strconv"
    "testing"
)

func Insert(slice []int, element int, index int) []int {
    slice = slice[:len(slice)+1]
    copy(slice[index+1:], slice[index:])
    slice[index] = element
    return slice
}

func BenchmarkInsert(b *testing.B) {
    for size := 10000; size <= 50000; size += 10000 {

        b.Run(strconv.Itoa(size/1000)+"k",

            func(b *testing.B) {
                a := make([]int, size, size+1)
                b.ReportAllocs()
                b.ResetTimer()
                for i := 0; i < b.N; i++ {
                    a = a[:size]
                    a = Insert(a, 1, len(a)/2)
                }
                b.StopTimer()
            },
        )
    }
}

输出:

$ go test -bench=.
goos: linux
goarch: amd64
pkg: sdizo
BenchmarkInsert/10k-4        200000       7664 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/20k-4        100000      15208 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/30k-4        100000      22959 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/40k-4         50000      35181 ns/op       0 B/op      0 allocs/op
BenchmarkInsert/50k-4         50000      39658 ns/op       0 B/op      0 allocs/op
PASS
ok      so/sdizo    10.331s
$

关于在 golang 中测试函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43023702/

相关文章:

go - 在go中按域查找IP地址

ruby-on-rails - Rails.env 在测试中返回 'development' 导致设计真实性 token 破坏测试?

java - 如何测试命令行界面 (CLI)?

android - 如何通过appium执行模拟器命令

ruby-on-rails - 测试中没有路由错误在开发中工作

go - 运行时没有任何反应 go get github.com/astaxie/beego

go - 如何使用 channel 收集各种goroutine的响应

java - 测试包含日期字段的对象

Gorm 按关联计数排序

postgresql - 维护同一行的并发更新的完整性