英文:
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".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论