diff --git a/exercises/matrix/package.yaml b/exercises/matrix/package.yaml index 3127b7e15..677a3fd61 100644 --- a/exercises/matrix/package.yaml +++ b/exercises/matrix/package.yaml @@ -17,4 +17,4 @@ tests: source-dirs: test dependencies: - matrix - - HUnit + - hspec diff --git a/exercises/matrix/test/Tests.hs b/exercises/matrix/test/Tests.hs index 0a0acb7db..21697092e 100644 --- a/exercises/matrix/test/Tests.hs +++ b/exercises/matrix/test/Tests.hs @@ -1,87 +1,90 @@ -import Test.HUnit (Assertion, (@=?), runTestTT, Test(..), Counts(..)) -import System.Exit (ExitCode(..), exitWith) -import Matrix ( Matrix, row, column, rows, cols, shape, transpose - , reshape, flatten, fromString, fromList) -import Control.Arrow ((&&&)) -import qualified Data.Vector as V +import Control.Arrow ((&&&)) +import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy) +import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith) --- Implementation of a row-major matrix for any type, using Data.Vector. +import qualified Data.Vector as Vector (fromList) --- fromString should work for any type that implements the Read typeclass. --- You can assume that "\n" is used to delimit rows without context --- sensitivity, but treatment of whitespace in a row should be context --- sensitive! +import Matrix + ( Matrix + , cols + , column + , flatten + , fromList + , fromString + , reshape + , row + , rows + , shape + , transpose + ) --- No validation of input is required. Let it fail if the matrix is not --- rectangular, invalid chars are encountered, etc. +main :: IO () +main = hspecWith defaultConfig {configFastFail = True} specs --- shape is (rows, cols) +specs :: Spec +specs = describe "matrix" $ do -exitProperly :: IO Counts -> IO () -exitProperly m = do - counts <- m - exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess + -- As of 2016-08-08, there was no reference file + -- for the test cases in `exercism/x-common`. -testCase :: String -> Assertion -> Test -testCase label assertion = TestLabel label (TestCase assertion) + let intMatrix = fromString :: String -> Matrix Int + let vector = Vector.fromList -main :: IO () -main = exitProperly $ runTestTT $ TestList - [ TestList matrixTests ] - -v :: [a] -> V.Vector a -v = V.fromList - -msInt :: String -> Matrix Int -msInt = fromString - -msInteger :: String -> Matrix Integer -msInteger = fromString - -msChar :: String -> Matrix Char -msChar = fromString - -msString :: String -> Matrix String -msString = fromString - -matrixTests :: [Test] -matrixTests = - [ testCase "extract first row" $ do - v [1, 2] @=? row 0 (msInt "1 2\n10 20") - v [9, 7] @=? row 0 (msInteger "9 7\n8 6") - , testCase "extract second row" $ do - v [19, 18, 17] @=? row 1 (msInt "9 8 7\n19 18 17") - v [16, 25, 36] @=? row 1 (msInteger "1 4 9\n16 25 36") - , testCase "extract first column" $ do - v [1, 4, 7, 8] @=? column 0 (msInt "1 2 3\n4 5 6\n7 8 9\n 8 7 6") - v [1903, 3, 4] @=? column 1 (msInteger "89 1903 3\n18 3 1\n9 4 800") - , testCase "shape" $ do - (0, 0) @=? shape (msInt "") - (1, 1) @=? shape (msInt "1") - (2, 1) @=? shape (msInt "1\n2") - (1, 2) @=? shape (msInt "1 2") - (2, 2) @=? shape (msInt "1 2\n3 4") - , testCase "rows & cols" $ - (1, 2) @=? (rows &&& cols) (msInt "1 2") - , testCase "eq" $ - msInt "1 2" @=? msInt "1 2" - , testCase "fromList" $ do - msInt "1 2" @=? fromList [[1, 2]] - msInt "1\n2" @=? fromList [[1], [2]] - , testCase "transpose" $ do - msInt "1 2 3" @=? transpose (msInt "1\n2\n3") - msInt "1 2 3\n4 5 6" @=? transpose (msInt "1 4\n2 5\n3 6") - , testCase "reshape" $ do - msInt "1 2\n3 4" @=? reshape (2, 2) (msInt "1 2 3 4") - , testCase "flatten" $ do - v [1, 2, 3, 4] @=? flatten (msInt "1 2\n3 4") - , testCase "matrix of chars" $ do - fromList ["foo", "bar"] @=? msChar "'f' 'o' 'o'\n'b' 'a' 'r'" - , testCase "matrix of strings" $ do - fromList [["this one"], ["may be tricky!"]] @=? - msString "\"this one\"\n\"may be tricky!\"" - , testCase "matrix of strings 2" $ do - fromList [["this one", "one"], ["may be tricky!", "really tricky"]] @=? - msString "\"this one\" \"one\" \n\"may be tricky!\" \"really tricky\"" - - ] + it "extract first row" $ do + row 0 (intMatrix "1 2\n10 20") `shouldBe` vector [1, 2] + row 0 (intMatrix "9 7\n8 6" ) `shouldBe` vector [9, 7] + + it "extract second row" $ do + row 1 (intMatrix "9 8 7\n19 18 17") `shouldBe` vector [19, 18, 17] + row 1 (intMatrix "1 4 9\n16 25 36") `shouldBe` vector [16, 25, 36] + + it "extract first column" $ do + column 0 (intMatrix "1 2 3\n4 5 6\n7 8 9\n 8 7 6") + `shouldBe` vector [1, 4, 7, 8] + column 1 (intMatrix "89 1903 3\n18 3 1\n9 4 800") + `shouldBe` vector [1903, 3, 4] + + it "shape" $ do + shape (intMatrix "" ) `shouldBe` (0, 0) + shape (intMatrix "1" ) `shouldBe` (1, 1) + shape (intMatrix "1\n2" ) `shouldBe` (2, 1) + shape (intMatrix "1 2" ) `shouldBe` (1, 2) + shape (intMatrix "1 2\n3 4") `shouldBe` (2, 2) + + it "rows & cols" $ + (rows &&& cols) (intMatrix "1 2") `shouldBe` (1, 2) + + it "eq" $ do + + -- `shouldNotBe` is not availabe on lts-2.22. + let x `shouldNotBe` y = x `shouldSatisfy` (/= y) + + intMatrix "1 2" `shouldBe` intMatrix "1 2" + intMatrix "2 3" `shouldNotBe` intMatrix "1 2 3" + + it "fromList" $ do + fromList [[1 , 2]] `shouldBe` intMatrix "1 2" + fromList [[1], [2]] `shouldBe` intMatrix "1\n2" + + it "transpose" $ do + transpose (intMatrix "1\n2\n3" ) `shouldBe` intMatrix "1 2 3" + transpose (intMatrix "1 4\n2 5\n3 6") `shouldBe` intMatrix "1 2 3\n4 5 6" + + it "reshape" $ do + reshape (2, 2) (intMatrix "1 2 3 4") `shouldBe` intMatrix "1 2\n3 4" + + it "flatten" $ do + flatten (intMatrix "1 2\n3 4") `shouldBe` vector [1, 2, 3, 4] + + it "matrix of chars" $ do + fromString "'f' 'o' 'o'\n'b' 'a' 'r'" `shouldBe` fromList ["foo", "bar"] + + it "matrix of strings" $ do + fromString "\"this one\"\n\"may be tricky!\"" + `shouldBe` fromList [ ["this one" ] + , ["may be tricky!"] ] + + it "matrix of strings 2" $ do + fromString "\"this one\" \"one\" \n\"may be tricky!\" \"really tricky\"" + `shouldBe` fromList [ ["this one" , "one" ] + , ["may be tricky!", "really tricky"] ]