@@ -267,6 +267,109 @@ func TestCheck(t *testing.T) {
267267 })
268268}
269269
270+ func TestCheckDiff (t * testing.T ) {
271+ t .Parallel ()
272+
273+ if testing .Short () {
274+ return
275+ }
276+
277+ brakedownFile := t .TempDir () + "/breakdown.testcoverage"
278+ brakedownCurrentFile := t .TempDir () + "/breakdown-current.testcoverage"
279+ brakedownFileEdited := "breakdown-edit.testcoverage"
280+
281+ // run check to generate brakedown file
282+ cfg := Config {
283+ Profile : profileOK ,
284+ BreakdownFileName : brakedownFile ,
285+ SourceDir : sourceDir ,
286+ }
287+ buf := & bytes.Buffer {}
288+ pass , err := Check (buf , cfg )
289+ assert .True (t , pass )
290+ assert .NoError (t , err )
291+
292+ // should pass since brakedown is the same
293+ cfg = Config {
294+ Profile : profileOK ,
295+ SourceDir : sourceDir ,
296+ Diff : Diff {
297+ BaseBreakdownFileName : brakedownFile ,
298+ Threshold : ptr (0.0 ),
299+ },
300+ }
301+ buf = & bytes.Buffer {}
302+ pass , err = Check (buf , cfg )
303+ assert .True (t , pass )
304+ assert .NoError (t , err )
305+ assertDiffNoChange (t , buf .String ())
306+ assertDiffPercentage (t , buf .String (), 0.0 )
307+ assertDiffThreshold (t , buf .String (), * cfg .Diff .Threshold , true )
308+
309+ // should pass since diff is negative
310+ cfg = Config {
311+ Profile : profileOK ,
312+ SourceDir : sourceDir ,
313+ Diff : Diff {
314+ BaseBreakdownFileName : brakedownFile ,
315+ Threshold : ptr (- 0.001 ),
316+ },
317+ }
318+ buf = & bytes.Buffer {}
319+ pass , err = Check (buf , cfg )
320+ assert .True (t , pass )
321+ assert .NoError (t , err )
322+ assertDiffNoChange (t , buf .String ())
323+ assertDiffPercentage (t , buf .String (), 0.0 )
324+ assertDiffThreshold (t , buf .String (), * cfg .Diff .Threshold , true )
325+
326+ // should NOT pass since brakedown is the same, and diff is positive
327+ cfg = Config {
328+ Profile : profileOK ,
329+ SourceDir : sourceDir ,
330+ Diff : Diff {
331+ BaseBreakdownFileName : brakedownFile ,
332+ Threshold : ptr (0.1 ),
333+ },
334+ }
335+ buf = & bytes.Buffer {}
336+ pass , err = Check (buf , cfg )
337+ assert .False (t , pass )
338+ assert .NoError (t , err )
339+ assertDiffNoChange (t , buf .String ())
340+ assertDiffPercentage (t , buf .String (), 0.0 )
341+ assertDiffThreshold (t , buf .String (), * cfg .Diff .Threshold , false )
342+
343+ // change brakedown file to have positive difference
344+ base := readStats (t , brakedownFile )
345+ base [0 ].Covered = 0
346+ base [1 ].Covered = 0
347+
348+ tmpFile , err := os .CreateTemp (t .TempDir (), brakedownFileEdited )
349+ assert .NoError (t , err )
350+ _ , err = tmpFile .Write (coverage .StatsSerialize (base ))
351+ assert .NoError (t , err )
352+
353+ // check should now pass since difference has increased
354+ cfg = Config {
355+ Profile : profileOK ,
356+ SourceDir : sourceDir ,
357+ BreakdownFileName : brakedownCurrentFile ,
358+ Diff : Diff {
359+ BaseBreakdownFileName : tmpFile .Name (),
360+ Threshold : ptr (1.0 ),
361+ },
362+ }
363+ buf = & bytes.Buffer {}
364+ pass , err = Check (buf , cfg )
365+ assert .True (t , pass )
366+ assert .NoError (t , err )
367+
368+ diff := TotalPercentageDiff (readStats (t , brakedownCurrentFile ), base )
369+ assertDiffPercentage (t , buf .String (), diff )
370+ assertDiffThreshold (t , buf .String (), * cfg .Diff .Threshold , true )
371+ }
372+
270373//nolint:paralleltest // must not be parallel because it uses env
271374func TestCheckNoParallel (t * testing.T ) {
272375 if testing .Short () {
@@ -450,6 +553,65 @@ func Test_Analyze(t *testing.T) {
450553 assert .False (t , result .Pass ())
451554 assertPrefix (t , result , prefix , true )
452555 })
556+
557+ t .Run ("diff stats" , func (t * testing.T ) {
558+ t .Parallel ()
559+
560+ stats := randStats (prefix , 10 , 100 )
561+
562+ cfg := Config {}
563+ result := Analyze (cfg , stats , stats )
564+ assert .Empty (t , result .Diff )
565+ assert .True (t , result .Pass ())
566+ assert .Equal (t , 0.0 , result .DiffPercentage ) //nolint:testifylint //relax
567+ })
568+
569+ t .Run ("diff below threshold" , func (t * testing.T ) {
570+ t .Parallel ()
571+
572+ base := []coverage.Stats {{Name : "foo" , Total : 10 , Covered : 1 }}
573+ stats := []coverage.Stats {{Name : "foo" , Total : 10 , Covered : 8 }}
574+
575+ cfg := Config {
576+ Diff : Diff {Threshold : ptr (999.0 )},
577+ }
578+ result := Analyze (cfg , stats , base )
579+ assert .NotEmpty (t , result .Diff )
580+ assert .False (t , result .Pass ())
581+ assert .False (t , result .MeetsDiffThreshold ())
582+ assert .Equal (t , 70.0 , result .DiffPercentage ) //nolint:testifylint //relax
583+ })
584+
585+ t .Run ("diff above threshold" , func (t * testing.T ) {
586+ t .Parallel ()
587+
588+ base := []coverage.Stats {{Name : "foo" , Total : 10 , Covered : 1 }}
589+ stats := []coverage.Stats {{Name : "foo" , Total : 10 , Covered : 8 }}
590+
591+ cfg := Config {
592+ Diff : Diff {Threshold : ptr (1.0 )},
593+ }
594+ result := Analyze (cfg , stats , base )
595+ assert .NotEmpty (t , result .Diff )
596+ assert .True (t , result .Pass ())
597+ assert .True (t , result .MeetsDiffThreshold ())
598+ assert .Equal (t , 70.0 , result .DiffPercentage ) //nolint:testifylint //relax
599+ })
600+
601+ t .Run ("diff above threshold (small diff)" , func (t * testing.T ) {
602+ t .Parallel ()
603+
604+ base := []coverage.Stats {{Name : "foo" , Total : 10000 , Covered : 9999 }}
605+ stats := []coverage.Stats {{Name : "foo" , Total : 10000 , Covered : 10000 }}
606+
607+ cfg := Config {
608+ Diff : Diff {Threshold : ptr (0.0 )},
609+ }
610+ result := Analyze (cfg , stats , base )
611+ assert .True (t , result .Pass ())
612+ assert .True (t , result .MeetsDiffThreshold ())
613+ assert .Equal (t , 0.01 , result .DiffPercentage ) //nolint:testifylint //relax
614+ })
453615}
454616
455617func TestLoadBaseCoverageBreakdown (t * testing.T ) {
0 commit comments