codesnippets:testingconventions
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| codesnippets:testingconventions [2022/04/06 13:08] – f2b216 | codesnippets:testingconventions [2025/10/08 00:48] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Testing conventions ====== | ====== Testing conventions ====== | ||
| - | ~~DISCUSSION~~ | ||
| ===== Setup with stack ===== | ===== Setup with stack ===== | ||
| Line 108: | Line 107: | ||
| === HUnit test === | === HUnit test === | ||
| + | |||
| + | * Function: HUnit.testCase | ||
| + | - parameter :: [Char]/ | ||
| + | * e.g. "Law A #u1", "Law A #u2", ... "Law A #u33" | ||
| + | - parameter :: Assertation: | ||
| + | * e.g. 3 * 2 @?= 2 * 3 | ||
| * example '' | * example '' | ||
| Line 118: | Line 123: | ||
| [ | [ | ||
| -- ..., | -- ..., | ||
| - | HU.testCase "#1" (A.f4 3 HU.@?= (A.f5 3 * A.f5 3)), | + | HU.testCase "#u1" (A.f4 3 HU.@?= (A.f5 3 * A.f5 3)), |
| - | HU.testCase "#2" (A.f4 4 HU.@?= (A.f5 4 * A.f5 4)) -- ... | + | HU.testCase "#u2" (A.f4 4 HU.@?= (A.f5 4 * A.f5 4)) -- ... |
| ] | ] | ||
| Line 126: | Line 131: | ||
| === QuickCheck test === | === QuickCheck test === | ||
| + | |||
| + | * Function: HUnit.testProperty | ||
| + | - parameter :: [Char]/ | ||
| + | * e.g. "Type 1 #p1", "Type 1 #p2", ... "Type 1 #p42" | ||
| + | - parameter :: a: Two functions from a lambda parameter left and rigth from " | ||
| + | * e.g. 3 * 2 @?= 2 * 3 | ||
| * example '' | * example '' | ||
| Line 136: | Line 147: | ||
| [ | [ | ||
| -- ..., | -- ..., | ||
| - | QC.testProperty "#1" (\nj -> A.f3 nj QC.==> (A.f4 nj == (A.f5 nj * A.f5 nj)) ), | + | QC.testProperty "#p1" (\nj -> A.f3 nj QC.==> (A.f4 nj == (A.f5 nj * A.f5 nj)) ), |
| - | QC.testProperty "#1" (\nj -> not A.f3 nj QC.==> (A.f4 nj == -1 ) -- ... | + | QC.testProperty "#p2" (\nj -> not A.f3 nj QC.==> (A.f4 nj == -1 ) -- ... |
| ] | ] | ||
| Line 149: | Line 160: | ||
| === Control of test samples === | === Control of test samples === | ||
| - | QuickCheck tests with random samples, and the frequency distribution of the ramdom samples can be controlled by the class Arbitrary. | + | QuickCheck tests with test data of random samples, and the frequency distribution of the ramdom samples can be controlled by the class Arbitrary. |
| * Example: Let suppose there is a type that is to huge to test all possible combinations. | * Example: Let suppose there is a type that is to huge to test all possible combinations. | ||
| - | * example with type declaration: | + | * type declaration |
| data TooHugeToTestAll = ToHuge { ra :: Int, rb :: Int, rc :: Int, rd :: Int } | data TooHugeToTestAll = ToHuge { ra :: Int, rb :: Int, rc :: Int, rd :: Int } | ||
| deriving (Show) | deriving (Show) | ||
| </ | </ | ||
| - | * And you want to have more tests in a certain range of values plus some in the vast possibilities. | + | * If you want to have more tests in a certain range of values plus some in the vast possibilities |
| - | * Then you create an orphan instance of Arbitrary. | + | |
| - | * example with class instance: < | + | * class instance |
| instance QC.Arbitrary TooHugeToTestAll where | instance QC.Arbitrary TooHugeToTestAll where | ||
| arbitrary = ToHuge <$> f <*> f <*> f <*> f | arbitrary = ToHuge <$> f <*> f <*> f <*> f | ||
| Line 178: | Line 188: | ||
| niMin :: Int | niMin :: Int | ||
| niMin = - niMax | niMin = - niMax | ||
| + | </ | ||
| + | |||
| + | === Control of test samples for known types === | ||
| + | |||
| + | Background: The following instances already exist with a standard distribution for sample data. | ||
| + | |||
| + | * Arbitrary Bool | ||
| + | * Arbitrary Char | ||
| + | * Arbitrary Double | ||
| + | * Arbitrary Float | ||
| + | * Arbitrary Int | ||
| + | * Arbitrary Int8 | ||
| + | * Arbitrary Int16 | ||
| + | * Arbitrary Int32 | ||
| + | * Arbitrary Int64 | ||
| + | * Arbitrary Integer | ||
| + | * Arbitrary Ordering | ||
| + | * Arbitrary Word | ||
| + | * Arbitrary Word8 | ||
| + | * Arbitrary Word16 | ||
| + | * Arbitrary Word32 | ||
| + | * Arbitrary Word64 | ||
| + | * Arbitrary () | ||
| + | * and much more ... see all of them here [[https:// | ||
| + | |||
| + | Problem: So, how to control them differently? | ||
| + | |||
| + | Solution: By declaration of a new type (by ' | ||
| + | |||
| + | * example: < | ||
| + | newtype Char' = Char' Char | ||
| + | deriving Show | ||
| + | |||
| + | fromChar' | ||
| + | fromChar' | ||
| + | |||
| + | instance QC.Arbitrary Char' where | ||
| + | arbitrary = | ||
| + | do | ||
| + | genChar <- QC.frequency | ||
| + | [ | ||
| + | (1, QC.elements [' | ||
| + | (1, QC.elements [' | ||
| + | (1, QC.elements [' | ||
| + | (5, QC.chooseAny ) | ||
| + | ] | ||
| + | return (Char' genChar) | ||
| + | |||
| + | -- ... | ||
| + | |||
| + | QC.testProperty "Char #p1" (\ch' -> (fromChar' | ||
| + | </ | ||
| + | |||
| + | * example, with a more generalised approach: < | ||
| + | {-# LANGUAGE FlexibleInstances #-} | ||
| + | |||
| + | -- ... | ||
| + | |||
| + | newtype T' a = T' a | ||
| + | deriving Show | ||
| + | |||
| + | fromT' :: T' a -> a | ||
| + | fromT' (T' x) = x | ||
| + | |||
| + | instance QC.Arbitrary (T' Char) where | ||
| + | arbitrary = | ||
| + | do | ||
| + | genChar <- QC.frequency | ||
| + | [ | ||
| + | (1, QC.elements [' | ||
| + | (1, QC.elements [' | ||
| + | (1, QC.elements [' | ||
| + | (5, QC.chooseAny ) | ||
| + | ] | ||
| + | return (T' genChar) | ||
| + | |||
| + | -- ... | ||
| + | |||
| + | QC.testProperty "Char #p1" (\cd' -> (fromT' | ||
| </ | </ | ||
| Line 208: | Line 297: | ||
| * the complete set of possible test values/data is used in unit tests, | * the complete set of possible test values/data is used in unit tests, | ||
| * or values for all possible equivalence classes are used | * or values for all possible equivalence classes are used | ||
| - | * or ramdom | + | * or random |
| * independence: | * independence: | ||
| - | * test method is independent | + | * test methods are independent functions |
| - | * or dependent | + | * unless they depend |
| - | * boundaries: | + | * edge cases: |
| - | * corner | + | * edge cases are tested by unit tests (HUnit) |
| * conform doc.: | * conform doc.: | ||
| * all tests are conform to documentation, | * all tests are conform to documentation, | ||
| - | After checking the abovementioned | + | After checking the above mentioned |
| * < | * < | ||
| - | {- | + | {- * validated: ✅ |
| - | | + | |
| * completeness: | * completeness: | ||
| * independence: | * independence: | ||
| - | * boundaries | + | * edge cases : ✅ |
| * conform doc.: ✅ -} | * conform doc.: ✅ -} | ||
| tgUnitf1 :: T.TestTree | tgUnitf1 :: T.TestTree | ||
| Line 257: | Line 345: | ||
| After checking the abovementioned criteria, the result is documented as source code comment: | After checking the abovementioned criteria, the result is documented as source code comment: | ||
| * < | * < | ||
| - | {- | + | {- * validated: ✅ |
| - | | + | |
| * documented: ✅ | * documented: ✅ | ||
| * laws : ✅ | * laws : ✅ | ||
| Line 292: | Line 379: | ||
| Description : provides a class for ... | Description : provides a class for ... | ||
| Copyright | Copyright | ||
| - | License | + | License |
| Maintainer | Maintainer | ||
| Stability | Stability | ||
| Line 305: | Line 392: | ||
| * example: < | * example: < | ||
| - | {- module A | + | {- * validated: ✅ |
| - | | + | |
| * documented: ✅ | * documented: ✅ | ||
| * completeness: | * completeness: | ||
| Line 321: | Line 407: | ||
| </ | </ | ||
| + | |||
| + | ===== ✎ ===== | ||
| + | ~~DISCUSSION~~ | ||
codesnippets/testingconventions.1649243305.txt.gz · Last modified: (external edit)
