英文:
Test Golang Goroutine
问题
我一直在搜索,但到目前为止,只找到了由Ariejan de Vroom在这里写的类似文章。
我想知道是否可以将goroutine引入单元测试中,以便可以精确地计算并发的goroutine数量,并告诉我它们是否以我所述的数量正确地生成了goroutine。
我有以下示例代码:
import (
"testing"
"github.com/stretchr/testify/assert"
)
func createList(job int, done chan bool) {
time.Sleep(500)
// do something
time.Sleep(500)
done <- true
return
}
func TestNewList(t *testing.T) {
list := NewList()
if assert.NotNil(t, list) {
const numGoRoutines = 16
jobs := make(chan int, numGoRoutines)
done := make(chan bool, 1)
for j := 1; j <= numGoRoutines; j++ {
jobs <- j
go createList(j, done)
fmt.Println("sent job", j)
}
close(jobs)
fmt.Println("sent all jobs")
<-done
}
}
英文:
I've been searching around, but so far only gone similar article written here by Ariejan de Vroom.
I would like to know if I can bring goroutine into unit testing such that it can precisely count the concurrent # of goroutines is running and can tell me if they are correctly spawned goroutine in the number I have stated.
I have the following code for example..
import (
"testing"
"github.com/stretchr/testify/assert"
)
func createList(job int, done chan bool) {
time.Sleep(500)
// do something
time.Sleep(500)
done <- true
return
}
func TestNewList(t *testing.T) {
list := NewList()
if assert.NotNil(t, list) {
const numGoRoutines = 16
jobs := make(chan int, numGoRoutines)
done := make(chan bool, 1)
for j := 1; j <= numGoRoutines; j++ {
jobs <- j
go createList(j, done)
fmt.Println("sent job", j)
}
close(jobs)
fmt.Println("sent all jobs")
<-done
}
答案1
得分: 1
根据我的理解,你希望限制同时运行的例程数量,并验证其是否正常工作。我建议编写一个函数,该函数将接受一个例程作为参数,并使用模拟例程对其进行测试。
以下是一个示例,spawn
函数会同时运行 fn
例程 count
次,但最多同时运行 limit
个例程。我将其包装在主函数中以在 playground 中运行,但你可以在测试方法中使用相同的方法。
package main
import (
"fmt"
"sync"
"time"
)
func spawn(fn func(), count int, limit int) {
limiter := make(chan bool, limit)
spawned := func() {
defer func() { <-limiter }()
fn()
}
for i := 0; i < count; i++ {
limiter <- true
go spawned()
}
}
func main() {
count := 10
limit := 3
var wg sync.WaitGroup
wg.Add(count)
concurrentCount := 0
failed := false
var mock = func() {
defer func() {
wg.Done()
concurrentCount--
}()
concurrentCount++
if concurrentCount > limit {
failed = true // test could be failed here without waiting all routines finish
}
time.Sleep(100)
}
spawn(mock, count, limit)
wg.Wait()
if failed {
fmt.Println("Test failed")
} else {
fmt.Println("Test passed")
}
}
英文:
As I understood you are willing to limit the number of routines running simultaneously and verify whether it works properly. I would suggest to write a function which will take a routine as and argument and use mock routine to test it.<br/>
In the following example spawn
function runs fn
routines count
times but no more than limit
routines concurrently. I wrapped it into main function to run it at playground but you can use the same approach for your test method.
package main
import (
"fmt"
"sync"
"time"
)
func spawn(fn func(), count int, limit int) {
limiter := make(chan bool, limit)
spawned := func() {
defer func() { <-limiter }()
fn()
}
for i := 0; i < count; i++ {
limiter <- true
go spawned()
}
}
func main() {
count := 10
limit := 3
var wg sync.WaitGroup
wg.Add(count)
concurrentCount := 0
failed := false
var mock = func() {
defer func() {
wg.Done()
concurrentCount--
}()
concurrentCount++
if concurrentCount > limit {
failed = true // test could be failed here without waiting all routines finish
}
time.Sleep(100)
}
spawn(mock, count, limit)
wg.Wait()
if failed {
fmt.Println("Test failed")
} else {
fmt.Println("Test passed")
}
}
答案2
得分: 0
一种可能的方法是使用runtime.Stack()
或分析runtime.debug.PrintStack()
的输出,以查看给定时间的所有goroutine。
这些选项在“https://stackoverflow.com/q/19094099/6309”中有详细说明。
英文:
One possible approch would be to use runtime.Stack()
or analyze the output of runtime.debug.PrintStack()
in order to see all goroutines at a given time.
Those options are detailed in "https://stackoverflow.com/q/19094099/6309".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论