1 package gmeasure_test
2
3 import (
4 "math"
5 "strings"
6 "time"
7
8 . "github.com/onsi/ginkgo/v2"
9 . "github.com/onsi/gomega"
10 "github.com/onsi/gomega/gmeasure"
11 )
12
13 var _ = Describe("Measurement", func() {
14 var e *gmeasure.Experiment
15 var measurement gmeasure.Measurement
16
17 BeforeEach(func() {
18 e = gmeasure.NewExperiment("Test Experiment")
19 })
20
21 Describe("Note Measurement", func() {
22 BeforeEach(func() {
23 e.RecordNote("I'm a red note", gmeasure.Style("{{red}}"))
24 measurement = e.Measurements[0]
25 })
26
27 Describe("Generating Stats", func() {
28 It("returns an empty stats", func() {
29 Ω(measurement.Stats()).Should(BeZero())
30 })
31 })
32
33 Describe("Emitting an unstyled report", func() {
34 It("does not include styling", func() {
35 Ω(measurement.String()).Should(Equal("Test Experiment - Note\nI'm a red note\n"))
36 })
37 })
38
39 Describe("Emitting a styled report", func() {
40 It("does include styling", func() {
41 Ω(measurement.ColorableString()).Should(Equal("{{red}}Test Experiment - Note\nI'm a red note\n{{/}}"))
42 })
43 })
44 })
45
46 Describe("Value Measurement", func() {
47 var min, median, mean, stdDev, max float64
48 BeforeEach(func() {
49 e.RecordValue("flange widths", 7.128, gmeasure.Annotation("A"), gmeasure.Precision(2), gmeasure.Units("inches"), gmeasure.Style("{{blue}}"))
50 e.RecordValue("flange widths", 3.141, gmeasure.Annotation("B"))
51 e.RecordValue("flange widths", 9.28223, gmeasure.Annotation("C"))
52 e.RecordValue("flange widths", 14.249, gmeasure.Annotation("D"))
53 e.RecordValue("flange widths", 8.975, gmeasure.Annotation("E"))
54 measurement = e.Measurements[0]
55 min = 3.141
56 max = 14.249
57 median = 8.975
58 mean = (7.128 + 3.141 + 9.28223 + 14.249 + 8.975) / 5.0
59 stdDev = (7.128-mean)*(7.128-mean) + (3.141-mean)*(3.141-mean) + (9.28223-mean)*(9.28223-mean) + (14.249-mean)*(14.249-mean) + (8.975-mean)*(8.975-mean)
60 stdDev = math.Sqrt(stdDev / 5.0)
61 })
62
63 Describe("Generating Stats", func() {
64 It("generates a correctly configured Stats with correct values", func() {
65 stats := measurement.Stats()
66 Ω(stats.ExperimentName).Should(Equal("Test Experiment"))
67 Ω(stats.MeasurementName).Should(Equal("flange widths"))
68 Ω(stats.Style).Should(Equal("{{blue}}"))
69 Ω(stats.Units).Should(Equal("inches"))
70 Ω(stats.PrecisionBundle.ValueFormat).Should(Equal("%.2f"))
71
72 Ω(stats.ValueBundle[gmeasure.StatMin]).Should(Equal(min))
73 Ω(stats.AnnotationBundle[gmeasure.StatMin]).Should(Equal("B"))
74 Ω(stats.ValueBundle[gmeasure.StatMax]).Should(Equal(max))
75 Ω(stats.AnnotationBundle[gmeasure.StatMax]).Should(Equal("D"))
76 Ω(stats.ValueBundle[gmeasure.StatMedian]).Should(Equal(median))
77 Ω(stats.ValueBundle[gmeasure.StatMean]).Should(Equal(mean))
78 Ω(stats.ValueBundle[gmeasure.StatStdDev]).Should(BeNumerically("~", stdDev))
79 })
80 })
81
82 Describe("Emitting an unstyled report", func() {
83 It("does not include styling", func() {
84 expected := strings.Join([]string{
85 "Test Experiment - flange widths [inches]",
86 "3.14 < [8.97] | <8.56> ±3.59 < 14.25",
87 "Value | Annotation",
88 "==================",
89 " 7.13 | A ",
90 "------------------",
91 " 3.14 | B ",
92 "------------------",
93 " 9.28 | C ",
94 "------------------",
95 "14.25 | D ",
96 "------------------",
97 " 8.97 | E ",
98 "",
99 }, "\n")
100 Ω(measurement.String()).Should(Equal(expected))
101 })
102 })
103
104 Describe("Emitting a styled report", func() {
105 It("does include styling", func() {
106 expected := strings.Join([]string{
107 "{{blue}}Test Experiment - flange widths [inches]{{/}}",
108 "3.14 < [8.97] | <8.56> ±3.59 < 14.25",
109 "{{blue}}Value{{/}} | {{blue}}Annotation{{/}}",
110 "==================",
111 " 7.13 | {{gray}}A {{/}}",
112 "------------------",
113 " 3.14 | {{gray}}B {{/}}",
114 "------------------",
115 " 9.28 | {{gray}}C {{/}}",
116 "------------------",
117 "14.25 | {{gray}}D {{/}}",
118 "------------------",
119 " 8.97 | {{gray}}E {{/}}",
120 "",
121 }, "\n")
122 Ω(measurement.ColorableString()).Should(Equal(expected))
123 })
124 })
125
126 Describe("Computing medians", func() {
127 Context("with an odd number of values", func() {
128 It("returns the middle element", func() {
129 e.RecordValue("odd", 5)
130 e.RecordValue("odd", 1)
131 e.RecordValue("odd", 2)
132 e.RecordValue("odd", 4)
133 e.RecordValue("odd", 3)
134
135 Ω(e.GetStats("odd").ValueBundle[gmeasure.StatMedian]).Should(Equal(3.0))
136 })
137 })
138
139 Context("when an even number of values", func() {
140 It("returns the mean of the two middle elements", func() {
141 e.RecordValue("even", 1)
142 e.RecordValue("even", 2)
143 e.RecordValue("even", 4)
144 e.RecordValue("even", 3)
145
146 Ω(e.GetStats("even").ValueBundle[gmeasure.StatMedian]).Should(Equal(2.5))
147 })
148 })
149 })
150 })
151
152 Describe("Duration Measurement", func() {
153 var min, median, mean, stdDev, max time.Duration
154 BeforeEach(func() {
155 e.RecordDuration("runtime", 7128*time.Millisecond, gmeasure.Annotation("A"), gmeasure.Precision(time.Millisecond*100), gmeasure.Style("{{blue}}"))
156 e.RecordDuration("runtime", 3141*time.Millisecond, gmeasure.Annotation("B"))
157 e.RecordDuration("runtime", 9282*time.Millisecond, gmeasure.Annotation("C"))
158 e.RecordDuration("runtime", 14249*time.Millisecond, gmeasure.Annotation("D"))
159 e.RecordDuration("runtime", 8975*time.Millisecond, gmeasure.Annotation("E"))
160 measurement = e.Measurements[0]
161 min = 3141 * time.Millisecond
162 max = 14249 * time.Millisecond
163 median = 8975 * time.Millisecond
164 mean = ((7128 + 3141 + 9282 + 14249 + 8975) * time.Millisecond) / 5
165 stdDev = time.Duration(math.Sqrt((float64(7128*time.Millisecond-mean)*float64(7128*time.Millisecond-mean) + float64(3141*time.Millisecond-mean)*float64(3141*time.Millisecond-mean) + float64(9282*time.Millisecond-mean)*float64(9282*time.Millisecond-mean) + float64(14249*time.Millisecond-mean)*float64(14249*time.Millisecond-mean) + float64(8975*time.Millisecond-mean)*float64(8975*time.Millisecond-mean)) / 5.0))
166 })
167
168 Describe("Generating Stats", func() {
169 It("generates a correctly configured Stats with correct values", func() {
170 stats := measurement.Stats()
171 Ω(stats.ExperimentName).Should(Equal("Test Experiment"))
172 Ω(stats.MeasurementName).Should(Equal("runtime"))
173 Ω(stats.Style).Should(Equal("{{blue}}"))
174 Ω(stats.Units).Should(Equal("duration"))
175 Ω(stats.PrecisionBundle.Duration).Should(Equal(time.Millisecond * 100))
176
177 Ω(stats.DurationBundle[gmeasure.StatMin]).Should(Equal(min))
178 Ω(stats.AnnotationBundle[gmeasure.StatMin]).Should(Equal("B"))
179 Ω(stats.DurationBundle[gmeasure.StatMax]).Should(Equal(max))
180 Ω(stats.AnnotationBundle[gmeasure.StatMax]).Should(Equal("D"))
181 Ω(stats.DurationBundle[gmeasure.StatMedian]).Should(Equal(median))
182 Ω(stats.DurationBundle[gmeasure.StatMean]).Should(Equal(mean))
183 Ω(stats.DurationBundle[gmeasure.StatStdDev]).Should(Equal(stdDev))
184 })
185 })
186
187 Describe("Emitting an unstyled report", func() {
188 It("does not include styling", func() {
189 expected := strings.Join([]string{
190 "Test Experiment - runtime [duration]",
191 "3.1s < [9s] | <8.6s> ±3.6s < 14.2s",
192 "Duration | Annotation",
193 "=====================",
194 " 7.1s | A ",
195 "---------------------",
196 " 3.1s | B ",
197 "---------------------",
198 " 9.3s | C ",
199 "---------------------",
200 " 14.2s | D ",
201 "---------------------",
202 " 9s | E ",
203 "",
204 }, "\n")
205 Ω(measurement.String()).Should(Equal(expected))
206 })
207 })
208
209 Describe("Emitting a styled report", func() {
210 It("does include styling", func() {
211 expected := strings.Join([]string{
212 "{{blue}}Test Experiment - runtime [duration]{{/}}",
213 "3.1s < [9s] | <8.6s> ±3.6s < 14.2s",
214 "{{blue}}Duration{{/}} | {{blue}}Annotation{{/}}",
215 "=====================",
216 "{{blue}} 7.1s{{/}} | {{gray}}A {{/}}",
217 "---------------------",
218 "{{blue}} 3.1s{{/}} | {{gray}}B {{/}}",
219 "---------------------",
220 "{{blue}} 9.3s{{/}} | {{gray}}C {{/}}",
221 "---------------------",
222 "{{blue}} 14.2s{{/}} | {{gray}}D {{/}}",
223 "---------------------",
224 "{{blue}} 9s{{/}} | {{gray}}E {{/}}",
225 "",
226 }, "\n")
227 Ω(measurement.ColorableString()).Should(Equal(expected))
228 })
229 })
230
231 Describe("Computing medians", func() {
232 Context("with an odd number of values", func() {
233 It("returns the middle element", func() {
234 e.RecordDuration("odd", 5*time.Second)
235 e.RecordDuration("odd", 1*time.Second)
236 e.RecordDuration("odd", 2*time.Second)
237 e.RecordDuration("odd", 4*time.Second)
238 e.RecordDuration("odd", 3*time.Second)
239
240 Ω(e.GetStats("odd").DurationBundle[gmeasure.StatMedian]).Should(Equal(3 * time.Second))
241 })
242 })
243
244 Context("when an even number of values", func() {
245 It("returns the mean of the two middle elements", func() {
246 e.RecordDuration("even", 1*time.Second)
247 e.RecordDuration("even", 2*time.Second)
248 e.RecordDuration("even", 4*time.Second)
249 e.RecordDuration("even", 3*time.Second)
250
251 Ω(e.GetStats("even").DurationBundle[gmeasure.StatMedian]).Should(Equal(2500 * time.Millisecond))
252 })
253 })
254 })
255 })
256 })
257
View as plain text