gotest.tools/gotestsum@v1.11.0/internal/aggregate/slowest.go (about) 1 package aggregate 2 3 import ( 4 "sort" 5 "time" 6 7 "gotest.tools/gotestsum/testjson" 8 ) 9 10 // Slowest returns a slice of all tests with an elapsed time greater than 11 // threshold. The slice is sorted by Elapsed time in descending order (slowest 12 // test first). 13 // 14 // If there are multiple runs of a TestCase, all of them will be represented 15 // by a single TestCase with the median elapsed time in the returned slice. 16 func Slowest(exec *testjson.Execution, threshold time.Duration, num int) []testjson.TestCase { 17 if threshold == 0 && num == 0 { 18 return nil 19 } 20 pkgs := exec.Packages() 21 tests := make([]testjson.TestCase, 0, len(pkgs)) 22 for _, pkg := range pkgs { 23 pkgTests := ByElapsed(exec.Package(pkg).TestCases(), median) 24 tests = append(tests, pkgTests...) 25 } 26 sort.Slice(tests, func(i, j int) bool { 27 return tests[i].Elapsed > tests[j].Elapsed 28 }) 29 if num >= len(tests) { 30 return tests 31 } 32 if num > 0 { 33 return tests[:num] 34 } 35 36 end := sort.Search(len(tests), func(i int) bool { 37 return tests[i].Elapsed < threshold 38 }) 39 return tests[:end] 40 } 41 42 // ByElapsed maps all test cases by name, and if there is more than one 43 // instance of a TestCase, uses fn to select the elapsed time for the group. 44 // 45 // All cases are assumed to be part of the same package. 46 func ByElapsed(cases []testjson.TestCase, fn func(times []time.Duration) time.Duration) []testjson.TestCase { 47 if len(cases) <= 1 { 48 return cases 49 } 50 pkg := cases[0].Package 51 // nolint: prealloc // size is not predictable 52 m := make(map[testjson.TestName][]time.Duration) 53 for _, tc := range cases { 54 m[tc.Test] = append(m[tc.Test], tc.Elapsed) 55 } 56 result := make([]testjson.TestCase, 0, len(m)) 57 for name, timing := range m { 58 result = append(result, testjson.TestCase{ 59 Package: pkg, 60 Test: name, 61 Elapsed: fn(timing), 62 }) 63 } 64 return result 65 } 66 67 func median(times []time.Duration) time.Duration { 68 switch len(times) { 69 case 0: 70 return 0 71 case 1: 72 return times[0] 73 } 74 sort.Slice(times, func(i, j int) bool { 75 return times[i] < times[j] 76 }) 77 return times[len(times)/2] 78 }