Janiczek/elm-common-tests/2.0.0

CommonTests.Dict

isDict : DictAPI d -> Test

Given a record of your Dict functions, this function will run a comprehensive suite of tests against them, comparing them to the elm/core Dict.

It will:

  • Create the initial Dict using a random constructor (like empty, singleton or fromList)
  • Run a random sequence of "updating" actions on it (like insert, filter, diff etc.)
  • Query the final Dict using a random function (like size, get, partition, toList etc.)

The process above will run on both your Dict and the elm/core Dict in tandem. (The same commands will run for both.)

There should be no visible difference in behaviour: eg. order of items given from toList should be the same.

This helps prevent subtle surprises when users switch between Dict implementations, like update key (\_ -> Nothing) not removing items from the Dict (a real bug in one of the 3rd-party Dicts!).

isUnorderedDict : DictAPI d -> Test

Same as isDict, but doesn't care about the order of lists gathered from query Dict functions like keys, toList, partition etc.

(Note folds on unordered lists might also behave differently if your combining function is not commutative, given the order is not guaranteed. As such, this test suite will only check that all items are used in the fold.)

type alias DictAPI d =
{ dictToString : d -> String
, empty : Maybe d
, singleton : Maybe (String -> Int -> d)
, fromList : Maybe (List ( String, Int ) -> d)
, insert : Maybe (String -> Int -> d -> d)
, remove : Maybe (String -> d -> d)
, update : Maybe (String -> (Maybe Int -> Maybe Int) -> d -> d)
, map : Maybe ((String -> Int -> Int) -> d -> d)
, filter : Maybe ((String -> Int -> Bool) -> d -> d)
, union : Maybe (d -> d -> d)
, intersect : Maybe (d -> d -> d)
, diff : Maybe (d -> d -> d)
, size : Maybe (d -> Int)
, isEmpty : Maybe (d -> Bool)
, member : Maybe (String -> d -> Bool)
, get : Maybe (String -> d -> Maybe Int)
, toList : Maybe (d -> List ( String, Int ))
, foldl :
Maybe
((String -> Int -> List Int -> List Int) -> List Int -> d -> List Int)
, foldr :
Maybe
((String -> Int -> List Int -> List Int) -> List Int -> d -> List Int)
, partition : Maybe ((String -> Int -> Bool) -> d -> ( d, d ))
, keys : Maybe (d -> List String)
, values : Maybe (d -> List Int)
, merge :
Maybe
( (String -> Int -> List Int -> List Int)
-> (String -> Int -> Int -> List Int -> List Int)
-> (String -> Int -> List Int -> List Int)
-> d
-> d
-> List Int
-> List Int
)
}

Provide your functions. Typically something like the below example.

Note: you can opt out of testing some functions with Nothing, but beware: not providing eg. toList will result in almost no tests being actually ran.

-- Debug.toString
{ dictToString = Debug.toString


-- Creation
, empty = Just <| OpaqueDict.empty identity
, singleton = Just <| OpaqueDict.singleton identity
, fromList = Just <| OpaqueDict.fromList identity


-- Updating
, insert = Just OpaqueDict.insert
, update = Just OpaqueDict.update
, remove = Just OpaqueDict.remove
, map = Just OpaqueDict.map
, filter = Just OpaqueDict.filter
, union = Just OpaqueDict.union
, intersect = Just OpaqueDict.intersect
, diff = Just OpaqueDict.diff


-- Querying
, size = Just OpaqueDict.size
, isEmpty = Just OpaqueDict.isEmpty
, member = Just OpaqueDict.member
, get = Just OpaqueDict.get
, toList = Just OpaqueDict.toList
, foldl = Just OpaqueDict.foldl
, foldr = Just OpaqueDict.foldr
, partition = Just OpaqueDict.partition
, keys = Just OpaqueDict.keys
, values = Just OpaqueDict.values
, merge = Just OpaqueDict.merge
}