File size: 9,854 Bytes
a10b189 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | {-|
Module : Test.Verify.ReportTests
Description : Tests for verification report serialization and formatting
Copyright : (c) 2026 Ahmad Ali Parr
License : BSL-1.0
Tests covering:
- Report construction
- JSON serialization correctness
- Human-readable formatting
- CSV export
- Deterministic output (same input = same output)
-}
module Test.Verify.ReportTests (tests) where
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (testCase, (@?=), Assertion)
import Assertica.Verify.Report
( VerificationReport (..)
, StageResult (..)
, Verdict (..)
, ErrorDetail (..)
, ErrorCategory (..)
, SourceLocation (..)
, mkStageResult
, mkReport
, toJSON
, toHumanReadable
, toCSV
, isSuccess
, allStagesSuccessful
, stagesToList
)
-- ============================================================================
-- REPORT TESTS
-- ============================================================================
tests :: TestTree
tests = testGroup "Assertica.Verify.Report"
[ testGroup "Report Construction"
[ testCase "successful report has Accept verdict" $
testSuccessfulReportVerdict
, testCase "failed report has Reject verdict" $
testFailedReportVerdict
, testCase "report tracks all stages" $
testReportTracksAllStages
, testCase "report calculates total duration" $
testReportTotalDuration
]
, testGroup "Stage Results"
[ testCase "successful stage is Success" $
testSuccessfulStageIsSuccess
, testCase "failed stage is not Success" $
testFailedStageIsNotSuccess
, testCase "all stages successful works correctly" $
testAllStagesSuccessful
]
, testGroup "JSON Serialization"
[ testCase "JSON contains file path" $
testJSONContainsFilePath
, testCase "JSON contains verdict" $
testJSONContainsVerdict
, testCase "JSON is well-formed" $
testJSONWellFormed
, testCase "JSON serialization is deterministic" $
testJSONDeterministic
]
, testGroup "Human-Readable Format"
[ testCase "text format contains file path" $
testTextContainsFilePath
, testCase "text format contains verdict" $
testTextContainsVerdict
, testCase "text format includes all stages" $
testTextIncludesAllStages
]
, testGroup "CSV Export"
[ testCase "CSV format contains file" $
testCSVContainsFile
, testCase "CSV format contains verdict" $
testCSVContainsVerdict
, testCase "CSV is single line" $
testCSVSingleLine
]
, testGroup "Error Reporting"
[ testCase "error detail in report has location" $
testErrorDetailHasLocation
, testCase "error message is preserved" $
testErrorMessagePreserved
]
, testGroup "Determinism"
[ testCase "same report produces same JSON" $
testJSONDeterminismExact
, testCase "same report produces same text" $
testTextDeterminismExact
]
]
-- ============================================================================
-- REPORT CONSTRUCTION TESTS
-- ============================================================================
testSuccessfulReportVerdict :: Assertion
testSuccessfulReportVerdict =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
in vrVerdict report @?= Accept
testFailedReportVerdict :: Assertion
testFailedReportVerdict =
let successStage = mkStageResult "Test" 10.0
err = ErrorDetail SyntaxError "Test error" Nothing Nothing Nothing
failStage = StageFailed "Test" 10.0 err
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" failStage successStage successStage successStage successStage
in vrVerdict report @?= Reject
testReportTracksAllStages :: Assertion
testReportTracksAllStages =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
in length (stagesToList report) @?= 5
testReportTotalDuration :: Assertion
testReportTotalDuration =
let stage1 = mkStageResult "Stage1" 10.0
stage2 = mkStageResult "Stage2" 20.0
stage3 = mkStageResult "Stage3" 30.0
stage4 = mkStageResult "Stage4" 40.0
stage5 = mkStageResult "Stage5" 50.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage1 stage2 stage3 stage4 stage5
in vrTotalDuration report @?= 150.0
-- ============================================================================
-- STAGE RESULTS TESTS
-- ============================================================================
testSuccessfulStageIsSuccess :: Assertion
testSuccessfulStageIsSuccess =
let stage = mkStageResult "Test" 10.0
in isSuccess stage @?= True
testFailedStageIsNotSuccess :: Assertion
testFailedStageIsNotSuccess =
let err = ErrorDetail SyntaxError "Error" Nothing Nothing Nothing
stage = StageFailed "Test" 10.0 err
in isSuccess stage @?= False
testAllStagesSuccessful :: Assertion
testAllStagesSuccessful =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
in allStagesSuccessful report @?= True
-- ============================================================================
-- JSON SERIALIZATION TESTS
-- ============================================================================
testJSONContainsFilePath :: Assertion
testJSONContainsFilePath =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
json = toJSON report
in ("test.as" `elem` lines json) @?= True
testJSONContainsVerdict :: Assertion
testJSONContainsVerdict =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
json = toJSON report
in ("Accept" `elem` lines json) @?= True
testJSONWellFormed :: Assertion
testJSONWellFormed =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
json = toJSON report
in ('{' `elem` json && '}' `elem` json) @?= True
testJSONDeterministic :: Assertion
testJSONDeterministic =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
json1 = toJSON report
json2 = toJSON report
in json1 @?= json2
testJSONDeterminismExact :: Assertion
testJSONDeterminismExact =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
in toJSON report @?= toJSON report
-- ============================================================================
-- HUMAN-READABLE FORMAT TESTS
-- ============================================================================
testTextContainsFilePath :: Assertion
testTextContainsFilePath =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
text = toHumanReadable report
in ("test.as" `elem` lines text) @?= True
testTextContainsVerdict :: Assertion
testTextContainsVerdict =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
text = toHumanReadable report
in ("Accept" `elem` lines text || any ("Accept" `elem`) (lines text)) @?= True
testTextIncludesAllStages :: Assertion
testTextIncludesAllStages =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
text = toHumanReadable report
in (length (lines text) > 5) @?= True
testTextDeterminismExact :: Assertion
testTextDeterminismExact =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
in toHumanReadable report @?= toHumanReadable report
-- ============================================================================
-- CSV EXPORT TESTS
-- ============================================================================
testCSVContainsFile :: Assertion
testCSVContainsFile =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
csv = toCSV report
in ("test.as" `elem` lines csv) @?= True
testCSVContainsVerdict :: Assertion
testCSVContainsVerdict =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
csv = toCSV report
in ("Accept" `elem` csv) @?= True
testCSVSingleLine :: Assertion
testCSVSingleLine =
let stage = mkStageResult "Test" 10.0
report = mkReport "test.as" Nothing Nothing "2026-01-01T00:00:00Z" stage stage stage stage stage
csv = toCSV report
in length (lines csv) @?= 1
-- ============================================================================
-- ERROR REPORTING TESTS
-- ============================================================================
testErrorDetailHasLocation :: Assertion
testErrorDetailHasLocation =
let loc = SourceLocation "test.as" 1 1
err = ErrorDetail SyntaxError "Test error" (Just loc) Nothing Nothing
in (edLocation err /= Nothing) @?= True
testErrorMessagePreserved :: Assertion
testErrorMessagePreserved =
let msg = "Test error message"
err = ErrorDetail SyntaxError msg Nothing Nothing Nothing
in edMessage err @?= msg
|