| Copyright | (c) 2026 |
|---|---|
| License | MIT |
| Maintainer | @ocramz |
| Safe Haskell | None |
| Language | Haskell2010 |
Test.Hspec.BenchGolden.Lenses
Description
This module provides van Laarhoven lenses for GoldenStats fields and
expectation combinators for building custom performance assertions.
Quick Start
import Test.Hspec
import Test.Hspec.BenchGolden
import Test.Hspec.BenchGolden.Lenses
main :: IO ()
main = hspec $ do
describe "Custom Expectations" $ do
-- Expect median within 10% tolerance
benchGoldenWithExpectation "median-based" defaultBenchConfig
[expect _statsMedian (Percent 10.0)]
myAction
-- Expect IQR within absolute 0.5ms
benchGoldenWithExpectation "low variance" defaultBenchConfig
[expect _statsIQR (Absolute 0.5)]
myAction
-- Compose multiple expectations (both must pass)
benchGoldenWithExpectation "composed" defaultBenchConfig
[ expect _statsMean (Percent 15.0) &&~
expect _statsMAD (Percent 50.0)
]
myAction
Lenses
Simple van Laarhoven lenses provide access to GoldenStats fields:
_statsMean,_statsMedian,_statsTrimmedMean- Central tendency metrics_statsStddev,_statsMAD,_statsIQR- Dispersion metrics_statsMin,_statsMax- Range metrics
Smart Selectors
metricFor and varianceFor automatically select the appropriate lens
based on BenchConfig settings:
let lens = metricFor config -- Returns _statsTrimmedMean if useRobustStatistics
baseline = golden ^. lens
current = actual ^. lens
Expectation Combinators
Build expectations with expect and compose them:
Percenttolerance - e.g.,Percent 15.0for ±15%Absolutetolerance - e.g.,Absolute 0.01for ±0.01msHybridtolerance - e.g.,Hybrid 15.0 0.01(pass if either satisfied)
Boolean composition operators:
Infix Operators
For concise tolerance checking:
Synopsis
- _statsMean :: Lens' GoldenStats Double
- _statsStddev :: Lens' GoldenStats Double
- _statsMedian :: Lens' GoldenStats Double
- _statsMin :: Lens' GoldenStats Double
- _statsMax :: Lens' GoldenStats Double
- _statsTrimmedMean :: Lens' GoldenStats Double
- _statsMAD :: Lens' GoldenStats Double
- _statsIQR :: Lens' GoldenStats Double
- metricFor :: BenchConfig -> Lens' GoldenStats Double
- varianceFor :: BenchConfig -> Lens' GoldenStats Double
- data Expectation
- data Tolerance
- expect :: Lens' GoldenStats Double -> Tolerance -> Expectation
- expectStat :: Lens' GoldenStats Double -> Tolerance -> Expectation
- checkExpectation :: Expectation -> GoldenStats -> GoldenStats -> Bool
- withinPercent :: Double -> Double -> Double -> Bool
- withinAbsolute :: Double -> Double -> Double -> Bool
- withinHybrid :: Double -> Double -> Double -> Double -> Bool
- mustImprove :: Double -> Double -> Double -> Bool
- mustRegress :: Double -> Double -> Double -> Bool
- (@~) :: Double -> Double -> Double -> Bool
- (@<) :: Double -> Double -> Double -> Bool
- (@<<) :: Double -> Double -> Double -> Bool
- (@>>) :: Double -> Double -> Double -> Bool
- (&&~) :: Expectation -> Expectation -> Expectation
- (||~) :: Expectation -> Expectation -> Expectation
- percentDiff :: Double -> Double -> Double
- absDiff :: Double -> Double -> Double
- toleranceFromExpectation :: Expectation -> (Double, Maybe Double)
- toleranceValues :: Tolerance -> (Double, Maybe Double)
Lenses for GoldenStats
_statsMean :: Lens' GoldenStats Double Source #
Lens for mean execution time in milliseconds.
_statsStddev :: Lens' GoldenStats Double Source #
Lens for standard deviation in milliseconds.
_statsMedian :: Lens' GoldenStats Double Source #
Lens for median execution time in milliseconds.
_statsTrimmedMean :: Lens' GoldenStats Double Source #
Lens for trimmed mean (with tails removed) in milliseconds.
_statsMAD :: Lens' GoldenStats Double Source #
Lens for median absolute deviation (MAD) in milliseconds.
_statsIQR :: Lens' GoldenStats Double Source #
Lens for interquartile range (IQR = Q3 - Q1) in milliseconds.
Smart Metric Selectors
metricFor :: BenchConfig -> Lens' GoldenStats Double Source #
Select the appropriate central tendency metric based on configuration.
Returns:
_statsTrimmedMeanifuseRobustStatisticsisTrue_statsMeanotherwise
Example:
let lens = metricFor config
baseline = golden ^. lens
current = actual ^. lens
varianceFor :: BenchConfig -> Lens' GoldenStats Double Source #
Select the appropriate dispersion metric based on configuration.
Returns:
_statsMADifuseRobustStatisticsisTrue_statsStddevotherwise
Example:
let vLens = varianceFor config
goldenVar = golden ^. vLens
actualVar = actual ^. vLens
Expectation Types
data Expectation Source #
An expectation for comparing golden and actual statistics.
Expectations can be composed using boolean operators:
expect _statsMean (Percent 15.0) &&~ expect _statsMAD (Percent 50.0)
Constructors
| ExpectStat !(Lens' GoldenStats Double) !Tolerance | Expect a specific field to be within tolerance |
| And !Expectation !Expectation | Both expectations must pass |
| Or !Expectation !Expectation | Either expectation can pass |
Instances
| Show Expectation Source # | |
Defined in Test.Hspec.BenchGolden.Lenses Methods showsPrec :: Int -> Expectation -> ShowS # show :: Expectation -> String # showList :: [Expectation] -> ShowS # | |
| Eq Expectation Source # | |
Defined in Test.Hspec.BenchGolden.Lenses | |
Tolerance specification for performance comparison.
Constructors
| Percent !Double | Percentage tolerance (e.g., |
| Absolute !Double | Absolute tolerance in milliseconds (e.g., |
| Hybrid !Double !Double | Hybrid tolerance: pass if EITHER percentage OR absolute is satisfied
(e.g., |
| MustImprove !Double | Must be faster by at least this percentage (e.g., |
| MustRegress !Double | Must be slower by at least this percentage (e.g., |
Expectation Combinators
expect :: Lens' GoldenStats Double -> Tolerance -> Expectation Source #
Create an expectation for a specific statistic field.
Example:
expect _statsMedian (Percent 10.0) expect _statsIQR (Absolute 0.5) expect _statsMean (Hybrid 15.0 0.01) expect _statsMean (MustImprove 10.0)
expectStat :: Lens' GoldenStats Double -> Tolerance -> Expectation Source #
Create an expectation using a custom lens.
This is an alias for expect for compatibility.
checkExpectation :: Expectation -> GoldenStats -> GoldenStats -> Bool Source #
Tolerance Checking Functions
withinPercent :: Double -> Double -> Double -> Bool Source #
Check if value is within percentage tolerance.
withinPercent 15.0 baseline actual -- within ±15%
withinAbsolute :: Double -> Double -> Double -> Bool Source #
Check if value is within absolute tolerance (milliseconds).
withinAbsolute 0.01 baseline actual -- within ±0.01ms
withinHybrid :: Double -> Double -> Double -> Double -> Bool Source #
Check if value satisfies hybrid tolerance (percentage OR absolute).
withinHybrid 15.0 0.01 baseline actual -- within ±15% OR ±0.01ms
mustImprove :: Double -> Double -> Double -> Bool Source #
Check if actual is faster than baseline by at least the given percentage.
mustImprove 10.0 baseline actual -- must be ≥10% faster
mustRegress :: Double -> Double -> Double -> Bool Source #
Check if actual is slower than baseline by at least the given percentage.
mustRegress 5.0 baseline actual -- must be ≥5% slower
Infix Operators
(@~) :: Double -> Double -> Double -> Bool infixl 4 Source #
Infix operator for percentage tolerance check.
baseline @~ 15.0 $ actual -- within ±15%
(@<) :: Double -> Double -> Double -> Bool infixl 4 Source #
Infix operator for absolute tolerance check.
baseline @< 0.01 $ actual -- within ±0.01ms
(@<<) :: Double -> Double -> Double -> Bool infixl 4 Source #
Infix operator for "must improve" check.
baseline @<< 10.0 $ actual -- must be ≥10% faster
(@>>) :: Double -> Double -> Double -> Bool infixl 4 Source #
Infix operator for "must regress" check.
baseline @>> 5.0 $ actual -- must be ≥5% slower
Boolean Composition
(&&~) :: Expectation -> Expectation -> Expectation infixr 3 Source #
AND composition of expectations (both must pass).
expect _statsMean (Percent 15.0) &&~ expect _statsMAD (Percent 50.0)
(||~) :: Expectation -> Expectation -> Expectation infixr 2 Source #
OR composition of expectations (either can pass).
expect _statsMedian (Percent 10.0) ||~ expect _statsMin (Absolute 0.01)
Utilities
percentDiff :: Double -> Double -> Double Source #
Calculate percentage difference between baseline and actual.
Returns: ((actual - baseline) / baseline) * 100
- Positive = regression (slower)
- Negative = improvement (faster)
- Zero = no change
absDiff :: Double -> Double -> Double Source #
Calculate absolute difference between baseline and actual.
Returns: abs(actual - baseline)
toleranceFromExpectation :: Expectation -> (Double, Maybe Double) Source #
Extract tolerance description from an expectation for error messages. For compound expectations (And/Or), returns the first tolerance found.