Skip to content

Commit 1b04aef

Browse files
Refactor test interface (#100)
* Monad stack for tests * Use ReaderT to distribute picture/animation * Throw errors with Except * add new functions for animation and picture tests * adjust examples
1 parent 88d2eab commit 1b04aef

File tree

14 files changed

+674
-370
lines changed

14 files changed

+674
-370
lines changed

examples/configs/Task01.hs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ main = drawingOf scene
185185
----------
186186
module Test (test) where
187187
import qualified Task01
188-
import Test.HUnit ((~:), (~?), Test)
188+
import Test.HUnit ((~:), Test(..), assertString)
189189
import CodeWorld.Test (
190190
withColor,
191191
green,
@@ -194,27 +194,29 @@ import CodeWorld.Test (
194194
yellow,
195195

196196
containsElem,
197-
evaluatePred,
198197
hasRelation,
199198
isAbove,
199+
200+
complain,
201+
testPicture,
200202
)
201203

202204
import TestHelper (isDeeplyDefined)
203205

204206
test :: [ Test ]
205207
test =
206208
[ "scene =/= undefined?" ~: isDeeplyDefined Task01.scene
207-
, onScene (containsElem someSolidCircle) ~?
208-
"This picture does not contain a solid circle."
209-
, onScene (containsElem someSolidRectangle) ~?
210-
"This picture does not contain a solid rectangle."
211-
, onScene (containsElem $ withColor yellow someSolidCircle) ~?
212-
"The circle is not yellow."
213-
, onScene (containsElem $ withColor green someSolidRectangle) ~?
214-
"The rectangle is not green."
215-
, onScene (hasRelation $ withColor yellow someSolidCircle `isAbove` withColor green someSolidRectangle) ~?
216-
"the sun should be positioned above the grass."
209+
, TestCase $ assertString $ testPicture Task01.scene $ do
210+
complain "This picture does not contain a solid circle."
211+
$ containsElem someSolidCircle
212+
complain "This picture does not contain a solid rectangle."
213+
$ containsElem someSolidRectangle
214+
complain "The circle is not yellow."
215+
$ containsElem $ withColor yellow someSolidCircle
216+
complain "The rectangle is not green."
217+
$ containsElem $ withColor green someSolidRectangle
218+
complain "the sun should be positioned above the grass."
219+
$ hasRelation $ withColor yellow someSolidCircle `isAbove` withColor green someSolidRectangle
217220
]
218-
where
219-
onScene = flip evaluatePred Task01.scene
221+
220222

examples/configs/Task02.hs

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,12 @@ scene = undefined
185185
----------
186186
module Test (test) where
187187
import qualified Task02
188-
import Test.HUnit ((~:), (~?), Assertion, Test(..), assertBool)
188+
import Test.HUnit (
189+
(~:),
190+
Test(..),
191+
assertBool,
192+
assertString,
193+
)
189194
import CodeWorld.Test (
190195
brown,
191196
green,
@@ -198,13 +203,15 @@ import CodeWorld.Test (
198203

199204
atLeast,
200205
containsElem,
201-
evaluatePred,
202-
evaluatePreds,
203206
hasRelation,
204207
ifThen,
205208
isAbove,
206209
isLeftOf,
207210
isNorthOf,
211+
(<&&>),
212+
213+
complain,
214+
testPicture,
208215

209216
testCSE,
210217
)
@@ -215,32 +222,30 @@ import TestHelper (isDeeplyDefined)
215222
test :: [ Test ]
216223
test =
217224
[ "scene =/= undefined?" ~: isDeeplyDefined Task02.scene
218-
, onScene (containsElem wood) ~?
219-
"Picture contains a trunk?"
220-
, onScene (wood `atLeast` 3) ~?
221-
"Tree has at least a trunk and two branches?"
222-
, onScene (containsElem $ withColor green someSolidCircle) ~?
223-
"Tree has a green crown?"
224-
, onScene (hasRelation $ withColor green someSolidCircle `isNorthOf` uprightWood) ~?
225-
"The trunk stands upright and there is a tree crown above it?"
226-
, onSceneMulti
227-
[ containsElem (rotatedQuarter uprightWood) `ifThen` containsElem (rotatedUpToFull uprightWood)
228-
, containsElem (rotatedUpToFull uprightWood) `ifThen` containsElem (rotatedQuarter uprightWood)
229-
] ~?
230-
"Branches are roughly symmetrical? (if they already are, make sure your branches share code as much as possible)"
231-
, onSceneMulti
232-
[ hasRelation $ rotatedQuarter uprightWood `isAbove` uprightWood
233-
, hasRelation $ rotatedUpToFull uprightWood `isAbove` uprightWood
234-
, hasRelation $ rotatedQuarter uprightWood `isLeftOf` rotatedUpToFull uprightWood
235-
] ~?
236-
"Branches are in the correct position? " ++
237-
"(They should neither cross, nor be detached from the trunk, nor be at level with the trunk)"
225+
, TestCase $ assertString $ testPicture Task02.scene $ do
226+
complain "Picture contains a trunk?" $ containsElem wood
227+
complain "Tree has at least a trunk and two branches?" $ wood `atLeast` 3
228+
complain "Tree has a green crown?" $ containsElem $ withColor green someSolidCircle
229+
complain "The trunk stands upright and there is a tree crown above it?"
230+
$ hasRelation $ withColor green someSolidCircle `isNorthOf` uprightWood
231+
complain
232+
( "Branches are roughly symmetrical? " ++
233+
"(if they already are, make sure your branches share code as much as possible)"
234+
)
235+
$ containsElem (rotatedQuarter uprightWood) `ifThen` containsElem (rotatedUpToFull uprightWood) <&&>
236+
containsElem (rotatedUpToFull uprightWood) `ifThen` containsElem (rotatedQuarter uprightWood)
237+
complain
238+
( "Branches are in the correct position? " ++
239+
"(They should neither cross, nor be detached from the trunk, nor be at level with the trunk)"
240+
)
241+
$ hasRelation (rotatedQuarter uprightWood `isAbove` uprightWood) <&&>
242+
hasRelation (rotatedUpToFull uprightWood `isAbove` uprightWood) <&&>
243+
hasRelation (rotatedQuarter uprightWood `isLeftOf` rotatedUpToFull uprightWood)
244+
238245
, TestCase $ do
239246
result <- testCSE Task02.scene
240247
assertBool (fromJust result) (isNothing result)
241248
]
242249
where
243-
onScene = flip evaluatePred Task02.scene
244-
onSceneMulti = flip evaluatePreds Task02.scene
245250
wood = withColor brown someSolidRectangle
246251
uprightWood = withColor brown someTallSolidRectangle

examples/configs/Task03.hs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ scene = undefined
188188
----------
189189
module Test (test) where
190190
import qualified Task03
191-
import Test.HUnit ((~:), (~?), Test)
191+
import Test.HUnit ((~:), Test(..), assertString)
192192
import CodeWorld.Test (
193193
(.&.),
194194
withColor,
@@ -199,45 +199,47 @@ import CodeWorld.Test (
199199
white,
200200
yellow,
201201

202-
findMaybe,
203-
getComponents,
202+
findAllAnd,
204203
getExactScalingFactors,
205204
contains,
206205

207206
(<||>),
208207
atSamePosition,
209208
containsElem,
210-
evaluatePred,
211209
hasRelation,
212210
isBelow,
213211
oneOf,
214-
)
215212

213+
complain,
214+
testPicture,
215+
)
216216
import TestHelper (isDeeplyDefined)
217217

218218
test :: [ Test ]
219219
test =
220220
[ "scene =/= undefined?" ~: isDeeplyDefined Task03.scene
221-
, onScene (containsElem yolk) ~?
222-
"The picture does not contain the yellow yolk."
223-
, onScene (oneOf containsElem [someCircle, solidWhite, polyEgg]) ~?
224-
"The picture does not contain the egg white."
225-
, onScene (oneOf containsElem [egg, solidGray, multiEgg, polyEgg]) ~?
226-
"The shell could not be found. It might have the wrong color (should be grey) " ++
227-
"or might not be a continuous, round shape."
228-
, any (uncurry (<) . scalingFactor) [egg,solidGray] ||
229-
onScene (containsElem polyEgg) ~?
230-
"The egg shell does not seem to have an oval shape."
231-
, onScene ( oneOf (\p ->
232-
hasRelation (yolk `atSamePosition` p) <||>
233-
hasRelation (yolk `isBelow` p)) [egg, multiEgg, polyEgg]
234-
) ~? "The yolk is not inside the egg or has not been positioned correctly inside it."
221+
, TestCase $ assertString $ testPicture Task03.scene $ do
222+
complain "The picture does not contain the yellow yolk."
223+
$ containsElem yolk
224+
complain "The picture does not contain the egg white."
225+
$ oneOf containsElem [someCircle, solidWhite, polyEgg]
226+
complain
227+
( "The shell could not be found. It might have the wrong color (should be grey) " ++
228+
"or might not be a continuous, round shape."
229+
)
230+
$ oneOf containsElem [egg, solidGray, multiEgg, polyEgg]
231+
complain "The egg shell does not seem to have an oval shape." $ do
232+
circleEggs <- findAllAnd
233+
((||) <$> (`contains` egg) <*> (`contains` solidGray))
234+
getExactScalingFactors
235+
pure (any (uncurry (<)) circleEggs) <||> containsElem polyEgg
236+
complain "The yolk is not inside the egg or has not been positioned correctly inside it."
237+
$ oneOf (\p ->
238+
hasRelation (yolk `atSamePosition` p) <||>
239+
hasRelation (yolk `isBelow` p)
240+
) [egg, multiEgg, polyEgg]
235241
]
236242
where
237-
onScene = flip evaluatePred Task03.scene
238-
scalingFactor p = maybe (1,1) getExactScalingFactors $
239-
findMaybe (`contains` p) $ getComponents Task03.scene
240-
241243
egg = withColor gray someCircle
242244
multiEgg = solidGray .&. solidWhite
243245
polyEgg = withColor gray (someCurve 4)

examples/configs/Task04.hs

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,14 @@ truncatedTime t =
236236
let (n,f) = properFraction t
237237
in show (n :: Int) ++ take 3 (tail (show f))
238238
----------
239+
{-# language NoMonomorphismRestriction #-}
240+
239241
module Test (test) where
240242
import qualified Task04
241-
243+
import Data.Maybe (isNothing)
242244
import Data.List.Extra (nubOrd)
243-
import Data.Tuple.Extra (both)
244-
import Test.HUnit ((~:), (~?), Test(..), assertBool)
245+
import Data.Tuple.Extra ((&&&))
246+
import Test.HUnit ((~:), Test(..), assertBool, assertString)
245247
import CodeWorld.Test (
246248
withColor,
247249
green,
@@ -251,48 +253,67 @@ import CodeWorld.Test (
251253
yellow,
252254

253255
contains,
254-
findMaybeActual,
255-
getComponents,
256+
findMaybeActualAnd,
256257
getExactTranslation,
257258
getRotation,
258259

259260
containsElem,
260-
evaluatePred,
261261
hasRelation,
262262
isBelow,
263263

264+
atTime,
265+
noneAt,
266+
rawImagesAt,
267+
queryAt,
268+
269+
complain,
270+
testAnimation,
271+
testPicture,
272+
264273
samplesUntil,
265274
)
266-
275+
import Control.Monad.Reader
267276
import qualified TestHarness as TH
268277
import TestHelper (isDeeplyDefined)
269278

270279
test :: [ Test ]
271280
test =
272281
[ "scene =/= undefined?" ~: isDeeplyDefined (Task04.scene 1.0)
273-
, onSceneAt 0 (containsElem someSolidCircle) ~?
274-
"This animation does not contain a solid circle."
275-
, onSceneAt 0 (containsElem someSolidRectangle) ~?
276-
"This animation does not contain a solid rectangle."
277-
, onSceneAt 0 (containsElem sun) ~?
278-
"The circle is not yellow."
279-
, onSceneAt 0 (containsElem grass) ~?
280-
"The rectangle is not green."
281-
, grassRotations (100 : frames) == 1 &&
282-
grassMovement (100 : frames) == 1 ~?
283-
"The grass seems to move or disappear at some point during this animation. " ++
284-
"It should be stationary and the sun should move instead."
285-
, not (onSceneAt 0 (containsElem cheat)) ~?
286-
"The scene contains a solid white rectangle. " ++
287-
"This suggests you are trying to conceal the movement of the sun at some point."
288-
, differentFrames (map (+100) frames) == 1 ~?
289-
"Your animation has changing frames after running for 100 seconds. " ++
290-
"This suggests your sun is permanently moving instead of setting at some point."
291-
, differentFrames frames > 1 ~?
292-
"Cannot detect (reasonable) movement in this animation. Make sure parameter 't' is not ignored. " ++
293-
"Your sun might be moving in a strange way if 't' is actually used for movement."
294-
, all (\t -> not $ onSceneAt t (hasRelation (sun `isBelow` grass))) (samplesUntil 0.5 30) ~?
295-
"Your sun is moving under the grass!"
282+
, TestCase $ assertString $ testAnimation Task04.scene $ do
283+
atTime 0 $ do
284+
complain "This animation does not contain a solid circle."
285+
$ containsElem someSolidCircle
286+
complain "This animation does not contain a solid rectangle."
287+
$ containsElem someSolidRectangle
288+
complain "The circle is not yellow." $ containsElem sun
289+
complain "The rectangle is not green." $ containsElem grass
290+
complain
291+
( "The scene contains a solid white rectangle. " ++
292+
"This suggests you are trying to conceal the movement of the sun at some point."
293+
)
294+
$ not <$> containsElem cheat
295+
296+
complain
297+
( "The grass seems to move or disappear at some point during this animation. " ++
298+
"It should be stationary and the sun should move instead."
299+
)
300+
$ (==1) . uniques <$> queryAt (100 : frames) getGrassValues
301+
302+
complain
303+
( "Your animation has changing frames after running for 100 seconds. " ++
304+
"This suggests your sun is permanently moving instead of setting at some point."
305+
)
306+
$ (==1) . uniques <$> rawImagesAt (map (+100) frames)
307+
308+
complain
309+
( "Cannot detect (reasonable) movement in this animation. Make sure parameter 't' is not ignored. " ++
310+
"Your sun might be moving in a strange way if 't' is actually used for movement."
311+
)
312+
$ (>1) . uniques <$> rawImagesAt frames
313+
314+
complain "Your sun is moving under the grass!"
315+
$ noneAt (samplesUntil 0.5 30) $ hasRelation $ sun `isBelow` grass
316+
296317
, TestCase $ TH.syntaxCheckWithExts ["LambdaCase","NoTemplateHaskell","TupleSections"] $ \m -> assertBool
297318
( "The sun is not exhibiting circular movement. " ++
298319
"Please make sure it is not following a parabola shape or other different motions."
@@ -303,13 +324,7 @@ test =
303324
frames = samplesUntil 0.2 5
304325
grass = withColor green someSolidRectangle
305326
cheat = withColor white someSolidRectangle
306-
onSceneAt t = flip evaluatePred (Task04.scene t)
307-
sceneAt = getComponents . Task04.scene
308-
mapUniques f = length . nubOrd . map f
309-
differentFrames = mapUniques Task04.scene
310-
getElementAt p = findMaybeActual (`contains` p) . Task04.scene
311-
rotationAt p t = getRotation <$> getElementAt p t
312-
grassRotations = mapUniques $ rotationAt grass
313-
grassMovement = mapUniques (fmap getExactTranslation . getElementAt grass)
327+
uniques = length . nubOrd
328+
getGrassValues = findMaybeActualAnd (`contains` grass)
329+
$ getRotation &&& getExactTranslation
314330
sun = withColor yellow someSolidCircle
315-

0 commit comments

Comments
 (0)