github.com/mailgun/holster/v4@v4.20.0/functional/functional.go (about) 1 /* 2 Copyright 2022 Mailgun Technologies Inc 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // `go test`-like functional testing framework. 18 // Can be used with Testify require/assert/mock. 19 package functional 20 21 import ( 22 "context" 23 "time" 24 ) 25 26 // Run a test. Test named after function name. 27 func Run(ctx context.Context, fn TestFunc, opts ...FunctionalOption) bool { 28 name := funcName(fn) 29 t := newT(name, opts...) 30 t.invoke(ctx, fn) 31 return t.result.Pass 32 } 33 34 // Run a test with user-provided name. 35 func RunWithName(ctx context.Context, name string, fn TestFunc, opts ...FunctionalOption) bool { 36 t := newT(name, opts...) 37 t.invoke(ctx, fn) 38 return t.result.Pass 39 } 40 41 // Run a suite of tests as a unit. 42 // Generates summary when finished. 43 func RunSuite(ctx context.Context, suiteName string, tests []TestFunc, opts ...FunctionalOption) bool { 44 result := map[bool]int{true: 0, false: 0} 45 numTests := len(tests) 46 t := newT(suiteName, opts...) 47 suiteStartTime := time.Now() 48 49 t.invoke(ctx, func(t *T) { 50 for _, test := range tests { 51 testName := funcName(test) 52 pass := t.Run(testName, test) 53 result[pass]++ 54 } 55 56 suiteEndTime := time.Now() 57 pass := result[false] == 0 58 passPct := float64(result[true]) / float64(numTests) * 100 59 t.Log() 60 t.Log("Suite test result summary:") 61 t.Logf(" pass: %d (%0.1f%%)", result[true], passPct) 62 t.Logf(" fail: %d", result[false]) 63 t.Logf(" elapsed: %s", suiteEndTime.Sub(suiteStartTime)) 64 65 if !pass { 66 t.FailNow() 67 } 68 }) 69 70 return t.result.Pass 71 } 72 73 // Run a benchmark test. Test named after function name. 74 func RunBenchmarkTimes(ctx context.Context, fn BenchmarkFunc, times int, opts ...FunctionalOption) TestResult { 75 name := funcName(fn) 76 b := newB(name, times, opts...) 77 b.invoke(ctx, fn) 78 return b.result 79 } 80 81 // Run a benchmark test with user-provided name. 82 func RunBenchmarkTimesWithName(ctx context.Context, name string, fn BenchmarkFunc, times int, opts ...FunctionalOption) TestResult { 83 b := newB(name, times, opts...) 84 b.invoke(ctx, fn) 85 return b.result 86 } 87 88 // Run a suite of benchmark tests as a unit. 89 // Run each benchmark n times. 90 // Generates summary when finished. 91 func RunBenchmarkSuiteTimes(ctx context.Context, suiteName string, times int, tests []BenchmarkFunc, opts ...FunctionalOption) bool { 92 result := map[bool]int{true: 0, false: 0} 93 numTests := len(tests) 94 b := newB(suiteName, 1, opts...) 95 suiteStartTime := time.Now() 96 97 b.invoke(ctx, func(b *B) { 98 for _, test := range tests { 99 testName := funcName(test) 100 b.N = times 101 bret := b.Run(testName, test) 102 result[bret.Pass]++ 103 } 104 105 suiteEndTime := time.Now() 106 pass := result[false] == 0 107 passPct := float64(result[true]) / float64(numTests) * 100 108 b.Log() 109 b.Log("Suite benchmark test result summary:") 110 b.Logf(" pass: %d (%0.1f%%)", result[true], passPct) 111 b.Logf(" fail: %d", result[false]) 112 b.Logf(" elapsed: %s", suiteEndTime.Sub(suiteStartTime)) 113 114 if !pass { 115 b.FailNow() 116 } 117 }) 118 119 return b.result.Pass 120 }