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
}
create channels of the appropriate type for my function under test. pass those channels into o. sum() and run the function on a separate go routine. create a loop that will send data to the values channel.
Golang provides goroutines to support concurrency in Go. A goroutine is a function that executes simultaneously with other goroutines in a program and are lightweight threads managed by Go. A goroutine takes about 2kB of stack space to initialize.
The 'go test' command may run tests for different packages in parallel as well, according to the setting of the -p flag (see 'go help build').
The WaitGroup type of sync package, is used to wait for the program to finish all goroutines launched from the main function. It uses a counter that specifies the number of goroutines, and Wait blocks the execution of the program until the WaitGroup counter is zero.
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.
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")
}
}
Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With