180 likes | 308 Views
This document provides an overview of program testing techniques covered in CPSC 449, Week 3, at the University of Calgary. It discusses various types of tests, emphasizing the importance of black box and white box testing methodologies. The guide explores the art of creating comprehensive test cases, the necessity of defining properties for functions, and presents examples such as the `maxThree` function. Additionally, it introduces QuickCheck for property testing, showcasing effective techniques for validating function outputs.
E N D
Programming Paradigms CPSC 449 Week 3-1 Prepared by : Mona Hosseinkhani, ArashAfshar Winter 2014 Department of Computer Science, University of Calgary
Program Testing • Different type of tests: • Prove: expensive process • QuickCheck: to test properties of functions using randomly generated data (defining properties is not always clear) • Traditional test: manually specify inputs and expected output • The art of testing: • choose the inputs as comprehensive as possible • represent all the different ‘kinds’ of input to the function
Program testing approaches • Black box testing • Devise test data just by knowing specification of function not the function definition • White box testing • Devise test data according to the function definition • Example: • function that returns the maximum of three integers • maxThree:: Int -> Int -> Int -> Int
Program Testing – Black box test • Partition the inputs into different testing groups • e.g. positive and negative numbers • Make sure you choose at least one representative from each group • Pay attention to any special cases • i.e. boundaries of groups. e.g. zero
Program Testing – Black box test • Example: maxThree:: Integer -> Integer -> Integer -> Integer maxThree x y z |x >= y && x >= z = x |y >= z = y |otherwise = z • Testing groups: • all three values different • all three values the same • two items equal, the third different • two values equal to maximum, one other • one value equal to the maximum, two others • Set of test data • 641 • 666 • 266 • 226
Program Testing – Black box test • We can code this test in Hunit testing framework testMax1 = TestCase (assertEqual "for: maxThree 6 4 1" 6 (maxThree 6 4 1)) testMax2 = TestCase (assertEqual "for: maxThree 6 6 6" 6 (maxThree 6 6 6)) testMax3 = TestCase (assertEqual "for: maxThree 2 6 6" 6 (maxThree 2 6 6)) testMax4 = TestCase (assertEqual "for: maxThree 2 2 6" 6 (maxThree 2 2 6)) testsMax = TestList [testMax1, testMax2, testMax3, testMax4] -- run as -- runTestTTtestsMax
Program Testing – Black box test • Does this function calculate the maximum of three numbers? mysteryMax :: Integer -> Integer -> Integer -> Integer mysteryMax x y z | x > y && x > z = x | y > x && y > z = y | otherwise = z testMMax1 = TestCase (assertEqual "for: mysteryMax 6 4 1" 6 (mysteryMax 6 4 1)) testMMax2 = TestCase (assertEqual "for: mysteryMax 6 6 6" 6 (mysteryMax 6 6 6)) testMMax3 = TestCase (assertEqual "for: mysteryMax 2 6 6" 6 (mysteryMax 2 6 6)) testMMax4 = TestCase (assertEqual "for: mysteryMax 2 2 6" 6 (mysteryMax 2 2 6)) testMMax5 = TestCase (assertEqual "for: mysteryMax 6 6 2" 6 (mysteryMax 6 6 2)) testsMMax = TestList [testMMax1, testMMax2, testMMax3, testMMax4, testMMax5] Testing alone cannot assure us that a function is correct
Program testing – white box test • Same principles of black box testing applies here + • Use the form of program to choose test data • for functions containing guards, supply data for each case (also pay attention to boundary conditions) • e.g. in mysteryMax example, the first two inputs of 6 6 2 data are at the guards boundaries • guards: x>y && x>z y>x && y>z • for recursive functions, test zero case, the one case and the general case
Program testing – white box test • Example for general case test in recursive functions • function definition: • general property • We expect this property to be True whatever the input n • Test result: • Int is the fixed-size representation of Integers. When numbers become big enough, they wrap around into the negative fact :: Int -> Int fact n | n>1 = n * fact (n-1) | otherwise = 1 prop_fact n = fact n > 0 *Chapter4> quickCheckprop_fact *** Failed! Falsifiable (after 12 tests and 2 shrinks): 21
Tuples vs. Lists • Tuples • defined using ( ) • Can contain different types of data • Lists • Defined using [ ] • Can contain same type of data • Strings are lists
Naming Types • Give name to your types • Do it often to make the code more readable • type FName = String • type LName = String • type ID = (FName, LName) • identity :: ID • identity = (”Jack",”Smith") • Haskell treats them as synonyms
Tuple Operators • Pattern matching • f1 (a, b) = …function definition… • f1 (1, 2) would match “1” to “a” , “2” to “b” • In Pairs: fst & snd • f2 d = (fst d) + (snd d)
Examples • Define three different versions for Sum • Regular • sum a b = a + b • Pattern matching • sum (a, b) = a + b • Using pair operators • sum c = (fst c) + (snd c)
List Operators • Taking elements • head vs take • head [‘a’, ‘b’, ‘c’, ‘d’] = ‘a’ • take 2 [‘a’, ‘b’, ‘c’, ‘d’] = [‘a’, ‘b’] • last vs drop • last [‘a’, ‘b’, ‘c’, ‘d’] = ‘d’ • drop 3 [‘a’, ‘b’, ‘c’, ‘d’] = [‘d’]
List Operators (cont.) • tail vs init • tail ['a', 'b', 'c', 'd'] = ['b', 'c', 'd'] • init ['a', 'b', 'c', 'd'] = ['a', 'b', 'c'] • Taking only the n-th element • ['a', 'b', 'c', 'd'] !! 2 = ‘c’
List Operators (cont.) • Concatenation • Add a single element • 'a' : ['b', 'c', 'd'] = ['a', 'b', 'c', 'd'] • Add another list • ['a', 'b'] ++ ['c', 'd'] = ['a', 'b', 'c', 'd'] • Merge a 2D array into a simple list • concat [[‘a’],[‘b’, ‘c’],[‘d’]] = [‘a’, ‘b’, ‘c’, ‘d’]
List Operators (cont.) • Reversal • reverse ['a', 'b', 'c', 'd'] = ['d', 'c', 'b', 'a'] • Length • length ['a', 'b', 'c', 'd'] = 4 • Make copies • replicate 3 ['a', 'b', 'c', 'd'] = [['a','b','c','d'],['a','b','c','d'],['a','b','c','d']]
Question hossem@ucalgary.ca