Skip to content

Commit

Permalink
feat: don't create multiple snapshots when -test.count>1 (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
gkampitakis committed Jan 22, 2024
1 parent c904be0 commit a7f793e
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 32 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -16,7 +16,7 @@ format: ## Format code
golines . -w

test: ## Run tests
go test -race -count=1 -cover ./...
go test -race -count=10 -shuffle on -cover ./...

test-verbose: ## Run tests with verbose output
go test -race -count=1 -v -cover ./...
go test -race -count=10 -shuffle on -v -cover ./...
15 changes: 11 additions & 4 deletions snaps/clean.go
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"sync"
"testing"
Expand Down Expand Up @@ -82,12 +83,14 @@ func Clean(m *testing.M, opts ...CleanOpts) {
// This is just for making sure Clean is called from TestMain
_ = m
runOnly := flag.Lookup("test.run").Value.String()
count, _ := strconv.Atoi(flag.Lookup("test.count").Value.String())

obsoleteFiles, usedFiles := examineFiles(testsRegistry.values, runOnly, shouldClean && !isCI)
obsoleteFiles, usedFiles := examineFiles(testsRegistry.cleanup, runOnly, shouldClean && !isCI)
obsoleteTests, err := examineSnaps(
testsRegistry.values,
testsRegistry.cleanup,
usedFiles,
runOnly,
count,
shouldClean && !isCI,
opt.Sort && !isCI,
)
Expand Down Expand Up @@ -200,6 +203,7 @@ func examineSnaps(
registry map[string]map[string]int,
used []string,
runOnly string,
count int,
update,
sort bool,
) ([]string, error) {
Expand All @@ -216,7 +220,7 @@ func examineSnaps(

var hasDiffs bool

registeredTests := occurrences(registry[snapPath])
registeredTests := occurrences(registry[snapPath], count)
s := snapshotScanner(f)

for s.Scan() {
Expand Down Expand Up @@ -405,9 +409,12 @@ e.g
as it means there are 3 snapshots created inside TestAdd
*/
func occurrences(tests map[string]int) set {
func occurrences(tests map[string]int, count int) set {
result := make(set, len(tests))
for testID, counter := range tests {
// divide a test's counter by count (how many times the go test suite ran)
// this gives us how many snapshots were created in a single test run.
counter = counter / count
if counter > 1 {
for i := 1; i <= counter; i++ {
result[fmt.Sprintf("%s - %d", testID, i)] = struct{}{}
Expand Down
61 changes: 42 additions & 19 deletions snaps/clean_test.go
Expand Up @@ -151,7 +151,7 @@ func TestExamineSnaps(t *testing.T) {
filepath.FromSlash(dir2 + "/test2.snap"),
}

obsolete, err := examineSnaps(tests, used, "", shouldUpdate, sort)
obsolete, err := examineSnaps(tests, used, "", 1, shouldUpdate, sort)

test.Equal(t, []string{}, obsolete)
test.NoError(t, err)
Expand All @@ -172,7 +172,7 @@ func TestExamineSnaps(t *testing.T) {
// Removing the test entirely
delete(tests[used[1]], "TestDir2_2/TestSimple")

obsolete, err := examineSnaps(tests, used, "", shouldUpdate, sort)
obsolete, err := examineSnaps(tests, used, "", 1, shouldUpdate, sort)
content1 := test.GetFileContent(t, used[0])
content2 := test.GetFileContent(t, used[1])

Expand Down Expand Up @@ -200,7 +200,7 @@ func TestExamineSnaps(t *testing.T) {
delete(tests[used[0]], "TestDir1_3/TestSimple")
delete(tests[used[1]], "TestDir2_1/TestSimple")

obsolete, err := examineSnaps(tests, used, "", shouldUpdate, sort)
obsolete, err := examineSnaps(tests, used, "", 1, shouldUpdate, sort)
content1 := test.GetFileContent(t, used[0])
content2 := test.GetFileContent(t, used[1])

Expand Down Expand Up @@ -258,7 +258,7 @@ string hello world 2 2 1
filepath.FromSlash(dir2 + "/test2.snap"),
}

obsolete, err := examineSnaps(tests, used, "", shouldUpdate, sort)
obsolete, err := examineSnaps(tests, used, "", 1, shouldUpdate, sort)

test.NoError(t, err)
test.Equal(t, 0, len(obsolete))
Expand Down Expand Up @@ -290,7 +290,7 @@ string hello world 2 2 1
delete(tests[used[0]], "TestDir1_3/TestSimple")
delete(tests[used[1]], "TestDir2_1/TestSimple")

obsolete, err := examineSnaps(tests, used, "", shouldUpdate, sort)
obsolete, err := examineSnaps(tests, used, "", 1, shouldUpdate, sort)

test.NoError(t, err)
test.Equal(t, []string{
Expand All @@ -313,22 +313,45 @@ string hello world 2 2 1
}

func TestOccurrences(t *testing.T) {
tests := map[string]int{
"add": 3,
"subtract": 1,
"divide": 2,
}
t.Run("when count 1", func(t *testing.T) {
tests := map[string]int{
"add": 3,
"subtract": 1,
"divide": 2,
}

expected := set{
"add - 1": {},
"add - 2": {},
"add - 3": {},
"subtract - 1": {},
"divide - 1": {},
"divide - 2": {},
}
expected := set{
"add - 1": {},
"add - 2": {},
"add - 3": {},
"subtract - 1": {},
"divide - 1": {},
"divide - 2": {},
}

test.Equal(t, expected, occurrences(tests, 1))
})

test.Equal(t, expected, occurrences(tests))
t.Run("when count 3", func(t *testing.T) {
tests := map[string]int{
"add": 12,
"subtract": 3,
"divide": 9,
}

expected := set{
"add - 1": {},
"add - 2": {},
"add - 3": {},
"add - 4": {},
"subtract - 1": {},
"divide - 1": {},
"divide - 2": {},
"divide - 3": {},
}

test.Equal(t, expected, occurrences(tests, 3))
})
}

func TestSummary(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions snaps/matchJSON.go
Expand Up @@ -65,6 +65,9 @@ func matchJSON(c *config, t testingT, input any, matchers ...match.JSONMatcher)

snapPath, snapPathRel := snapshotPath(c)
testID := testsRegistry.getTestID(snapPath, t.Name())
t.Cleanup(func() {
testsRegistry.reset(snapPath, t.Name())
})

j, err := validateJSON(input)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions snaps/matchJSON_test.go
Expand Up @@ -59,6 +59,9 @@ func TestMatchJSON(t *testing.T) {
test.Equal(t, 2, line)
test.Equal(t, expected, snap)
test.Equal(t, 1, testEvents.items[added])
// clean up function called
test.Equal(t, 0, testsRegistry.running[snapPath]["mock-name"])
test.Equal(t, 1, testsRegistry.cleanup[snapPath]["mock-name"])
})
}
})
Expand Down
4 changes: 4 additions & 0 deletions snaps/matchSnapshot.go
Expand Up @@ -56,6 +56,10 @@ func matchSnapshot(c *config, t testingT, values ...any) {

snapPath, snapPathRel := snapshotPath(c)
testID := testsRegistry.getTestID(snapPath, t.Name())
t.Cleanup(func() {
testsRegistry.reset(snapPath, t.Name())
})

snapshot := takeSnapshot(values)
prevSnapshot, line, err := getPrevSnapshot(testID, snapPath)
if errors.Is(err, errSnapNotFound) {
Expand Down
3 changes: 3 additions & 0 deletions snaps/matchSnapshot_test.go
Expand Up @@ -73,6 +73,9 @@ func TestMatchSnapshot(t *testing.T) {
test.GetFileContent(t, snapPath),
)
test.Equal(t, 1, testEvents.items[added])
// clean up function called
test.Equal(t, 0, testsRegistry.running[snapPath]["mock-name"])
test.Equal(t, 1, testsRegistry.cleanup[snapPath]["mock-name"])
})

t.Run("if it's running on ci should skip", func(t *testing.T) {
Expand Down
25 changes: 18 additions & 7 deletions snaps/snapshot.go
Expand Up @@ -86,7 +86,8 @@ This also helps with keeping track with obsolete snaps
map[snap path]: map[testname]: <number of snapshots>
*/
type syncRegistry struct {
values map[string]map[string]int
running map[string]map[string]int
cleanup map[string]map[string]int
sync.Mutex
}

Expand All @@ -95,21 +96,31 @@ type syncRegistry struct {
func (s *syncRegistry) getTestID(snapPath, testName string) string {
s.Lock()

if _, exists := s.values[snapPath]; !exists {
s.values[snapPath] = make(map[string]int)
if _, exists := s.running[snapPath]; !exists {
s.running[snapPath] = make(map[string]int)
s.cleanup[snapPath] = make(map[string]int)
}

s.values[snapPath][testName]++
c := s.values[snapPath][testName]
s.running[snapPath][testName]++
s.cleanup[snapPath][testName]++
c := s.running[snapPath][testName]
s.Unlock()

return fmt.Sprintf("[%s - %d]", testName, c)
}

// reset sets only the number of running registry for the given test to 0.
func (s *syncRegistry) reset(snapPath, testName string) {
s.Lock()
s.running[snapPath][testName] = 0
s.Unlock()
}

func newRegistry() *syncRegistry {
return &syncRegistry{
values: make(map[string]map[string]int),
Mutex: sync.Mutex{},
running: make(map[string]map[string]int),
cleanup: make(map[string]map[string]int),
Mutex: sync.Mutex{},
}
}

Expand Down
24 changes: 24 additions & 0 deletions snaps/snapshot_test.go
Expand Up @@ -26,6 +26,30 @@ func TestSyncRegistry(t *testing.T) {

test.Equal(t, "[test - 6]", registry.getTestID("/file", "test"))
test.Equal(t, "[test-v2 - 1]", registry.getTestID("/file", "test-v2"))
test.Equal(t, registry.cleanup, registry.running)
})

t.Run("should reset running registry", func(t *testing.T) {
wg := sync.WaitGroup{}
registry := newRegistry()

for i := 0; i < 100; i++ {
wg.Add(1)

go func() {
registry.getTestID("/file", "test")
wg.Done()
}()
}

wg.Wait()

registry.reset("/file", "test")

// running registry start from 0 again
test.Equal(t, "[test - 1]", registry.getTestID("/file", "test"))
// cleanup registry still has 101
test.Equal(t, 101, registry.cleanup["/file"]["test"])
})
}

Expand Down

0 comments on commit a7f793e

Please sign in to comment.