Oskar Wickström
May 2019
prop_reverse = property $ do
xs <- forAll $
Gen.list
(Range.linear 0 10)
(Gen.int Range.linearBounded)
reverse (reverse xs) === xs
prop_sort = property $ do
xs <- forAll $
Gen.list
(Range.linear 0 10)
(Gen.int Range.linearBounded)
mySuperSort xs === industryStandardSort xs
How many of you write sort algorithms in your day job?
|
hprop_flat_timeline_has_same_duration_as_hierarchical =
property $ do
t <- forAll $ Gen.timeline (Range.exponential 0 20) Gen.parallelWithClips
let Just flat = Render.flattenTimeline t
durationOf AdjustedDuration t === durationOf AdjustedDuration flat
hprop_flat_timeline_has_same_clips_as_hierarchical =
property $ do
t <- forAll $ Gen.timeline (Range.exponential 0 20) Gen.parallelWithClips
let Just flat = Render.flattenTimeline t
timelineVideoClips t === flatVideoClips flat
timelineAudioClips t === flatAudioClips flat
hprop_classifies_still_segments_of_min_length = property $ do
-- 1. Generate a minimum still segment length/duration
minStillSegmentFrames <- forAll $ Gen.int (Range.linear 2 (2 * frameRate))
let minStillSegmentTime = frameCountDuration minStillSegmentFrames
-- 2. Generate output segments
segments <- forAll $
genSegments (Range.linear 1 10)
(Range.linear 1
(minStillSegmentFrames * 2))
(Range.linear minStillSegmentFrames
(minStillSegmentFrames * 2))
resolution
...
-- 3. Convert test segments to actual pixel frames
let pixelFrames = testSegmentsToPixelFrames segments
-- 4. Run the classifier on the pixel frames
let counted = classifyMovement minStillSegmentTime (Pipes.each pixelFrames)
& Pipes.toList
& countSegments
...
...
-- 5. Sanity check
countTestSegmentFrames segments === totalClassifiedFrames counted
-- 6. Ignore last segment and verify all other segments
case initMay counted of
Just rest ->
traverse_ (assertStillLengthAtLeast minStillSegmentTime) rest
Nothing -> success
where
resolution = 10 :. 10
> :{
| hprop_classifies_still_segments_of_min_length
| & Hedgehog.withTests 10000
| & Hedgehog.check
| :}
✓ <interactive> passed 10000 tests.
hprop_classifies_same_scenes_as_input = property $ do
-- 1. Generate a minimum still still segment duration
minStillSegmentFrames <- forAll $ Gen.int (Range.linear 2 (2 * frameRate))
let minStillSegmentTime = frameCountDuration minStillSegmentFrames
-- 2. Generate test segments
segments <- forAll $
genSegments (Range.linear 1 10)
(Range.linear 1
(minStillSegmentFrames * 2))
(Range.linear minStillSegmentFrames
(minStillSegmentFrames * 2))
resolution
...
...
-- 3. Convert test segments to actual pixel frames
let pixelFrames = testSegmentsToPixelFrames segments
-- 4. Convert expected output segments to a list of expected time spans
-- and the full duration
let durations = map segmentWithDuration segments
expectedSegments = movingSceneTimeSpans durations
fullDuration = foldMap unwrapSegment durations
...
...
-- 5. Classify movement of frames
let classifiedFrames =
Pipes.each pixelFrames
& classifyMovement minStillSegmentTime
& Pipes.toList
-- 6. Classify moving scene time spans
let classified =
(Pipes.each classifiedFrames
& classifyMovingScenes fullDuration)
>-> Pipes.drain
& Pipes.runEffect
& runIdentity
...
...
-- 7. Check classified time span equivalence
expectedSegments === classified
where
resolution = 10 :. 10
classifyMovement minStillSegmentTime =
case ... of
InStillState{..} ->
if someDiff > minEqualTimeForStill
then ...
else ...
InMovingState{..} ->
if someOtherDiff >= minStillSegmentTime
then ...
else ...
where
minEqualTimeForStill = 0.5
hprop_undo_actions_are_undoable = property $ do
-- Generate initial timeline and focus
timelineAndFocus <- forAllWith showTimelineAndFocus $
Gen.timelineWithFocus (Range.linear 0 10) Gen.parallel
-- Generate initial application state
initialState <- forAll (initializeState timelineAndFocus)
-- Generate a sequence of undoable/redoable commands
events <- forAll $
Gen.list (Range.exponential 1 100) genUndoableTimelineEvent
...
...
-- We begin by running 'events' on the original state
beforeUndos <- runTimelineStubbedWithExit events initialState
-- Then we run as many undo commands as undoable commands
afterUndos <- runTimelineStubbedWithExit (undoEvent <$ events) beforeUndos
-- That should result in a timeline equal to the one we at the
-- beginning
timelineToTree (initialState ^. currentTimeline)
=== timelineToTree (afterUndos ^. currentTimeline)
hprop_undo_actions_are_redoable = property $ do
-- Generate the initial timeline and focus
timelineAndFocus <- forAllWith showTimelineAndFocus $
Gen.timelineWithFocus (Range.linear 0 10) Gen.parallel
-- Generate the initial application state
initialState <- forAll (initializeState timelineAndFocus)
-- Generate a sequence of undoable/redoable commands
events <- forAll $
Gen.list (Range.exponential 1 100) genUndoableTimelineEvent
-- We begin by running 'events' on the original state
beforeUndos <- runTimelineStubbedWithExit events initialState
-- Then we undo and redo all of them
afterRedos <-
runTimelineStubbedWithExit (undoEvent <$ events) beforeUndos
>>= runTimelineStubbedWithExit (redoEvent <$ events)
-- That should result in a timeline equal to the one we had before
-- starting the undos
timelineToTree (beforeUndos ^. currentTimeline)
=== timelineToTree (afterRedos ^. currentTimeline)