Skip to content

Commit

Permalink
add random.Random.Repeat helper to make random sampling easier in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
adamluzsi committed Jan 24, 2023
1 parent 092cc17 commit e5d64ae
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 8 deletions.
6 changes: 6 additions & 0 deletions random/Random.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,9 @@ func (r *Random) Email() string {
r.SliceElement(fixtureStrings.emailDomains).(string),
)
}

func (r *Random) Repeat(min, max int, do func()) {
for i, n := 0, r.IntB(min, max); i < n; i++ {
do()
}
}
52 changes: 44 additions & 8 deletions random/Random_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package random_test

import (
"fmt"
"github.com/adamluzsi/testcase/let"
"math/rand"
"regexp"
"strings"
Expand Down Expand Up @@ -54,6 +55,8 @@ func TestRandom(t *testing.T) {
}

func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {
const SamplingNumber = 1024

s.Describe(`Int`, func(s *testcase.Spec) {
var subject = func(t *testcase.T) int {
return rnd.Get(t).Int()
Expand Down Expand Up @@ -128,7 +131,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {
s.Test(`E2E`, func(t *testcase.T) {
pool := []int{1, 2, 3, 4, 5}
resSet := make(map[int]struct{})
for i := 0; i < 1024; i++ {
for i := 0; i < SamplingNumber; i++ {
res := rnd.Get(t).SliceElement(pool).(int)
resSet[res] = struct{}{}
t.Must.Contain(pool, res)
Expand Down Expand Up @@ -175,7 +178,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {

s.Then(`it return with random bool on each calls`, func(t *testcase.T) {
var bools = map[bool]struct{}{}
for i := 0; i <= 1024; i++ {
for i := 0; i <= SamplingNumber; i++ {
bools[subject(t)] = struct{}{}
}
t.Must.Equal(2, len(bools))
Expand All @@ -189,7 +192,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {

s.Then(`it create error with different content`, func(t *testcase.T) {
var lengths = make(map[string]struct{})
for i := 0; i < 1024; i++ {
for i := 0; i < SamplingNumber; i++ {
err := act(t)
t.Must.Error(err)
lengths[err.Error()] = struct{}{}
Expand All @@ -211,7 +214,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {

s.Then(`it create strings with different lengths`, func(t *testcase.T) {
var lengths = make(map[int]struct{})
for i := 0; i < 1024; i++ {
for i := 0; i < SamplingNumber; i++ {
lengths[len(subject(t))] = struct{}{}
}
t.Must.True(1 < len(lengths))
Expand Down Expand Up @@ -397,7 +400,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {
})

s.Then("calling it bulk yields relatively random UUIDs", func(t *testcase.T) {
sampling := t.Random.IntB(512, 1024)
sampling := t.Random.IntB(512, SamplingNumber)
t.Eventually(func(it assert.It) {
results := make(map[string]struct{})
for i := 0; i < sampling; i++ {
Expand Down Expand Up @@ -448,7 +451,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {
s.Then("it never returns a female name", func(t *testcase.T) {
name := rnd.Get(t).Name().First(sextype.Female)
t.Must.AnyOf(func(a *assert.AnyOf) {
for i := 0; i < 1024; i++ {
for i := 0; i < SamplingNumber; i++ {
a.Test(func(it assert.It) {
it.Must.NotEqual(name, act(t))
})
Expand All @@ -471,7 +474,7 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {
s.Then("it never returns a male name", func(t *testcase.T) {
name := rnd.Get(t).Name().First(sextype.Male)
t.Must.AnyOf(func(a *assert.AnyOf) {
for i := 0; i < 1024; i++ {
for i := 0; i < SamplingNumber; i++ {
a.Test(func(it assert.It) {
it.Must.NotEqual(name, act(t))
})
Expand Down Expand Up @@ -526,14 +529,47 @@ func SpecRandomMethods(s *testcase.Spec, rnd testcase.Var[*random.Random]) {
t.Must.NotEmpty(act(t))
})

s.Then("it returns a valid common last name", func(t *testcase.T) {
s.Then("it returns a valid common email domain", func(t *testcase.T) {
const exampleDomainSuffix = "@gmail.com"

t.Eventually(func(it assert.It) {
it.Must.True(strings.HasSuffix(act(t), exampleDomainSuffix))
})
})
})

s.Describe(".Repeat", func(s *testcase.Spec) {
var (
min = let.IntB(s, 5, 7)
max = let.IntB(s, 12, 42)

times = testcase.LetValue(s, 0)
blk = testcase.Let(s, func(t *testcase.T) func() {
return func() { times.Set(t, times.Get(t)+1) }
})
)
act := func(t *testcase.T) {
rnd.Get(t).Repeat(min.Get(t), max.Get(t), blk.Get(t))
}

s.Then("the number of callback execution will be between the min and the max", func(t *testcase.T) {
act(t)
t.Must.True(min.Get(t) <= times.Get(t))
t.Must.True(times.Get(t) <= max.Get(t))
})

s.Then("the number of callback execution will be a random number", func(t *testcase.T) {
runCounts := make(map[int]struct{})

for i := 0; i < SamplingNumber; i++ {
times.Set(t, 0)
act(t)
runCounts[times.Get(t)] = struct{}{}
}

t.Must.True(1 < len(runCounts))
})
})
}

func SpecStringNWithCharset(s *testcase.Spec, rnd testcase.Var[*random.Random], act func(t *testcase.T, rnd *random.Random, length int, charset string) string) {
Expand Down
8 changes: 8 additions & 0 deletions random/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,11 @@ func ExampleMakeMap() {

pp.PP(random.MakeMap[string, int](rnd, 3)) // map[string]int slice with 3 key-value pairs
}

func ExampleRandom_Repeat() {
rnd := random.New(random.CryptoSeed{})

rnd.Repeat(1, 3, func() {
// will be called repeatedly between 1 and 3 times.
})
}

0 comments on commit e5d64ae

Please sign in to comment.