| 1 | |
|---|
| 2 | New patches: |
|---|
| 3 | |
|---|
| 4 | [changed file extensions from .lhs to .hs |
|---|
| 5 | Leif Frenzel <leiffrenzel@googlemail.com>**20070717153017] { |
|---|
| 6 | move ./Test/HUnit.lhs ./Test/HUnit.hs |
|---|
| 7 | move ./Test/HUnit/Base.lhs ./Test/HUnit/Base.hs |
|---|
| 8 | move ./Test/HUnit/Lang.lhs ./Test/HUnit/Lang.hs |
|---|
| 9 | move ./Test/HUnit/Terminal.lhs ./Test/HUnit/Terminal.hs |
|---|
| 10 | move ./Test/HUnit/Text.lhs ./Test/HUnit/Text.hs |
|---|
| 11 | } |
|---|
| 12 | |
|---|
| 13 | [un-literated code |
|---|
| 14 | Leif Frenzel <leiffrenzel@googlemail.com>**20070717154325] { |
|---|
| 15 | hunk ./Test/HUnit.hs 1 |
|---|
| 16 | -HUnit.lhs -- interface module for HUnit |
|---|
| 17 | - |
|---|
| 18 | -> module Test.HUnit |
|---|
| 19 | -> ( |
|---|
| 20 | -> module Test.HUnit.Base, |
|---|
| 21 | -> module Test.HUnit.Text |
|---|
| 22 | -> ) |
|---|
| 23 | -> where |
|---|
| 24 | - |
|---|
| 25 | -> import Test.HUnit.Base |
|---|
| 26 | -> import Test.HUnit.Text |
|---|
| 27 | +-- interface module for HUnit |
|---|
| 28 | + |
|---|
| 29 | +module Test.HUnit |
|---|
| 30 | +( |
|---|
| 31 | + module Test.HUnit.Base, |
|---|
| 32 | + module Test.HUnit.Text |
|---|
| 33 | +) |
|---|
| 34 | +where |
|---|
| 35 | + |
|---|
| 36 | +import Test.HUnit.Base |
|---|
| 37 | +import Test.HUnit.Text |
|---|
| 38 | hunk ./Test/HUnit/Base.hs 1 |
|---|
| 39 | -HUnitBase.lhs -- basic definitions |
|---|
| 40 | - |
|---|
| 41 | -> module Test.HUnit.Base |
|---|
| 42 | -> ( |
|---|
| 43 | -> {- from Test.HUnit.Lang: -} Assertion, assertFailure, |
|---|
| 44 | -> assertString, assertBool, assertEqual, |
|---|
| 45 | -> Assertable(..), ListAssertable(..), |
|---|
| 46 | -> AssertionPredicate, AssertionPredicable(..), |
|---|
| 47 | -> (@?), (@=?), (@?=), |
|---|
| 48 | -> Test(..), Node(..), Path, |
|---|
| 49 | -> testCaseCount, |
|---|
| 50 | -> Testable(..), |
|---|
| 51 | -> (~?), (~=?), (~?=), (~:), |
|---|
| 52 | -> Counts(..), State(..), |
|---|
| 53 | -> ReportStart, ReportProblem, |
|---|
| 54 | -> testCasePaths, |
|---|
| 55 | -> performTest |
|---|
| 56 | -> ) |
|---|
| 57 | -> where |
|---|
| 58 | - |
|---|
| 59 | -> import Control.Monad (unless, foldM) |
|---|
| 60 | - |
|---|
| 61 | - |
|---|
| 62 | -Assertion Definition |
|---|
| 63 | -==================== |
|---|
| 64 | - |
|---|
| 65 | -> import Test.HUnit.Lang |
|---|
| 66 | - |
|---|
| 67 | - |
|---|
| 68 | -Conditional Assertion Functions |
|---|
| 69 | -------------------------------- |
|---|
| 70 | - |
|---|
| 71 | -> assertBool :: String -> Bool -> Assertion |
|---|
| 72 | -> assertBool msg b = unless b (assertFailure msg) |
|---|
| 73 | - |
|---|
| 74 | -> assertString :: String -> Assertion |
|---|
| 75 | -> assertString s = unless (null s) (assertFailure s) |
|---|
| 76 | - |
|---|
| 77 | -> assertEqual :: (Eq a, Show a) => String -> a -> a -> Assertion |
|---|
| 78 | -> assertEqual preface expected actual = |
|---|
| 79 | -> unless (actual == expected) (assertFailure msg) |
|---|
| 80 | -> where msg = (if null preface then "" else preface ++ "\n") ++ |
|---|
| 81 | -> "expected: " ++ show expected ++ "\n but got: " ++ show actual |
|---|
| 82 | - |
|---|
| 83 | - |
|---|
| 84 | -Overloaded `assert` Function |
|---|
| 85 | ----------------------------- |
|---|
| 86 | - |
|---|
| 87 | -> class Assertable t |
|---|
| 88 | -> where assert :: t -> Assertion |
|---|
| 89 | - |
|---|
| 90 | -> instance Assertable () |
|---|
| 91 | -> where assert = return |
|---|
| 92 | - |
|---|
| 93 | -> instance Assertable Bool |
|---|
| 94 | -> where assert = assertBool "" |
|---|
| 95 | - |
|---|
| 96 | -> instance (ListAssertable t) => Assertable [t] |
|---|
| 97 | -> where assert = listAssert |
|---|
| 98 | - |
|---|
| 99 | -> instance (Assertable t) => Assertable (IO t) |
|---|
| 100 | -> where assert = (>>= assert) |
|---|
| 101 | - |
|---|
| 102 | -We define the assertability of `[Char]` (that is, `String`) and leave |
|---|
| 103 | -other types of list to possible user extension. |
|---|
| 104 | - |
|---|
| 105 | -> class ListAssertable t |
|---|
| 106 | -> where listAssert :: [t] -> Assertion |
|---|
| 107 | - |
|---|
| 108 | -> instance ListAssertable Char |
|---|
| 109 | -> where listAssert = assertString |
|---|
| 110 | - |
|---|
| 111 | - |
|---|
| 112 | -Overloaded `assertionPredicate` Function |
|---|
| 113 | ----------------------------------------- |
|---|
| 114 | - |
|---|
| 115 | -> type AssertionPredicate = IO Bool |
|---|
| 116 | - |
|---|
| 117 | -> class AssertionPredicable t |
|---|
| 118 | -> where assertionPredicate :: t -> AssertionPredicate |
|---|
| 119 | - |
|---|
| 120 | -> instance AssertionPredicable Bool |
|---|
| 121 | -> where assertionPredicate = return |
|---|
| 122 | - |
|---|
| 123 | -> instance (AssertionPredicable t) => AssertionPredicable (IO t) |
|---|
| 124 | -> where assertionPredicate = (>>= assertionPredicate) |
|---|
| 125 | - |
|---|
| 126 | - |
|---|
| 127 | -Assertion Construction Operators |
|---|
| 128 | --------------------------------- |
|---|
| 129 | - |
|---|
| 130 | -> infix 1 @?, @=?, @?= |
|---|
| 131 | - |
|---|
| 132 | -> (@?) :: (AssertionPredicable t) => t -> String -> Assertion |
|---|
| 133 | -> pred @? msg = assertionPredicate pred >>= assertBool msg |
|---|
| 134 | - |
|---|
| 135 | -> (@=?) :: (Eq a, Show a) => a -> a -> Assertion |
|---|
| 136 | -> expected @=? actual = assertEqual "" expected actual |
|---|
| 137 | - |
|---|
| 138 | -> (@?=) :: (Eq a, Show a) => a -> a -> Assertion |
|---|
| 139 | -> actual @?= expected = assertEqual "" expected actual |
|---|
| 140 | - |
|---|
| 141 | - |
|---|
| 142 | - |
|---|
| 143 | -Test Definition |
|---|
| 144 | -=============== |
|---|
| 145 | - |
|---|
| 146 | -> data Test = TestCase Assertion |
|---|
| 147 | -> | TestList [Test] |
|---|
| 148 | -> | TestLabel String Test |
|---|
| 149 | - |
|---|
| 150 | -> instance Show Test where |
|---|
| 151 | -> showsPrec p (TestCase _) = showString "TestCase _" |
|---|
| 152 | -> showsPrec p (TestList ts) = showString "TestList " . showList ts |
|---|
| 153 | -> showsPrec p (TestLabel l t) = showString "TestLabel " . showString l |
|---|
| 154 | -> . showChar ' ' . showsPrec p t |
|---|
| 155 | - |
|---|
| 156 | -> testCaseCount :: Test -> Int |
|---|
| 157 | -> testCaseCount (TestCase _) = 1 |
|---|
| 158 | -> testCaseCount (TestList ts) = sum (map testCaseCount ts) |
|---|
| 159 | -> testCaseCount (TestLabel _ t) = testCaseCount t |
|---|
| 160 | - |
|---|
| 161 | - |
|---|
| 162 | -> data Node = ListItem Int | Label String |
|---|
| 163 | -> deriving (Eq, Show, Read) |
|---|
| 164 | - |
|---|
| 165 | -> type Path = [Node] -- Node order is from test case to root. |
|---|
| 166 | - |
|---|
| 167 | - |
|---|
| 168 | -> testCasePaths :: Test -> [Path] |
|---|
| 169 | -> testCasePaths t = tcp t [] |
|---|
| 170 | -> where tcp (TestCase _) p = [p] |
|---|
| 171 | -> tcp (TestList ts) p = |
|---|
| 172 | -> concat [ tcp t (ListItem n : p) | (t,n) <- zip ts [0..] ] |
|---|
| 173 | -> tcp (TestLabel l t) p = tcp t (Label l : p) |
|---|
| 174 | - |
|---|
| 175 | - |
|---|
| 176 | -Overloaded `test` Function |
|---|
| 177 | --------------------------- |
|---|
| 178 | - |
|---|
| 179 | -> class Testable t |
|---|
| 180 | -> where test :: t -> Test |
|---|
| 181 | - |
|---|
| 182 | -> instance Testable Test |
|---|
| 183 | -> where test = id |
|---|
| 184 | - |
|---|
| 185 | -> instance (Assertable t) => Testable (IO t) |
|---|
| 186 | -> where test = TestCase . assert |
|---|
| 187 | - |
|---|
| 188 | -> instance (Testable t) => Testable [t] |
|---|
| 189 | -> where test = TestList . map test |
|---|
| 190 | - |
|---|
| 191 | - |
|---|
| 192 | -Test Construction Operators |
|---|
| 193 | ---------------------------- |
|---|
| 194 | - |
|---|
| 195 | -> infix 1 ~?, ~=?, ~?= |
|---|
| 196 | -> infixr 0 ~: |
|---|
| 197 | - |
|---|
| 198 | -> (~?) :: (AssertionPredicable t) => t -> String -> Test |
|---|
| 199 | -> pred ~? msg = TestCase (pred @? msg) |
|---|
| 200 | - |
|---|
| 201 | -> (~=?) :: (Eq a, Show a) => a -> a -> Test |
|---|
| 202 | -> expected ~=? actual = TestCase (expected @=? actual) |
|---|
| 203 | - |
|---|
| 204 | -> (~?=) :: (Eq a, Show a) => a -> a -> Test |
|---|
| 205 | -> actual ~?= expected = TestCase (actual @?= expected) |
|---|
| 206 | - |
|---|
| 207 | -> (~:) :: (Testable t) => String -> t -> Test |
|---|
| 208 | -> label ~: t = TestLabel label (test t) |
|---|
| 209 | - |
|---|
| 210 | - |
|---|
| 211 | - |
|---|
| 212 | -Test Execution |
|---|
| 213 | -============== |
|---|
| 214 | - |
|---|
| 215 | -> data Counts = Counts { cases, tried, errors, failures :: Int } |
|---|
| 216 | -> deriving (Eq, Show, Read) |
|---|
| 217 | - |
|---|
| 218 | -> data State = State { path :: Path, counts :: Counts } |
|---|
| 219 | -> deriving (Eq, Show, Read) |
|---|
| 220 | - |
|---|
| 221 | -> type ReportStart us = State -> us -> IO us |
|---|
| 222 | - |
|---|
| 223 | -> type ReportProblem us = String -> State -> us -> IO us |
|---|
| 224 | - |
|---|
| 225 | - |
|---|
| 226 | -Note that the counts in a start report do not include the test case |
|---|
| 227 | -being started, whereas the counts in a problem report do include the |
|---|
| 228 | -test case just finished. The principle is that the counts are sampled |
|---|
| 229 | -only between test case executions. As a result, the number of test |
|---|
| 230 | -case successes always equals the difference of test cases tried and |
|---|
| 231 | -the sum of test case errors and failures. |
|---|
| 232 | - |
|---|
| 233 | - |
|---|
| 234 | -> performTest :: ReportStart us -> ReportProblem us -> ReportProblem us |
|---|
| 235 | -> -> us -> Test -> IO (Counts, us) |
|---|
| 236 | -> performTest reportStart reportError reportFailure us t = do |
|---|
| 237 | -> (ss', us') <- pt initState us t |
|---|
| 238 | -> unless (null (path ss')) $ error "performTest: Final path is nonnull" |
|---|
| 239 | -> return (counts ss', us') |
|---|
| 240 | -> where |
|---|
| 241 | -> initState = State{ path = [], counts = initCounts } |
|---|
| 242 | -> initCounts = Counts{ cases = testCaseCount t, tried = 0, |
|---|
| 243 | -> errors = 0, failures = 0} |
|---|
| 244 | - |
|---|
| 245 | -> pt ss us (TestCase a) = do |
|---|
| 246 | -> us' <- reportStart ss us |
|---|
| 247 | -> r <- performTestCase a |
|---|
| 248 | -> case r of Nothing -> do return (ss', us') |
|---|
| 249 | -> Just (True, m) -> do usF <- reportFailure m ssF us' |
|---|
| 250 | -> return (ssF, usF) |
|---|
| 251 | -> Just (False, m) -> do usE <- reportError m ssE us' |
|---|
| 252 | -> return (ssE, usE) |
|---|
| 253 | -> where c@Counts{ tried = t } = counts ss |
|---|
| 254 | -> ss' = ss{ counts = c{ tried = t + 1 } } |
|---|
| 255 | -> ssF = ss{ counts = c{ tried = t + 1, failures = failures c + 1 } } |
|---|
| 256 | -> ssE = ss{ counts = c{ tried = t + 1, errors = errors c + 1 } } |
|---|
| 257 | - |
|---|
| 258 | -> pt ss us (TestList ts) = foldM f (ss, us) (zip ts [0..]) |
|---|
| 259 | -> where f (ss, us) (t, n) = withNode (ListItem n) ss us t |
|---|
| 260 | - |
|---|
| 261 | -> pt ss us (TestLabel label t) = withNode (Label label) ss us t |
|---|
| 262 | - |
|---|
| 263 | -> withNode node ss0 us0 t = do (ss2, us1) <- pt ss1 us0 t |
|---|
| 264 | -> return (ss2{ path = path0 }, us1) |
|---|
| 265 | -> where path0 = path ss0 |
|---|
| 266 | -> ss1 = ss0{ path = node : path0 } |
|---|
| 267 | +-- basic definitions |
|---|
| 268 | + |
|---|
| 269 | +module Test.HUnit.Base |
|---|
| 270 | +( |
|---|
| 271 | + {- from Test.HUnit.Lang: -} Assertion, assertFailure, |
|---|
| 272 | + assertString, assertBool, assertEqual, |
|---|
| 273 | + Assertable(..), ListAssertable(..), |
|---|
| 274 | + AssertionPredicate, AssertionPredicable(..), |
|---|
| 275 | + (@?), (@=?), (@?=), |
|---|
| 276 | + Test(..), Node(..), Path, |
|---|
| 277 | + testCaseCount, |
|---|
| 278 | + Testable(..), |
|---|
| 279 | + (~?), (~=?), (~?=), (~:), |
|---|
| 280 | + Counts(..), State(..), |
|---|
| 281 | + ReportStart, ReportProblem, |
|---|
| 282 | + testCasePaths, |
|---|
| 283 | + performTest |
|---|
| 284 | +) |
|---|
| 285 | +where |
|---|
| 286 | + |
|---|
| 287 | +import Control.Monad (unless, foldM) |
|---|
| 288 | + |
|---|
| 289 | + |
|---|
| 290 | +-- Assertion Definition |
|---|
| 291 | +-- ==================== |
|---|
| 292 | + |
|---|
| 293 | +import Test.HUnit.Lang |
|---|
| 294 | + |
|---|
| 295 | + |
|---|
| 296 | +-- Conditional Assertion Functions |
|---|
| 297 | +-- ------------------------------- |
|---|
| 298 | + |
|---|
| 299 | +assertBool :: String -> Bool -> Assertion |
|---|
| 300 | +assertBool msg b = unless b (assertFailure msg) |
|---|
| 301 | + |
|---|
| 302 | +assertString :: String -> Assertion |
|---|
| 303 | +assertString s = unless (null s) (assertFailure s) |
|---|
| 304 | + |
|---|
| 305 | +assertEqual :: (Eq a, Show a) => String -> a -> a -> Assertion |
|---|
| 306 | +assertEqual preface expected actual = |
|---|
| 307 | + unless (actual == expected) (assertFailure msg) |
|---|
| 308 | + where msg = (if null preface then "" else preface ++ "\n") ++ |
|---|
| 309 | + "expected: " ++ show expected ++ "\n but got: " ++ show actual |
|---|
| 310 | + |
|---|
| 311 | + |
|---|
| 312 | +-- Overloaded `assert` Function |
|---|
| 313 | +-- ---------------------------- |
|---|
| 314 | + |
|---|
| 315 | +class Assertable t |
|---|
| 316 | + where assert :: t -> Assertion |
|---|
| 317 | + |
|---|
| 318 | +instance Assertable () |
|---|
| 319 | + where assert = return |
|---|
| 320 | + |
|---|
| 321 | +instance Assertable Bool |
|---|
| 322 | + where assert = assertBool "" |
|---|
| 323 | + |
|---|
| 324 | +instance (ListAssertable t) => Assertable [t] |
|---|
| 325 | + where assert = listAssert |
|---|
| 326 | + |
|---|
| 327 | +instance (Assertable t) => Assertable (IO t) |
|---|
| 328 | + where assert = (>>= assert) |
|---|
| 329 | + |
|---|
| 330 | +-- We define the assertability of `[Char]` (that is, `String`) and leave |
|---|
| 331 | +-- other types of list to possible user extension. |
|---|
| 332 | + |
|---|
| 333 | +class ListAssertable t |
|---|
| 334 | + where listAssert :: [t] -> Assertion |
|---|
| 335 | + |
|---|
| 336 | +instance ListAssertable Char |
|---|
| 337 | + where listAssert = assertString |
|---|
| 338 | + |
|---|
| 339 | + |
|---|
| 340 | +-- Overloaded `assertionPredicate` Function |
|---|
| 341 | +-- ---------------------------------------- |
|---|
| 342 | + |
|---|
| 343 | +type AssertionPredicate = IO Bool |
|---|
| 344 | + |
|---|
| 345 | +class AssertionPredicable t |
|---|
| 346 | + where assertionPredicate :: t -> AssertionPredicate |
|---|
| 347 | + |
|---|
| 348 | +instance AssertionPredicable Bool |
|---|
| 349 | + where assertionPredicate = return |
|---|
| 350 | + |
|---|
| 351 | +instance (AssertionPredicable t) => AssertionPredicable (IO t) |
|---|
| 352 | + where assertionPredicate = (>>= assertionPredicate) |
|---|
| 353 | + |
|---|
| 354 | + |
|---|
| 355 | +-- Assertion Construction Operators |
|---|
| 356 | +-- -------------------------------- |
|---|
| 357 | + |
|---|
| 358 | +infix 1 @?, @=?, @?= |
|---|
| 359 | + |
|---|
| 360 | +(@?) :: (AssertionPredicable t) => t -> String -> Assertion |
|---|
| 361 | +pred @? msg = assertionPredicate pred >>= assertBool msg |
|---|
| 362 | + |
|---|
| 363 | +(@=?) :: (Eq a, Show a) => a -> a -> Assertion |
|---|
| 364 | +expected @=? actual = assertEqual "" expected actual |
|---|
| 365 | + |
|---|
| 366 | +(@?=) :: (Eq a, Show a) => a -> a -> Assertion |
|---|
| 367 | +actual @?= expected = assertEqual "" expected actual |
|---|
| 368 | + |
|---|
| 369 | + |
|---|
| 370 | + |
|---|
| 371 | +-- Test Definition |
|---|
| 372 | +-- =============== |
|---|
| 373 | + |
|---|
| 374 | +data Test = TestCase Assertion |
|---|
| 375 | + | TestList [Test] |
|---|
| 376 | + | TestLabel String Test |
|---|
| 377 | + |
|---|
| 378 | +instance Show Test where |
|---|
| 379 | + showsPrec p (TestCase _) = showString "TestCase _" |
|---|
| 380 | + showsPrec p (TestList ts) = showString "TestList " . showList ts |
|---|
| 381 | + showsPrec p (TestLabel l t) = showString "TestLabel " . showString l |
|---|
| 382 | + . showChar ' ' . showsPrec p t |
|---|
| 383 | + |
|---|
| 384 | +testCaseCount :: Test -> Int |
|---|
| 385 | +testCaseCount (TestCase _) = 1 |
|---|
| 386 | +testCaseCount (TestList ts) = sum (map testCaseCount ts) |
|---|
| 387 | +testCaseCount (TestLabel _ t) = testCaseCount t |
|---|
| 388 | + |
|---|
| 389 | + |
|---|
| 390 | +data Node = ListItem Int | Label String |
|---|
| 391 | + deriving (Eq, Show, Read) |
|---|
| 392 | + |
|---|
| 393 | +type Path = [Node] -- Node order is from test case to root. |
|---|
| 394 | + |
|---|
| 395 | + |
|---|
| 396 | +testCasePaths :: Test -> [Path] |
|---|
| 397 | +testCasePaths t = tcp t [] |
|---|
| 398 | + where tcp (TestCase _) p = [p] |
|---|
| 399 | + tcp (TestList ts) p = |
|---|
| 400 | + concat [ tcp t (ListItem n : p) | (t,n) <- zip ts [0..] ] |
|---|
| 401 | + tcp (TestLabel l t) p = tcp t (Label l : p) |
|---|
| 402 | + |
|---|
| 403 | + |
|---|
| 404 | +-- Overloaded `test` Function |
|---|
| 405 | +-- -------------------------- |
|---|
| 406 | + |
|---|
| 407 | +class Testable t |
|---|
| 408 | + where test :: t -> Test |
|---|
| 409 | + |
|---|
| 410 | +instance Testable Test |
|---|
| 411 | + where test = id |
|---|
| 412 | + |
|---|
| 413 | +instance (Assertable t) => Testable (IO t) |
|---|
| 414 | + where test = TestCase . assert |
|---|
| 415 | + |
|---|
| 416 | +instance (Testable t) => Testable [t] |
|---|
| 417 | + where test = TestList . map test |
|---|
| 418 | + |
|---|
| 419 | + |
|---|
| 420 | +-- Test Construction Operators |
|---|
| 421 | +-- --------------------------- |
|---|
| 422 | + |
|---|
| 423 | +infix 1 ~?, ~=?, ~?= |
|---|
| 424 | +infixr 0 ~: |
|---|
| 425 | + |
|---|
| 426 | +(~?) :: (AssertionPredicable t) => t -> String -> Test |
|---|
| 427 | +pred ~? msg = TestCase (pred @? msg) |
|---|
| 428 | + |
|---|
| 429 | +(~=?) :: (Eq a, Show a) => a -> a -> Test |
|---|
| 430 | +expected ~=? actual = TestCase (expected @=? actual) |
|---|
| 431 | + |
|---|
| 432 | +(~?=) :: (Eq a, Show a) => a -> a -> Test |
|---|
| 433 | +actual ~?= expected = TestCase (actual @?= expected) |
|---|
| 434 | + |
|---|
| 435 | +(~:) :: (Testable t) => String -> t -> Test |
|---|
| 436 | +label ~: t = TestLabel label (test t) |
|---|
| 437 | + |
|---|
| 438 | + |
|---|
| 439 | + |
|---|
| 440 | +-- Test Execution |
|---|
| 441 | +-- ============== |
|---|
| 442 | + |
|---|
| 443 | +data Counts = Counts { cases, tried, errors, failures :: Int } |
|---|
| 444 | + deriving (Eq, Show, Read) |
|---|
| 445 | + |
|---|
| 446 | +data State = State { path :: Path, counts :: Counts } |
|---|
| 447 | + deriving (Eq, Show, Read) |
|---|
| 448 | + |
|---|
| 449 | +type ReportStart us = State -> us -> IO us |
|---|
| 450 | + |
|---|
| 451 | +type ReportProblem us = String -> State -> us -> IO us |
|---|
| 452 | + |
|---|
| 453 | + |
|---|
| 454 | +-- Note that the counts in a start report do not include the test case |
|---|
| 455 | +-- being started, whereas the counts in a problem report do include the |
|---|
| 456 | +-- test case just finished. The principle is that the counts are sampled |
|---|
| 457 | +-- only between test case executions. As a result, the number of test |
|---|
| 458 | +-- case successes always equals the difference of test cases tried and |
|---|
| 459 | +-- the sum of test case errors and failures. |
|---|
| 460 | + |
|---|
| 461 | + |
|---|
| 462 | +performTest :: ReportStart us -> ReportProblem us -> ReportProblem us |
|---|
| 463 | + -> us -> Test -> IO (Counts, us) |
|---|
| 464 | +performTest reportStart reportError reportFailure us t = do |
|---|
| 465 | + (ss', us') <- pt initState us t |
|---|
| 466 | + unless (null (path ss')) $ error "performTest: Final path is nonnull" |
|---|
| 467 | + return (counts ss', us') |
|---|
| 468 | + where |
|---|
| 469 | + initState = State{ path = [], counts = initCounts } |
|---|
| 470 | + initCounts = Counts{ cases = testCaseCount t, tried = 0, |
|---|
| 471 | + errors = 0, failures = 0} |
|---|
| 472 | + |
|---|
| 473 | + pt ss us (TestCase a) = do |
|---|
| 474 | + us' <- reportStart ss us |
|---|
| 475 | + r <- performTestCase a |
|---|
| 476 | + case r of Nothing -> do return (ss', us') |
|---|
| 477 | + Just (True, m) -> do usF <- reportFailure m ssF us' |
|---|
| 478 | + return (ssF, usF) |
|---|
| 479 | + Just (False, m) -> do usE <- reportError m ssE us' |
|---|
| 480 | + return (ssE, usE) |
|---|
| 481 | + where c@Counts{ tried = t } = counts ss |
|---|
| 482 | + ss' = ss{ counts = c{ tried = t + 1 } } |
|---|
| 483 | + ssF = ss{ counts = c{ tried = t + 1, failures = failures c + 1 } } |
|---|
| 484 | + ssE = ss{ counts = c{ tried = t + 1, errors = errors c + 1 } } |
|---|
| 485 | + |
|---|
| 486 | + pt ss us (TestList ts) = foldM f (ss, us) (zip ts [0..]) |
|---|
| 487 | + where f (ss, us) (t, n) = withNode (ListItem n) ss us t |
|---|
| 488 | + |
|---|
| 489 | + pt ss us (TestLabel label t) = withNode (Label label) ss us t |
|---|
| 490 | + |
|---|
| 491 | + withNode node ss0 us0 t = do (ss2, us1) <- pt ss1 us0 t |
|---|
| 492 | + return (ss2{ path = path0 }, us1) |
|---|
| 493 | + where path0 = path ss0 |
|---|
| 494 | + ss1 = ss0{ path = node : path0 } |
|---|
| 495 | hunk ./Test/HUnit/Lang.hs 1 |
|---|
| 496 | -Test/HUnit/Lang.lhs -- HUnit language support. |
|---|
| 497 | - |
|---|
| 498 | -> module Test.HUnit.Lang |
|---|
| 499 | -> ( |
|---|
| 500 | -> Assertion, |
|---|
| 501 | -> assertFailure, |
|---|
| 502 | -> performTestCase |
|---|
| 503 | -> ) |
|---|
| 504 | -> where |
|---|
| 505 | - |
|---|
| 506 | - |
|---|
| 507 | -When adapting this module for other Haskell language systems, change |
|---|
| 508 | -the imports and the implementations but not the interfaces. |
|---|
| 509 | - |
|---|
| 510 | - |
|---|
| 511 | - |
|---|
| 512 | -Imports |
|---|
| 513 | -------- |
|---|
| 514 | - |
|---|
| 515 | -> import Data.List (isPrefixOf) |
|---|
| 516 | -#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__) |
|---|
| 517 | -> import Data.Dynamic |
|---|
| 518 | -> import Control.Exception as E ( throwDyn, try, Exception(..) ) |
|---|
| 519 | -#else |
|---|
| 520 | -> import System.IO.Error (ioeGetErrorString, try) |
|---|
| 521 | -#endif |
|---|
| 522 | - |
|---|
| 523 | - |
|---|
| 524 | - |
|---|
| 525 | -Interfaces |
|---|
| 526 | ----------- |
|---|
| 527 | - |
|---|
| 528 | -An assertion is an `IO` computation with trivial result. |
|---|
| 529 | - |
|---|
| 530 | -> type Assertion = IO () |
|---|
| 531 | - |
|---|
| 532 | -`assertFailure` signals an assertion failure with a given message. |
|---|
| 533 | - |
|---|
| 534 | -> assertFailure :: String -> Assertion |
|---|
| 535 | - |
|---|
| 536 | -`performTestCase` performs a single test case. The meaning of the |
|---|
| 537 | -result is as follows: |
|---|
| 538 | - Nothing test case success |
|---|
| 539 | - Just (True, msg) test case failure with the given message |
|---|
| 540 | - Just (False, msg) test case error with the given message |
|---|
| 541 | - |
|---|
| 542 | -> performTestCase :: Assertion -> IO (Maybe (Bool, String)) |
|---|
| 543 | - |
|---|
| 544 | - |
|---|
| 545 | -Implementations |
|---|
| 546 | ---------------- |
|---|
| 547 | - |
|---|
| 548 | -#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__) |
|---|
| 549 | -> data HUnitFailure = HUnitFailure String |
|---|
| 550 | -> |
|---|
| 551 | -> hunitFailureTc :: TyCon |
|---|
| 552 | -> hunitFailureTc = mkTyCon "HUnitFailure" |
|---|
| 553 | -> {-# NOINLINE hunitFailureTc #-} |
|---|
| 554 | -> |
|---|
| 555 | -> instance Typeable HUnitFailure where |
|---|
| 556 | -> typeOf _ = mkTyConApp hunitFailureTc [] |
|---|
| 557 | - |
|---|
| 558 | -> assertFailure msg = E.throwDyn (HUnitFailure msg) |
|---|
| 559 | - |
|---|
| 560 | -> performTestCase action = |
|---|
| 561 | -> do r <- E.try action |
|---|
| 562 | -> case r of |
|---|
| 563 | -> Right () -> return Nothing |
|---|
| 564 | -> Left e@(E.DynException dyn) -> |
|---|
| 565 | -> case fromDynamic dyn of |
|---|
| 566 | -> Just (HUnitFailure msg) -> return $ Just (True, msg) |
|---|
| 567 | -> Nothing -> return $ Just (False, show e) |
|---|
| 568 | -> Left e -> return $ Just (False, show e) |
|---|
| 569 | -#else |
|---|
| 570 | -> hunitPrefix = "HUnit:" |
|---|
| 571 | - |
|---|
| 572 | -> nhc98Prefix = "I/O error (user-defined), call to function `userError':\n " |
|---|
| 573 | - |
|---|
| 574 | -> assertFailure msg = ioError (userError (hunitPrefix ++ msg)) |
|---|
| 575 | - |
|---|
| 576 | -> performTestCase action = do r <- try action |
|---|
| 577 | -> case r of Right () -> return Nothing |
|---|
| 578 | -> Left e -> return (Just (decode e)) |
|---|
| 579 | -> where |
|---|
| 580 | -> decode e = let s0 = ioeGetErrorString e |
|---|
| 581 | -> (_, s1) = dropPrefix nhc98Prefix s0 |
|---|
| 582 | -> in dropPrefix hunitPrefix s1 |
|---|
| 583 | -> dropPrefix pref str = if pref `isPrefixOf` str |
|---|
| 584 | -> then (True, drop (length pref) str) |
|---|
| 585 | -> else (False, str) |
|---|
| 586 | -#endif |
|---|
| 587 | +-- HUnit language support. |
|---|
| 588 | + |
|---|
| 589 | +module Test.HUnit.Lang |
|---|
| 590 | +( |
|---|
| 591 | + Assertion, |
|---|
| 592 | + assertFailure, |
|---|
| 593 | + performTestCase |
|---|
| 594 | +) |
|---|
| 595 | +where |
|---|
| 596 | + |
|---|
| 597 | + |
|---|
| 598 | +-- When adapting this module for other Haskell language systems, change |
|---|
| 599 | +-- the imports and the implementations but not the interfaces. |
|---|
| 600 | + |
|---|
| 601 | + |
|---|
| 602 | + |
|---|
| 603 | +-- Imports |
|---|
| 604 | +-- ------- |
|---|
| 605 | + |
|---|
| 606 | +import Data.List (isPrefixOf) |
|---|
| 607 | +#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__) |
|---|
| 608 | +import Data.Dynamic |
|---|
| 609 | +import Control.Exception as E ( throwDyn, try, Exception(..) ) |
|---|
| 610 | +#else |
|---|
| 611 | +import System.IO.Error (ioeGetErrorString, try) |
|---|
| 612 | +#endif |
|---|
| 613 | + |
|---|
| 614 | + |
|---|
| 615 | + |
|---|
| 616 | +-- Interfaces |
|---|
| 617 | +-- ---------- |
|---|
| 618 | + |
|---|
| 619 | +-- An assertion is an `IO` computation with trivial result. |
|---|
| 620 | + |
|---|
| 621 | +type Assertion = IO () |
|---|
| 622 | + |
|---|
| 623 | +-- `assertFailure` signals an assertion failure with a given message. |
|---|
| 624 | + |
|---|
| 625 | +assertFailure :: String -> Assertion |
|---|
| 626 | + |
|---|
| 627 | +-- `performTestCase` performs a single test case. The meaning of the |
|---|
| 628 | +-- result is as follows: |
|---|
| 629 | +-- Nothing test case success |
|---|
| 630 | +-- Just (True, msg) test case failure with the given message |
|---|
| 631 | +-- Just (False, msg) test case error with the given message |
|---|
| 632 | + |
|---|
| 633 | +performTestCase :: Assertion -> IO (Maybe (Bool, String)) |
|---|
| 634 | + |
|---|
| 635 | + |
|---|
| 636 | +-- Implementations |
|---|
| 637 | +-- --------------- |
|---|
| 638 | + |
|---|
| 639 | +#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__) |
|---|
| 640 | +data HUnitFailure = HUnitFailure String |
|---|
| 641 | + |
|---|
| 642 | +hunitFailureTc :: TyCon |
|---|
| 643 | +hunitFailureTc = mkTyCon "HUnitFailure" |
|---|
| 644 | +{-# NOINLINE hunitFailureTc #-} |
|---|
| 645 | + |
|---|
| 646 | +instance Typeable HUnitFailure where |
|---|
| 647 | + typeOf _ = mkTyConApp hunitFailureTc [] |
|---|
| 648 | + |
|---|
| 649 | +assertFailure msg = E.throwDyn (HUnitFailure msg) |
|---|
| 650 | + |
|---|
| 651 | +performTestCase action = |
|---|
| 652 | + do r <- E.try action |
|---|
| 653 | + case r of |
|---|
| 654 | + Right () -> return Nothing |
|---|
| 655 | + Left e@(E.DynException dyn) -> |
|---|
| 656 | + case fromDynamic dyn of |
|---|
| 657 | + Just (HUnitFailure msg) -> return $ Just (True, msg) |
|---|
| 658 | + Nothing -> return $ Just (False, show e) |
|---|
| 659 | + Left e -> return $ Just (False, show e) |
|---|
| 660 | +#else |
|---|
| 661 | +hunitPrefix = "HUnit:" |
|---|
| 662 | + |
|---|
| 663 | +nhc98Prefix = "I/O error (user-defined), call to function `userError':\n " |
|---|
| 664 | + |
|---|
| 665 | +assertFailure msg = ioError (userError (hunitPrefix ++ msg)) |
|---|
| 666 | + |
|---|
| 667 | +performTestCase action = do r <- try action |
|---|
| 668 | + case r of Right () -> return Nothing |
|---|
| 669 | + Left e -> return (Just (decode e)) |
|---|
| 670 | + where |
|---|
| 671 | + decode e = let s0 = ioeGetErrorString e |
|---|
| 672 | + (_, s1) = dropPrefix nhc98Prefix s0 |
|---|
| 673 | + in dropPrefix hunitPrefix s1 |
|---|
| 674 | + dropPrefix pref str = if pref `isPrefixOf` str |
|---|
| 675 | + then (True, drop (length pref) str) |
|---|
| 676 | + else (False, str) |
|---|
| 677 | +#endif |
|---|
| 678 | hunk ./Test/HUnit/Terminal.hs 1 |
|---|
| 679 | -> module Test.HUnit.Terminal |
|---|
| 680 | -> ( |
|---|
| 681 | -> terminalAppearance |
|---|
| 682 | -> ) |
|---|
| 683 | -> where |
|---|
| 684 | - |
|---|
| 685 | -> import Data.Char (isPrint) |
|---|
| 686 | - |
|---|
| 687 | - |
|---|
| 688 | -Simplifies the input string by interpreting '\r' and '\b' characters |
|---|
| 689 | -specially so that the result string has the same final (or "terminal", |
|---|
| 690 | -pun intended) appearance as would the input string when written to a |
|---|
| 691 | -terminal that overwrites character positions following carriage |
|---|
| 692 | -returns and backspaces. |
|---|
| 693 | - |
|---|
| 694 | -The helper function `ta` takes an accumulating `ShowS`-style function |
|---|
| 695 | -that holds "committed" lines of text, a (reversed) list of characters |
|---|
| 696 | -on the current line *before* the cursor, a (normal) list of characters |
|---|
| 697 | -on the current line *after* the cursor, and the remaining input. |
|---|
| 698 | - |
|---|
| 699 | -> terminalAppearance :: String -> String |
|---|
| 700 | -> terminalAppearance str = ta id "" "" str |
|---|
| 701 | -> where |
|---|
| 702 | -> ta f bs as ('\n':cs) = ta (\t -> f (reverse bs ++ as ++ '\n' : t)) "" "" cs |
|---|
| 703 | -> ta f bs as ('\r':cs) = ta f "" (reverse bs ++ as) cs |
|---|
| 704 | -> ta f (b:bs) as ('\b':cs) = ta f bs (b:as) cs |
|---|
| 705 | -> ta f "" as ('\b':cs) = error "'\\b' at beginning of line" |
|---|
| 706 | -> ta f bs as (c:cs) | not (isPrint c) = error "invalid nonprinting character" |
|---|
| 707 | -> | null as = ta f (c:bs) "" cs |
|---|
| 708 | -> | otherwise = ta f (c:bs) (tail as) cs |
|---|
| 709 | -> ta f bs as "" = f (reverse bs ++ as) |
|---|
| 710 | +module Test.HUnit.Terminal |
|---|
| 711 | +( |
|---|
| 712 | + terminalAppearance |
|---|
| 713 | +) |
|---|
| 714 | +where |
|---|
| 715 | + |
|---|
| 716 | +import Data.Char (isPrint) |
|---|
| 717 | + |
|---|
| 718 | + |
|---|
| 719 | +-- Simplifies the input string by interpreting '\r' and '\b' characters |
|---|
| 720 | +-- specially so that the result string has the same final (or "terminal", |
|---|
| 721 | +-- pun intended) appearance as would the input string when written to a |
|---|
| 722 | +-- terminal that overwrites character positions following carriage |
|---|
| 723 | +-- returns and backspaces. |
|---|
| 724 | + |
|---|
| 725 | +-- The helper function `ta` takes an accumulating `ShowS`-style function |
|---|
| 726 | +-- that holds "committed" lines of text, a (reversed) list of characters |
|---|
| 727 | +-- on the current line *before* the cursor, a (normal) list of characters |
|---|
| 728 | +-- on the current line *after* the cursor, and the remaining input. |
|---|
| 729 | + |
|---|
| 730 | +terminalAppearance :: String -> String |
|---|
| 731 | +terminalAppearance str = ta id "" "" str |
|---|
| 732 | + where |
|---|
| 733 | + ta f bs as ('\n':cs) = ta (\t -> f (reverse bs ++ as ++ '\n' : t)) "" "" cs |
|---|
| 734 | + ta f bs as ('\r':cs) = ta f "" (reverse bs ++ as) cs |
|---|
| 735 | + ta f (b:bs) as ('\b':cs) = ta f bs (b:as) cs |
|---|
| 736 | + ta f "" as ('\b':cs) = error "'\\b' at beginning of line" |
|---|
| 737 | + ta f bs as (c:cs) | not (isPrint c) = error "invalid nonprinting character" |
|---|
| 738 | + | null as = ta f (c:bs) "" cs |
|---|
| 739 | + | otherwise = ta f (c:bs) (tail as) cs |
|---|
| 740 | + ta f bs as "" = f (reverse bs ++ as) |
|---|
| 741 | hunk ./Test/HUnit/Text.hs 1 |
|---|
| 742 | -HUnitText.lhs -- text-based test controller |
|---|
| 743 | - |
|---|
| 744 | -> module Test.HUnit.Text |
|---|
| 745 | -> ( |
|---|
| 746 | -> PutText(..), |
|---|
| 747 | -> putTextToHandle, putTextToShowS, |
|---|
| 748 | -> runTestText, |
|---|
| 749 | -> showPath, showCounts, |
|---|
| 750 | -> runTestTT |
|---|
| 751 | -> ) |
|---|
| 752 | -> where |
|---|
| 753 | - |
|---|
| 754 | -> import Test.HUnit.Base |
|---|
| 755 | - |
|---|
| 756 | -> import Control.Monad (when) |
|---|
| 757 | -> import System.IO (Handle, stderr, hPutStr, hPutStrLn) |
|---|
| 758 | - |
|---|
| 759 | - |
|---|
| 760 | -As the general text-based test controller (`runTestText`) executes a |
|---|
| 761 | -test, it reports each test case start, error, and failure by |
|---|
| 762 | -constructing a string and passing it to the function embodied in a |
|---|
| 763 | -`PutText`. A report string is known as a "line", although it includes |
|---|
| 764 | -no line terminator; the function in a `PutText` is responsible for |
|---|
| 765 | -terminating lines appropriately. Besides the line, the function |
|---|
| 766 | -receives a flag indicating the intended "persistence" of the line: |
|---|
| 767 | -`True` indicates that the line should be part of the final overall |
|---|
| 768 | -report; `False` indicates that the line merely indicates progress of |
|---|
| 769 | -the test execution. Each progress line shows the current values of |
|---|
| 770 | -the cumulative test execution counts; a final, persistent line shows |
|---|
| 771 | -the final count values. |
|---|
| 772 | - |
|---|
| 773 | -The `PutText` function is also passed, and returns, an arbitrary state |
|---|
| 774 | -value (called `st` here). The initial state value is given in the |
|---|
| 775 | -`PutText`; the final value is returned by `runTestText`. |
|---|
| 776 | - |
|---|
| 777 | -> data PutText st = PutText (String -> Bool -> st -> IO st) st |
|---|
| 778 | - |
|---|
| 779 | - |
|---|
| 780 | -Two reporting schemes are defined here. `putTextToHandle` writes |
|---|
| 781 | -report lines to a given handle. `putTextToShowS` accumulates |
|---|
| 782 | -persistent lines for return as a whole by `runTestText`. |
|---|
| 783 | - |
|---|
| 784 | - |
|---|
| 785 | -`putTextToHandle` writes persistent lines to the given handle, |
|---|
| 786 | -following each by a newline character. In addition, if the given flag |
|---|
| 787 | -is `True`, it writes progress lines to the handle as well. A progress |
|---|
| 788 | -line is written with no line termination, so that it can be |
|---|
| 789 | -overwritten by the next report line. As overwriting involves writing |
|---|
| 790 | -carriage return and blank characters, its proper effect is usually |
|---|
| 791 | -only obtained on terminal devices. |
|---|
| 792 | - |
|---|
| 793 | -> putTextToHandle :: Handle -> Bool -> PutText Int |
|---|
| 794 | -> putTextToHandle handle showProgress = PutText put initCnt |
|---|
| 795 | -> where |
|---|
| 796 | -> initCnt = if showProgress then 0 else -1 |
|---|
| 797 | -> put line pers (-1) = do when pers (hPutStrLn handle line); return (-1) |
|---|
| 798 | -> put line True cnt = do hPutStrLn handle (erase cnt ++ line); return 0 |
|---|
| 799 | -> put line False cnt = do hPutStr handle ('\r' : line); return (length line) |
|---|
| 800 | -> -- The "erasing" strategy with a single '\r' relies on the fact that the |
|---|
| 801 | -> -- lengths of successive summary lines are monotonically nondecreasing. |
|---|
| 802 | -> erase cnt = if cnt == 0 then "" else "\r" ++ replicate cnt ' ' ++ "\r" |
|---|
| 803 | - |
|---|
| 804 | - |
|---|
| 805 | -`putTextToShowS` accumulates persistent lines (dropping progess lines) |
|---|
| 806 | -for return by `runTestText`. The accumulated lines are represented by |
|---|
| 807 | -a `ShowS` (`String -> String`) function whose first argument is the |
|---|
| 808 | -string to be appended to the accumulated report lines. |
|---|
| 809 | - |
|---|
| 810 | -> putTextToShowS :: PutText ShowS |
|---|
| 811 | -> putTextToShowS = PutText put id |
|---|
| 812 | -> where put line pers f = return (if pers then acc f line else f) |
|---|
| 813 | -> acc f line tail = f (line ++ '\n' : tail) |
|---|
| 814 | - |
|---|
| 815 | - |
|---|
| 816 | -`runTestText` executes a test, processing each report line according |
|---|
| 817 | -to the given reporting scheme. The reporting scheme's state is |
|---|
| 818 | -threaded through calls to the reporting scheme's function and finally |
|---|
| 819 | -returned, along with final count values. |
|---|
| 820 | - |
|---|
| 821 | -> runTestText :: PutText st -> Test -> IO (Counts, st) |
|---|
| 822 | -> runTestText (PutText put us) t = do |
|---|
| 823 | -> (counts, us') <- performTest reportStart reportError reportFailure us t |
|---|
| 824 | -> us'' <- put (showCounts counts) True us' |
|---|
| 825 | -> return (counts, us'') |
|---|
| 826 | -> where |
|---|
| 827 | -> reportStart ss us = put (showCounts (counts ss)) False us |
|---|
| 828 | -> reportError = reportProblem "Error:" "Error in: " |
|---|
| 829 | -> reportFailure = reportProblem "Failure:" "Failure in: " |
|---|
| 830 | -> reportProblem p0 p1 msg ss us = put line True us |
|---|
| 831 | -> where line = "### " ++ kind ++ path' ++ '\n' : msg |
|---|
| 832 | -> kind = if null path' then p0 else p1 |
|---|
| 833 | -> path' = showPath (path ss) |
|---|
| 834 | - |
|---|
| 835 | - |
|---|
| 836 | -`showCounts` converts test execution counts to a string. |
|---|
| 837 | - |
|---|
| 838 | -> showCounts :: Counts -> String |
|---|
| 839 | -> showCounts Counts{ cases = cases, tried = tried, |
|---|
| 840 | -> errors = errors, failures = failures } = |
|---|
| 841 | -> "Cases: " ++ show cases ++ " Tried: " ++ show tried ++ |
|---|
| 842 | -> " Errors: " ++ show errors ++ " Failures: " ++ show failures |
|---|
| 843 | - |
|---|
| 844 | - |
|---|
| 845 | -`showPath` converts a test case path to a string, separating adjacent |
|---|
| 846 | -elements by ':'. An element of the path is quoted (as with `show`) |
|---|
| 847 | -when there is potential ambiguity. |
|---|
| 848 | - |
|---|
| 849 | -> showPath :: Path -> String |
|---|
| 850 | -> showPath [] = "" |
|---|
| 851 | -> showPath nodes = foldl1 f (map showNode nodes) |
|---|
| 852 | -> where f b a = a ++ ":" ++ b |
|---|
| 853 | -> showNode (ListItem n) = show n |
|---|
| 854 | -> showNode (Label label) = safe label (show label) |
|---|
| 855 | -> safe s ss = if ':' `elem` s || "\"" ++ s ++ "\"" /= ss then ss else s |
|---|
| 856 | - |
|---|
| 857 | - |
|---|
| 858 | -`runTestTT` provides the "standard" text-based test controller. |
|---|
| 859 | -Reporting is made to standard error, and progress reports are |
|---|
| 860 | -included. For possible programmatic use, the final counts are |
|---|
| 861 | -returned. The "TT" in the name suggests "Text-based reporting to the |
|---|
| 862 | -Terminal". |
|---|
| 863 | - |
|---|
| 864 | -> runTestTT :: Test -> IO Counts |
|---|
| 865 | -> runTestTT t = do (counts, 0) <- runTestText (putTextToHandle stderr True) t |
|---|
| 866 | -> return counts |
|---|
| 867 | +-- text-based test controller |
|---|
| 868 | + |
|---|
| 869 | +module Test.HUnit.Text |
|---|
| 870 | +( |
|---|
| 871 | + PutText(..), |
|---|
| 872 | + putTextToHandle, putTextToShowS, |
|---|
| 873 | + runTestText, |
|---|
| 874 | + showPath, showCounts, |
|---|
| 875 | + runTestTT |
|---|
| 876 | +) |
|---|
| 877 | +where |
|---|
| 878 | + |
|---|
| 879 | +import Test.HUnit.Base |
|---|
| 880 | + |
|---|
| 881 | +import Control.Monad (when) |
|---|
| 882 | +import System.IO (Handle, stderr, hPutStr, hPutStrLn) |
|---|
| 883 | + |
|---|
| 884 | + |
|---|
| 885 | +-- As the general text-based test controller (`runTestText`) executes a |
|---|
| 886 | +-- test, it reports each test case start, error, and failure by |
|---|
| 887 | +-- constructing a string and passing it to the function embodied in a |
|---|
| 888 | +-- `PutText`. A report string is known as a "line", although it includes |
|---|
| 889 | +-- no line terminator; the function in a `PutText` is responsible for |
|---|
| 890 | +-- terminating lines appropriately. Besides the line, the function |
|---|
| 891 | +-- receives a flag indicating the intended "persistence" of the line: |
|---|
| 892 | +-- `True` indicates that the line should be part of the final overall |
|---|
| 893 | +-- report; `False` indicates that the line merely indicates progress of |
|---|
| 894 | +-- the test execution. Each progress line shows the current values of |
|---|
| 895 | +-- the cumulative test execution counts; a final, persistent line shows |
|---|
| 896 | +-- the final count values. |
|---|
| 897 | + |
|---|
| 898 | +-- The `PutText` function is also passed, and returns, an arbitrary state |
|---|
| 899 | +-- value (called `st` here). The initial state value is given in the |
|---|
| 900 | +-- `PutText`; the final value is returned by `runTestText`. |
|---|
| 901 | + |
|---|
| 902 | +data PutText st = PutText (String -> Bool -> st -> IO st) st |
|---|
| 903 | + |
|---|
| 904 | + |
|---|
| 905 | +-- Two reporting schemes are defined here. `putTextToHandle` writes |
|---|
| 906 | +-- report lines to a given handle. `putTextToShowS` accumulates |
|---|
| 907 | +-- persistent lines for return as a whole by `runTestText`. |
|---|
| 908 | + |
|---|
| 909 | + |
|---|
| 910 | +-- `putTextToHandle` writes persistent lines to the given handle, |
|---|
| 911 | +-- following each by a newline character. In addition, if the given flag |
|---|
| 912 | +-- is `True`, it writes progress lines to the handle as well. A progress |
|---|
| 913 | +-- line is written with no line termination, so that it can be |
|---|
| 914 | +-- overwritten by the next report line. As overwriting involves writing |
|---|
| 915 | +-- carriage return and blank characters, its proper effect is usually |
|---|
| 916 | +-- only obtained on terminal devices. |
|---|
| 917 | + |
|---|
| 918 | +putTextToHandle :: Handle -> Bool -> PutText Int |
|---|
| 919 | +putTextToHandle handle showProgress = PutText put initCnt |
|---|
| 920 | + where |
|---|
| 921 | + initCnt = if showProgress then 0 else -1 |
|---|
| 922 | + put line pers (-1) = do when pers (hPutStrLn handle line); return (-1) |
|---|
| 923 | + put line True cnt = do hPutStrLn handle (erase cnt ++ line); return 0 |
|---|
| 924 | + put line False cnt = do hPutStr handle ('\r' : line); return (length line) |
|---|
| 925 | + -- The "erasing" strategy with a single '\r' relies on the fact that the |
|---|
| 926 | + -- lengths of successive summary lines are monotonically nondecreasing. |
|---|
| 927 | + erase cnt = if cnt == 0 then "" else "\r" ++ replicate cnt ' ' ++ "\r" |
|---|
| 928 | + |
|---|
| 929 | + |
|---|
| 930 | +-- `putTextToShowS` accumulates persistent lines (dropping progess lines) |
|---|
| 931 | +-- for return by `runTestText`. The accumulated lines are represented by |
|---|
| 932 | +-- a `ShowS` (`String -> String`) function whose first argument is the |
|---|
| 933 | +-- string to be appended to the accumulated report lines. |
|---|
| 934 | + |
|---|
| 935 | +putTextToShowS :: PutText ShowS |
|---|
| 936 | +putTextToShowS = PutText put id |
|---|
| 937 | + where put line pers f = return (if pers then acc f line else f) |
|---|
| 938 | + acc f line tail = f (line ++ '\n' : tail) |
|---|
| 939 | + |
|---|
| 940 | + |
|---|
| 941 | +-- `runTestText` executes a test, processing each report line according |
|---|
| 942 | +-- to the given reporting scheme. The reporting scheme's state is |
|---|
| 943 | +-- threaded through calls to the reporting scheme's function and finally |
|---|
| 944 | +-- returned, along with final count values. |
|---|
| 945 | + |
|---|
| 946 | +runTestText :: PutText st -> Test -> IO (Counts, st) |
|---|
| 947 | +runTestText (PutText put us) t = do |
|---|
| 948 | + (counts, us') <- performTest reportStart reportError reportFailure us t |
|---|
| 949 | + us'' <- put (showCounts counts) True us' |
|---|
| 950 | + return (counts, us'') |
|---|
| 951 | + where |
|---|
| 952 | + reportStart ss us = put (showCounts (counts ss)) False us |
|---|
| 953 | + reportError = reportProblem "Error:" "Error in: " |
|---|
| 954 | + reportFailure = reportProblem "Failure:" "Failure in: " |
|---|
| 955 | + reportProblem p0 p1 msg ss us = put line True us |
|---|
| 956 | + where line = "### " ++ kind ++ path' ++ '\n' : msg |
|---|
| 957 | + kind = if null path' then p0 else p1 |
|---|
| 958 | + path' = showPath (path ss) |
|---|
| 959 | + |
|---|
| 960 | + |
|---|
| 961 | +-- `showCounts` converts test execution counts to a string. |
|---|
| 962 | + |
|---|
| 963 | +showCounts :: Counts -> String |
|---|
| 964 | +showCounts Counts{ cases = cases, tried = tried, |
|---|
| 965 | + errors = errors, failures = failures } = |
|---|
| 966 | + "Cases: " ++ show cases ++ " Tried: " ++ show tried ++ |
|---|
| 967 | + " Errors: " ++ show errors ++ " Failures: " ++ show failures |
|---|
| 968 | + |
|---|
| 969 | + |
|---|
| 970 | +-- `showPath` converts a test case path to a string, separating adjacent |
|---|
| 971 | +-- elements by ':'. An element of the path is quoted (as with `show`) |
|---|
| 972 | +-- when there is potential ambiguity. |
|---|
| 973 | + |
|---|
| 974 | +showPath :: Path -> String |
|---|
| 975 | +showPath [] = "" |
|---|
| 976 | +showPath nodes = foldl1 f (map showNode nodes) |
|---|
| 977 | + where f b a = a ++ ":" ++ b |
|---|
| 978 | + showNode (ListItem n) = show n |
|---|
| 979 | + showNode (Label label) = safe label (show label) |
|---|
| 980 | + safe s ss = if ':' `elem` s || "\"" ++ s ++ "\"" /= ss then ss else s |
|---|
| 981 | + |
|---|
| 982 | + |
|---|
| 983 | +-- `runTestTT` provides the "standard" text-based test controller. |
|---|
| 984 | +-- Reporting is made to standard error, and progress reports are |
|---|
| 985 | +-- included. For possible programmatic use, the final counts are |
|---|
| 986 | +-- returned. The "TT" in the name suggests "Text-based reporting to the |
|---|
| 987 | +-- Terminal". |
|---|
| 988 | + |
|---|
| 989 | +runTestTT :: Test -> IO Counts |
|---|
| 990 | +runTestTT t = do (counts, 0) <- runTestText (putTextToHandle stderr True) t |
|---|
| 991 | + return counts |
|---|
| 992 | } |
|---|
| 993 | |
|---|
| 994 | [converted existing source comments to Haddock comments and filled in rest of documentation |
|---|
| 995 | Leif Frenzel <leiffrenzel@googlemail.com>**20070823192207] { |
|---|
| 996 | hunk ./Test/HUnit.hs 1 |
|---|
| 997 | --- interface module for HUnit |
|---|
| 998 | +-- | The HUnit library. To write HUnit tests it is sufficient to import this |
|---|
| 999 | +-- module, which simply re-exports all modules of the library. |
|---|
| 1000 | hunk ./Test/HUnit/Base.hs 1 |
|---|
| 1001 | --- basic definitions |
|---|
| 1002 | +-- | Basic definitions for the HUnit library. |
|---|
| 1003 | +-- |
|---|
| 1004 | +-- This module contains what you need to create assertions and test cases and |
|---|
| 1005 | +-- combine them into test suites. It also provides infrastructure for |
|---|
| 1006 | +-- implementing test controllers (which are used to execute tests). For an |
|---|
| 1007 | +-- exemplary implementation of a test controller, see "Test.HUnit.Text". |
|---|
| 1008 | hunk ./Test/HUnit/Base.hs 10 |
|---|
| 1009 | - {- from Test.HUnit.Lang: -} Assertion, assertFailure, |
|---|
| 1010 | - assertString, assertBool, assertEqual, |
|---|
| 1011 | + -- ** Declaring tests |
|---|
| 1012 | + Test(..), |
|---|
| 1013 | + (~=?), (~?=), (~:), (~?), |
|---|
| 1014 | + -- ** Making assertions |
|---|
| 1015 | + assertBool, assertEqual, assertString, |
|---|
| 1016 | + {- from Test.HUnit.Lang: -} |
|---|
| 1017 | + assertFailure, Assertion, |
|---|
| 1018 | + (@=?), (@?=), (@?), |
|---|
| 1019 | + -- ** Extending the assertion functionality |
|---|
| 1020 | hunk ./Test/HUnit/Base.hs 21 |
|---|
| 1021 | - (@?), (@=?), (@?=), |
|---|
| 1022 | - Test(..), Node(..), Path, |
|---|
| 1023 | + Node(..), Path, |
|---|
| 1024 | hunk ./Test/HUnit/Base.hs 23 |
|---|
| 1025 | - Testable(..), |
|---|
| 1026 | - (~?), (~=?), (~?=), (~:), |
|---|
| 1027 | + Testable(..), |
|---|
| 1028 | + -- ** Test execution |
|---|
| 1029 | + -- $testExecutionNote |
|---|
| 1030 | hunk ./Test/HUnit/Base.hs 45 |
|---|
| 1031 | -assertBool :: String -> Bool -> Assertion |
|---|
| 1032 | +-- | asserts that the specified condition holds. |
|---|
| 1033 | +assertBool :: String -- ^ a message that is displayed if the assertion fails |
|---|
| 1034 | + -> Bool -- ^ the condition that is asserted to hold |
|---|
| 1035 | + -> Assertion |
|---|
| 1036 | hunk ./Test/HUnit/Base.hs 51 |
|---|
| 1037 | -assertString :: String -> Assertion |
|---|
| 1038 | +-- | signals an assertion failure if a non-empty message is passed. |
|---|
| 1039 | +assertString :: String -- ^ a message that is displayed with the assertion failure |
|---|
| 1040 | + -> Assertion |
|---|
| 1041 | hunk ./Test/HUnit/Base.hs 56 |
|---|
| 1042 | -assertEqual :: (Eq a, Show a) => String -> a -> a -> Assertion |
|---|
| 1043 | +-- | asserts that the specified actual value is equal to the expected value. |
|---|
| 1044 | +assertEqual :: (Eq a, Show a) => String -- ^ a message that is displayed if the assertion fails |
|---|
| 1045 | + -> a -- ^ the expected value |
|---|
| 1046 | + -> a -- ^ the actual value |
|---|
| 1047 | + -> Assertion |
|---|
| 1048 | hunk ./Test/HUnit/Base.hs 115 |
|---|
| 1049 | -(@?) :: (AssertionPredicable t) => t -> String -> Assertion |
|---|
| 1050 | +-- | asserts that the condition obtained from the specified |
|---|
| 1051 | +-- 'AssertionPredicable' holds. |
|---|
| 1052 | +(@?) :: (AssertionPredicable t) => t -- ^ a value of which the asserted condition is predicated |
|---|
| 1053 | + -> String -- ^ a message that is displayed if the assertion fails |
|---|
| 1054 | + -> Assertion |
|---|
| 1055 | hunk ./Test/HUnit/Base.hs 121 |
|---|
| 1056 | - |
|---|
| 1057 | -(@=?) :: (Eq a, Show a) => a -> a -> Assertion |
|---|
| 1058 | -expected @=? actual = assertEqual "" expected actual |
|---|
| 1059 | - |
|---|
| 1060 | -(@?=) :: (Eq a, Show a) => a -> a -> Assertion |
|---|
| 1061 | + |
|---|
| 1062 | +-- | asserts that the specified actual value is equal to the expected value |
|---|
| 1063 | +-- (with the expected value on the left-hand side). |
|---|
| 1064 | +(@=?) :: (Eq a, Show a) => a -- ^ the expected value |
|---|
| 1065 | + -> a -- ^ the actual value |
|---|
| 1066 | + -> Assertion |
|---|
| 1067 | +expected @=? actual = assertEqual "" expected actual |
|---|
| 1068 | + |
|---|
| 1069 | +-- | asserts that the specified actual value is equal to the expected value |
|---|
| 1070 | +-- (with the actual value on the left-hand side). |
|---|
| 1071 | +(@?=) :: (Eq a, Show a) => a -- ^ the actual value |
|---|
| 1072 | + -> a -- ^ the expected value |
|---|
| 1073 | + -> Assertion |
|---|
| 1074 | hunk ./Test/HUnit/Base.hs 151 |
|---|
| 1075 | +-- | recursively counts all test cases contained in the specified test. |
|---|
| 1076 | hunk ./Test/HUnit/Base.hs 194 |
|---|
| 1077 | -(~?) :: (AssertionPredicable t) => t -> String -> Test |
|---|
| 1078 | +-- | creates a test case resulting from asserting the condition obtained |
|---|
| 1079 | +-- from the specified 'AssertionPredicable'. |
|---|
| 1080 | +(~?) :: (AssertionPredicable t) => t -- ^ a value of which the asserted condition is predicated |
|---|
| 1081 | + -> String -- ^ a message that is displayed on test failure |
|---|
| 1082 | + -> Test |
|---|
| 1083 | hunk ./Test/HUnit/Base.hs 201 |
|---|
| 1084 | -(~=?) :: (Eq a, Show a) => a -> a -> Test |
|---|
| 1085 | +-- | shorthand for a test case that asserts equality (with the expected |
|---|
| 1086 | +-- value on the left-hand side, and the actual value on the right-hand |
|---|
| 1087 | +-- side). |
|---|
| 1088 | +(~=?) :: (Eq a, Show a) => a -- ^ the expected value |
|---|
| 1089 | + -> a -- ^ the actual value |
|---|
| 1090 | + -> Test |
|---|
| 1091 | hunk ./Test/HUnit/Base.hs 209 |
|---|
| 1092 | -(~?=) :: (Eq a, Show a) => a -> a -> Test |
|---|
| 1093 | +-- | shorthand for a test case that asserts equality (with the actual |
|---|
| 1094 | +-- value on the left-hand side, and the expected value on the right-hand |
|---|
| 1095 | +-- side). |
|---|
| 1096 | +(~?=) :: (Eq a, Show a) => a -- ^ the actual value |
|---|
| 1097 | + -> a -- ^ the expected value |
|---|
| 1098 | + -> Test |
|---|
| 1099 | hunk ./Test/HUnit/Base.hs 217 |
|---|
| 1100 | +-- | creates a test from the specified 'Testable', with the specified |
|---|
| 1101 | +-- label attached to it. |
|---|
| 1102 | hunk ./Test/HUnit/Base.hs 226 |
|---|
| 1103 | + |
|---|
| 1104 | +-- $testExecutionNote |
|---|
| 1105 | +-- Note: the rest of the functionality in this module is intended for |
|---|
| 1106 | +-- implementors of test controllers. If you just want to run your tests cases, |
|---|
| 1107 | +-- simply use a test controller, such as the text-based controller in |
|---|
| 1108 | +-- "Test.HUnit.Text". |
|---|
| 1109 | + |
|---|
| 1110 | hunk ./Test/HUnit/Base.hs 239 |
|---|
| 1111 | - |
|---|
| 1112 | + |
|---|
| 1113 | +-- | report generator for reporting the start of a test run. |
|---|
| 1114 | hunk ./Test/HUnit/Base.hs 242 |
|---|
| 1115 | - |
|---|
| 1116 | + |
|---|
| 1117 | +-- | report generator for reporting problems that have occurred during |
|---|
| 1118 | +-- a test run. Problems may be errors or assertion failures. |
|---|
| 1119 | hunk ./Test/HUnit/Base.hs 247 |
|---|
| 1120 | - |
|---|
| 1121 | --- Note that the counts in a start report do not include the test case |
|---|
| 1122 | --- being started, whereas the counts in a problem report do include the |
|---|
| 1123 | --- test case just finished. The principle is that the counts are sampled |
|---|
| 1124 | --- only between test case executions. As a result, the number of test |
|---|
| 1125 | --- case successes always equals the difference of test cases tried and |
|---|
| 1126 | --- the sum of test case errors and failures. |
|---|
| 1127 | - |
|---|
| 1128 | - |
|---|
| 1129 | -performTest :: ReportStart us -> ReportProblem us -> ReportProblem us |
|---|
| 1130 | - -> us -> Test -> IO (Counts, us) |
|---|
| 1131 | +-- | performs a test run with the specified report generators. |
|---|
| 1132 | +-- |
|---|
| 1133 | +-- Note that the counts in a start report do not include the test case |
|---|
| 1134 | +-- being started, whereas the counts in a problem report do include the |
|---|
| 1135 | +-- test case just finished. The principle is that the counts are sampled |
|---|
| 1136 | +-- only between test case executions. As a result, the number of test |
|---|
| 1137 | +-- case successes always equals the difference of test cases tried and |
|---|
| 1138 | +-- the sum of test case errors and failures. |
|---|
| 1139 | +performTest :: ReportStart us -- ^ report generator for the test run start |
|---|
| 1140 | + -> ReportProblem us -- ^ report generator for errors during the test run |
|---|
| 1141 | + -> ReportProblem us -- ^ report generator for assertion failures during the test run |
|---|
| 1142 | + -> us |
|---|
| 1143 | + -> Test -- ^ the test to be executed |
|---|
| 1144 | + -> IO (Counts, us) |
|---|
| 1145 | hunk ./Test/HUnit/Lang.hs 1 |
|---|
| 1146 | --- HUnit language support. |
|---|
| 1147 | +-- | HUnit language support. |
|---|
| 1148 | hunk ./Test/HUnit/Lang.hs 33 |
|---|
| 1149 | --- An assertion is an `IO` computation with trivial result. |
|---|
| 1150 | +-- | An assertion is an 'IO' computation with trivial result. An assertion or |
|---|
| 1151 | +-- a sequence of assertions makes up a test case. |
|---|
| 1152 | hunk ./Test/HUnit/Lang.hs 38 |
|---|
| 1153 | --- `assertFailure` signals an assertion failure with a given message. |
|---|
| 1154 | +-- | signals an assertion failure with a given message. |
|---|
| 1155 | hunk ./Test/HUnit/Lang.hs 40 |
|---|
| 1156 | -assertFailure :: String -> Assertion |
|---|
| 1157 | +assertFailure :: String -- ^ a message that is displayed with the assertion failure |
|---|
| 1158 | + -> Assertion |
|---|
| 1159 | hunk ./Test/HUnit/Lang.hs 43 |
|---|
| 1160 | --- `performTestCase` performs a single test case. The meaning of the |
|---|
| 1161 | --- result is as follows: |
|---|
| 1162 | --- Nothing test case success |
|---|
| 1163 | --- Just (True, msg) test case failure with the given message |
|---|
| 1164 | --- Just (False, msg) test case error with the given message |
|---|
| 1165 | +-- | performs a single test case. The meaning of the result is as follows: |
|---|
| 1166 | +-- |
|---|
| 1167 | +-- [@Nothing@] test case success |
|---|
| 1168 | +-- |
|---|
| 1169 | +-- [@Just (True, msg)@] test case failure with the given message |
|---|
| 1170 | +-- |
|---|
| 1171 | +-- [@Just (False, msg)@] test case error with the given message |
|---|
| 1172 | hunk ./Test/HUnit/Lang.hs 51 |
|---|
| 1173 | -performTestCase :: Assertion -> IO (Maybe (Bool, String)) |
|---|
| 1174 | +performTestCase :: Assertion -- ^ an assertion to be made during the test case run |
|---|
| 1175 | + -> IO (Maybe (Bool, String)) |
|---|
| 1176 | hunk ./Test/HUnit/Terminal.hs 10 |
|---|
| 1177 | --- Simplifies the input string by interpreting '\r' and '\b' characters |
|---|
| 1178 | --- specially so that the result string has the same final (or "terminal", |
|---|
| 1179 | --- pun intended) appearance as would the input string when written to a |
|---|
| 1180 | --- terminal that overwrites character positions following carriage |
|---|
| 1181 | --- returns and backspaces. |
|---|
| 1182 | +-- | simplifies the input string by interpreting \'\r\' and \'\b\' characters |
|---|
| 1183 | +-- specially so that the result string has the same final (or \"terminal\", |
|---|
| 1184 | +-- pun intended) appearance as would the input string when written to a |
|---|
| 1185 | +-- terminal that overwrites character positions following carriage |
|---|
| 1186 | +-- returns and backspaces. |
|---|
| 1187 | hunk ./Test/HUnit/Terminal.hs 16 |
|---|
| 1188 | --- The helper function `ta` takes an accumulating `ShowS`-style function |
|---|
| 1189 | --- that holds "committed" lines of text, a (reversed) list of characters |
|---|
| 1190 | --- on the current line *before* the cursor, a (normal) list of characters |
|---|
| 1191 | --- on the current line *after* the cursor, and the remaining input. |
|---|
| 1192 | hunk ./Test/HUnit/Terminal.hs 20 |
|---|
| 1193 | + -- The helper function `ta` takes an accumulating `ShowS`-style function |
|---|
| 1194 | + -- that holds "committed" lines of text, a (reversed) list of characters |
|---|
| 1195 | + -- on the current line *before* the cursor, a (normal) list of characters |
|---|
| 1196 | + -- on the current line *after* the cursor, and the remaining input. |
|---|
| 1197 | hunk ./Test/HUnit/Text.hs 1 |
|---|
| 1198 | --- text-based test controller |
|---|
| 1199 | +-- | Text-based test controller for running HUnit tests and reporting |
|---|
| 1200 | +-- results as text, usually to a terminal. |
|---|
| 1201 | hunk ./Test/HUnit/Text.hs 20 |
|---|
| 1202 | --- As the general text-based test controller (`runTestText`) executes a |
|---|
| 1203 | --- test, it reports each test case start, error, and failure by |
|---|
| 1204 | --- constructing a string and passing it to the function embodied in a |
|---|
| 1205 | --- `PutText`. A report string is known as a "line", although it includes |
|---|
| 1206 | --- no line terminator; the function in a `PutText` is responsible for |
|---|
| 1207 | --- terminating lines appropriately. Besides the line, the function |
|---|
| 1208 | --- receives a flag indicating the intended "persistence" of the line: |
|---|
| 1209 | --- `True` indicates that the line should be part of the final overall |
|---|
| 1210 | --- report; `False` indicates that the line merely indicates progress of |
|---|
| 1211 | --- the test execution. Each progress line shows the current values of |
|---|
| 1212 | --- the cumulative test execution counts; a final, persistent line shows |
|---|
| 1213 | --- the final count values. |
|---|
| 1214 | - |
|---|
| 1215 | --- The `PutText` function is also passed, and returns, an arbitrary state |
|---|
| 1216 | --- value (called `st` here). The initial state value is given in the |
|---|
| 1217 | --- `PutText`; the final value is returned by `runTestText`. |
|---|
| 1218 | +-- | As the general text-based test controller ('runTestText') executes a |
|---|
| 1219 | +-- test, it reports each test case start, error, and failure by |
|---|
| 1220 | +-- constructing a string and passing it to the function embodied in a |
|---|
| 1221 | +-- 'PutText'. A report string is known as a \"line\", although it includes |
|---|
| 1222 | +-- no line terminator; the function in a 'PutText' is responsible for |
|---|
| 1223 | +-- terminating lines appropriately. Besides the line, the function |
|---|
| 1224 | +-- receives a flag indicating the intended \"persistence\" of the line: |
|---|
| 1225 | +-- 'True' indicates that the line should be part of the final overall |
|---|
| 1226 | +-- report; 'False' indicates that the line merely indicates progress of |
|---|
| 1227 | +-- the test execution. Each progress line shows the current values of |
|---|
| 1228 | +-- the cumulative test execution counts; a final, persistent line shows |
|---|
| 1229 | +-- the final count values. |
|---|
| 1230 | +-- |
|---|
| 1231 | +-- The 'PutText' function is also passed, and returns, an arbitrary state |
|---|
| 1232 | +-- value (called 'st' here). The initial state value is given in the |
|---|
| 1233 | +-- 'PutText'; the final value is returned by 'runTestText'. |
|---|
| 1234 | hunk ./Test/HUnit/Text.hs 45 |
|---|
| 1235 | --- `putTextToHandle` writes persistent lines to the given handle, |
|---|
| 1236 | --- following each by a newline character. In addition, if the given flag |
|---|
| 1237 | --- is `True`, it writes progress lines to the handle as well. A progress |
|---|
| 1238 | --- line is written with no line termination, so that it can be |
|---|
| 1239 | --- overwritten by the next report line. As overwriting involves writing |
|---|
| 1240 | --- carriage return and blank characters, its proper effect is usually |
|---|
| 1241 | --- only obtained on terminal devices. |
|---|
| 1242 | +-- | writes persistent lines to the given handle, following each by a newline |
|---|
| 1243 | +-- character. In addition, if the given flag is 'True', it writes progress |
|---|
| 1244 | +-- lines to the handle as well. A progress line is written with no line |
|---|
| 1245 | +-- termination, so that it can be overwritten by the next report line. |
|---|
| 1246 | +-- As overwriting involves writing carriage return and blank characters, its |
|---|
| 1247 | +-- proper effect is usually only obtained on terminal devices. |
|---|
| 1248 | hunk ./Test/HUnit/Text.hs 64 |
|---|
| 1249 | --- `putTextToShowS` accumulates persistent lines (dropping progess lines) |
|---|
| 1250 | --- for return by `runTestText`. The accumulated lines are represented by |
|---|
| 1251 | --- a `ShowS` (`String -> String`) function whose first argument is the |
|---|
| 1252 | --- string to be appended to the accumulated report lines. |
|---|
| 1253 | +-- | accumulates persistent lines (dropping progess lines) for return by |
|---|
| 1254 | +-- 'runTestText'. The accumulated lines are represented by a |
|---|
| 1255 | +-- @'ShowS' ('String' -> 'String')@ function whose first argument is the |
|---|
| 1256 | +-- string to be appended to the accumulated report lines. |
|---|
| 1257 | hunk ./Test/HUnit/Text.hs 75 |
|---|
| 1258 | --- `runTestText` executes a test, processing each report line according |
|---|
| 1259 | --- to the given reporting scheme. The reporting scheme's state is |
|---|
| 1260 | --- threaded through calls to the reporting scheme's function and finally |
|---|
| 1261 | --- returned, along with final count values. |
|---|
| 1262 | +-- | executes a test, processing each report line according to the given |
|---|
| 1263 | +-- reporting scheme. The reporting scheme's state is threaded through calls |
|---|
| 1264 | +-- to the reporting scheme's function and finally returned, along with final |
|---|
| 1265 | +-- count values. |
|---|
| 1266 | hunk ./Test/HUnit/Text.hs 95 |
|---|
| 1267 | --- `showCounts` converts test execution counts to a string. |
|---|
| 1268 | +-- | converts test execution counts to a string. |
|---|
| 1269 | hunk ./Test/HUnit/Text.hs 104 |
|---|
| 1270 | --- `showPath` converts a test case path to a string, separating adjacent |
|---|
| 1271 | --- elements by ':'. An element of the path is quoted (as with `show`) |
|---|
| 1272 | --- when there is potential ambiguity. |
|---|
| 1273 | +-- | converts a test case path to a string, separating adjacent elements by |
|---|
| 1274 | +-- the colon (\':\'). An element of the path is quoted (as with 'show') when |
|---|
| 1275 | +-- there is potential ambiguity. |
|---|
| 1276 | hunk ./Test/HUnit/Text.hs 117 |
|---|
| 1277 | --- `runTestTT` provides the "standard" text-based test controller. |
|---|
| 1278 | --- Reporting is made to standard error, and progress reports are |
|---|
| 1279 | --- included. For possible programmatic use, the final counts are |
|---|
| 1280 | --- returned. The "TT" in the name suggests "Text-based reporting to the |
|---|
| 1281 | --- Terminal". |
|---|
| 1282 | +-- | provides the \"standard\" text-based test controller. Reporting is made to |
|---|
| 1283 | +-- standard error, and progress reports are included. For possible |
|---|
| 1284 | +-- programmatic use, the final counts are returned. |
|---|
| 1285 | +-- |
|---|
| 1286 | +-- The \"TT\" in the name suggests \"Text-based reporting to the Terminal\". |
|---|
| 1287 | } |
|---|
| 1288 | |
|---|
| 1289 | Context: |
|---|
| 1290 | |
|---|
| 1291 | [--configure-option and --ghc-option are now provided by Cabal |
|---|
| 1292 | Ross Paterson <ross@soi.city.ac.uk>**20070604115936] |
|---|
| 1293 | [FIX #476 (HUnit treats failures as errors) |
|---|
| 1294 | Simon Marlow <simonmar@microsoft.com>**20070530100832 |
|---|
| 1295 | Patch submitted by stefanheimann via Trac |
|---|
| 1296 | ] |
|---|
| 1297 | [old nhc98 Makefiles now obsolete |
|---|
| 1298 | Malcolm.Wallace@cs.york.ac.uk**20070525133446] |
|---|
| 1299 | [remove Makefile.inc (only affects nhc98) |
|---|
| 1300 | Malcolm.Wallace@cs.york.ac.uk**20070320120854] |
|---|
| 1301 | [Remove Makefile and package.conf.in (used in the old GHC build system) |
|---|
| 1302 | Ian Lynagh <igloo@earth.li>**20070524145605] |
|---|
| 1303 | [TAG GHC 6.6.1 release |
|---|
| 1304 | Ian Lynagh <igloo@earth.li>**20070428195851] |
|---|
| 1305 | Patch bundle hash: |
|---|
| 1306 | 4dd2e2672e0214de4a0a84e1698fb1e17031732b |
|---|