packages feed

hjugement-1.0.0.20170804: test/HUnit.hs

{-# LANGUAGE OverloadedLists #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module HUnit where

import Test.Tasty
import Test.Tasty.HUnit

import Control.Arrow (second)
import qualified Data.Map.Strict as Map

import Hjugement
import Types

hunits :: TestTree
hunits =
	testGroup "HUnit"
	 [ testGroup "Value" $
		 [ testCompareValue
			 [(3,15), (2,7), (1,3), (0::Int,2)]
			 [(3,16), (2,6), (1,2), (0,3)]
		 , testGroup "OfMerits"
			 [  let m = mkMerit ['A'..'F'] in
				testValueOfMerits
				 [ (The, m [136,307,251,148,84,74])
				 ]
				 [ (The, [('C',251),('B',307),('D',148),('E',84),('A',136),('F',74)])
				 ]
			 , let m = mkMerit [ToReject .. TooGood] in
				testValueOfMerits
				 [ (This, m [12,10,21,5,5,5,2])
				 , (That, m [12,16,22,3,3,3,1])
				 ]
				 [ (This, [(Acceptable,21),(Insufficient,10),(Good,5),(ToReject,12),(Perfect,5),(VeryGood,5),(TooGood,2)])
				 , (That, [(Acceptable,22),(Insufficient,16),(ToReject,12),(VeryGood,3),(Perfect,3),(Good,3),(TooGood,1)])
				 ]
			 ]
		 , testGroup "OfOpinions"
			 [ testValueOfOpinions [No,Yes]
				   [The]
				 [ [No ]
				 , [No ]
				 , [No ]
				 , [No ]
				 , [Yes]
				 , [Yes]
				 ]
				 [ (The, [(No,4),(Yes,2)])
				 ]
			 , testValueOfOpinions [No,Yes]
				   [The]
				 [ [No ]
				 , [No ]
				 , [No ]
				 , [Yes]
				 , [Yes]
				 , [Yes]
				 ]
				 [ (The, [(No,3),(Yes,3)])
				 ]
			 , testValueOfOpinions [No,Yes]
				   [This, That]
				 [ [No  , No ]
				 , [No  , Yes]
				 , [No  , Yes]
				 , [No  , Yes]
				 , [Yes , Yes]
				 , [Yes , Yes]
				 ]
				 [ (This, [(No,4),(Yes,2)])
				 , (That, [(Yes,5),(No,1)])
				 ]
			 , testValueOfOpinions [No,Yes]
				   [This, That]
				 [ [No  , No ]
				 , [No  , No ]
				 , [No  , No ]
				 , [No  , Yes]
				 , [No  , Yes]
				 , [No  , Yes]
				 ]
				 [ (This, [(No,6),(Yes,0)])
				 , (That, [(No,3),(Yes,3)])
				 ]
			 , testValueOfOpinions [No,Yes]
				   [This, That]
				 [ [Yes , No ]
				 , [Yes , No ]
				 , [Yes , No ]
				 , [Yes , Yes]
				 , [Yes , Yes]
				 , [Yes , Yes]
				 ]
				 [ (This, [(Yes,6),(No,0)])
				 , (That, [(No,3),(Yes,3)])
				 ]
			 , testValueOfOpinions [No,Yes]
				   [This, That]
				 [ [No  , No ]
				 , [No  , No ]
				 , [Yes , No ]
				 , [Yes , Yes]
				 , [Yes , Yes]
				 , [Yes , Yes]
				 ]
				 [ (This, [(Yes,4),(No,2)])
				 , (That, [(No,3),(Yes,3)])
				 ]
			 , testValueOfOpinions [ToReject,Insufficient,Acceptable,Good,VeryGood,Perfect]
				   [1::Int ..6]
				 [ [Perfect,Perfect,Acceptable,VeryGood,Good,VeryGood]
				 , [Perfect,VeryGood,Perfect,Good,Acceptable,Acceptable]
				 , [VeryGood,VeryGood,Good,Acceptable,VeryGood,Insufficient]
				 , [Perfect,VeryGood,VeryGood,Good,Good,Acceptable]
				 , [Perfect,Good,VeryGood,Good,Good,Acceptable]
				 , [Perfect,VeryGood,Perfect,Good,Good,Good]
				 ]
				 [ (1, [(Perfect,5),(VeryGood,1),(ToReject,0),(Insufficient,0),(Acceptable,0),(Good,0)])
				 , (2, [(VeryGood,4),(Good,1),(Perfect,1),(ToReject,0),(Insufficient,0),(Acceptable,0)])
				 , (3, [(VeryGood,2),(Good,1),(Perfect,2),(Acceptable,1),(ToReject,0),(Insufficient,0)])
				 , (4, [(Good,4),(Acceptable,1),(VeryGood,1),(ToReject,0),(Insufficient,0),(Perfect,0)])
				 , (5, [(Good,4),(Acceptable,1),(VeryGood,1),(ToReject,0),(Insufficient,0),(Perfect,0)])
				 , (6, [(Acceptable,3),(Good,1),(Insufficient,1),(VeryGood,1),(ToReject,0),(Perfect,0)])
				 ]
			 ]
		 ]
	 ]


elide :: String -> String
elide s | length s > 42 = take 42 s ++ ['…']
        | otherwise = s

mkOpinion :: Ord prop =>
             Choices prop -> judge -> [grade] ->
             (judge, Opinion prop grade)
mkOpinion props j gs = (j, Map.fromList $ toList props `zip` gs)

mkMerit :: (Ord grade, Show grade) => [grade] -> [Count] -> Merit grade
mkMerit scal = fromList . (scal`zip`)

mkMerits :: (Ord prop, Ord grade) =>
            [grade] -> Choices prop -> [[grade]] ->
            Merits prop grade
mkMerits scal props opins =
	merits (Scale (fromList scal) (head scal)) props $ fromList $
	zipWith (mkOpinion props) [1::Int ..] opins


testCompareValue :: (Ord grade, Show grade) =>
                    [(grade, Count)] -> [(grade, Count)] -> TestTree
testCompareValue x y =
	testGroup (elide $ show (x,y))
	 [ testCase "x == x" $ Value x`compare`Value x @?= EQ
	 , testCase "y == y" $ Value y`compare`Value y @?= EQ
	 , testCase "x <  y" $ Value x`compare`Value y @?= LT
	 , testCase "y >  x" $ Value y`compare`Value x @?= GT
	 ]

testRanking :: (Ord prop, Ord grade, Show grade, Show prop) =>
               [grade] -> Choices prop -> [[grade]] ->
               Ranking prop -> TestTree
testRanking scal props opins expect =
	testCase (elide $ show (toList props,opins)) $
		majorityRanking (mkMerits scal props opins) @?= expect

testValueOfOpinions :: (Show grade, Show prop, Ord grade, Ord prop) =>
             [grade] -> Choices prop -> [[grade]] ->
             [(prop, [(grade,Count)])] -> TestTree
testValueOfOpinions scal props opins expect =
	testCase (elide $ show (toList props,opins)) $
		majorityValueByChoice (mkMerits scal props opins)
		 @?= ((Value`second`)<$>expect)

testValueOfMerits :: (Show grade, Show prop, Ord grade, Ord prop) =>
             Merits prop grade ->
             [(prop, [(grade,Count)])] -> TestTree
testValueOfMerits ms expect =
	testCase (elide $ show ms) $
		majorityValueByChoice ms
		 @?= ((Value`second`)<$>expect)