Skip to content

palindrome-products: Rewrite tests to use hspec with fail-fast. #286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions exercises/palindrome-products/HINTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Hints

To solve this exercise you need to implement these two functions:

- `largestPalindrome`
- `smallestPalindrome`

Both functions receive lower and upper factor limits, returning a pair
`(value, [(factor1, factor2)])` containing the palindrome and its possible
pairs of factors.

Your can use the provided signatures if you are unsure about the types, but
don't let them restrict your creativity.

It's ok to return duplicates in the factors list, and the order of the factors
is irrelevant.

You should consider using a slightly different algorithm to find small or
large palindromes.
3 changes: 1 addition & 2 deletions exercises/palindrome-products/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ tests:
source-dirs: test
dependencies:
- palindrome-products
- containers
- HUnit
- hspec
16 changes: 4 additions & 12 deletions exercises/palindrome-products/src/Palindromes.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
module Palindromes (largestPalindrome, smallestPalindrome) where

-- It's ok to return duplicates in the factor list, and the order of the factors
-- is irrelevant.
--
-- You should consider using a slightly different algorithm to find small or
-- large palindromes.
largestPalindrome :: Integer -> Integer -> (Integer, [(Integer, Integer)])
largestPalindrome minFactor maxFactor = undefined

-- largestPalindrome minFactor maxFactor = (value, [(factor1, factor2)])
largestPalindrome :: Integral a => a -> a -> (a, [(a, a)])
largestPalindrome = undefined

-- smallestPalindrome minFactor maxFactor = (value, [(factor1, factor2)])
smallestPalindrome :: Integral a => a -> a -> (a, [(a, a)])
smallestPalindrome = undefined
smallestPalindrome :: Integer -> Integer -> (Integer, [(Integer, Integer)])
smallestPalindrome minFactor maxFactor = undefined
101 changes: 32 additions & 69 deletions exercises/palindrome-products/test/Tests.hs
Original file line number Diff line number Diff line change
@@ -1,73 +1,36 @@
import Test.HUnit (Assertion, (@=?), runTestTT, Test(..), Counts(..))
import System.Exit (ExitCode(..), exitWith)
import Palindromes (largestPalindrome, smallestPalindrome)
import qualified Data.Set as S

-- largestPalindrome, smallestPalindrome :: Integral a => a -> a -> (a,[(a, a)])
-- largestPalindrome minFactor maxFactor = (value, [(factor1, factor2)])

-- It's ok to return duplicates in the factor list, and the order of the factors
-- is irrelevant.

-- You should consider using a slightly different algorithm to find small or
-- large palindromes.
{-# OPTIONS_GHC -fno-warn-type-defaults #-}

exitProperly :: IO Counts -> IO ()
exitProperly m = do
counts <- m
exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess
import Data.Foldable (for_)
import Data.List (nub, sort)
import Test.Hspec (Spec, describe, it, shouldBe)
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)

testCase :: String -> Assertion -> Test
testCase label assertion = TestLabel label (TestCase assertion)
import Palindromes (largestPalindrome, smallestPalindrome)

main :: IO ()
main = exitProperly $ runTestTT $ TestList
[ TestList palindromesTests ]

norm :: Ord a => [(a, a)] -> [(a, a)]
norm = S.toList . S.fromList . map normPair
where normPair p@(a, b) = if b < a then (b, a) else p

palindromesTests :: [Test]
palindromesTests =
[ testCase "largest palindrome from single digit factors" $ do
let (largest, factors) = largestPalindrome 1 9
(9 :: Int) @=? largest
[(1, 9), (3, 3)] @=? norm factors
, testCase "smallest palindrome from single digit factors" $ do
let (smallest, factors) = smallestPalindrome 1 9
(1 :: Int) @=? smallest
[(1, 1)] @=? norm factors
, testCase "largest palindrome from double digit factors" $ do
let (largest, factors) = largestPalindrome 10 99
(9009 :: Int) @=? largest
[(91, 99)] @=? norm factors
, testCase "smallest palindrome from double digit factors" $ do
let (smallest, factors) = smallestPalindrome 10 99
(121 :: Int) @=? smallest
[(11, 11)] @=? norm factors
, testCase "largest palindrome from triple digit factors" $ do
let (largest, factors) = largestPalindrome 100 999
(906609 :: Int) @=? largest
[(913, 993)] @=? norm factors
, testCase "smallest palindrome from triple digit factors" $ do
let (smallest, factors) = smallestPalindrome 100 999
(10201 :: Int) @=? smallest
[(101, 101)] @=? norm factors
, testCase "largest palindrome from four digit factors" $ do
let (largest, factors) = largestPalindrome 1000 9999
(99000099 :: Int) @=? largest
[(9901, 9999)] @=? norm factors
, testCase "smallest palindrome from four digit factors" $ do
let (smallest, factors) = smallestPalindrome 1000 9999
(1002001 :: Int) @=? smallest
[(1001,1001)] @=? norm factors
, testCase "largest palindrome from five digit factors" $ do
let (largest, factors) = largestPalindrome 10000 99999
(9966006699 :: Integer) @=? largest
[(99681, 99979)] @=? norm factors
, testCase "smallest palindrome from five digit factors" $ do
let (smallest, factors) = smallestPalindrome 10000 99999
(100020001 :: Integer) @=? smallest
[(10001,10001)] @=? norm factors
]
main = hspecWith defaultConfig {configFastFail = True} specs

specs :: Spec
specs = describe "palindrome-products" $ for_ cases test
where
test (desc, minFactor, maxFactor, sPal, sPalFactors, lPal, lPalFactors) =
describe desc $ do
let sortPair (a, b) = if a < b then (a, b) else (b, a)
let normalize = sort . nub . map sortPair
describe "smallesPalindrome" $ do
let (value, factors) = smallestPalindrome minFactor maxFactor
it "value" $ value `shouldBe` sPal
it "factors" $ normalize factors `shouldBe` sPalFactors
describe "largestPalindrome" $ do
let (value, factors) = largestPalindrome minFactor maxFactor
it "value" $ value `shouldBe` lPal
it "factors" $ normalize factors `shouldBe` lPalFactors

-- As of 2016-09-07, there was no reference file
-- for the test cases in `exercism/x-common`.

cases = [ ("palindromes from single digit factors", 1, 9, 1, [( 1, 1)], 9, [(1, 9), (3, 3)])
, ("palindromes from double digit factors", 10, 99, 121, [( 11, 11)], 9009, [( 91, 99)])
, ("palindromes from triple digit factors", 100, 999, 10201, [( 101, 101)], 906609, [( 913, 993)])
, ("palindromes from four digit factors" , 1000, 9999, 1002001, [( 1001, 1001)], 99000099, [( 9901, 9999)])
, ("palindromes from five digit factors" , 10000, 99999, 100020001, [(10001, 10001)], 9966006699, [(99681, 99979)]) ]