From 05f873bf1a0516c0880fec7ca2c0b60005493126 Mon Sep 17 00:00:00 2001 From: rbasso Date: Sat, 24 Sep 2016 02:17:24 +0900 Subject: [PATCH] house: Rewrite tests and add working stub solution. - Use lyrics from `x-common/exercises/house/description.md`. - Tests all lines, one by one, and then the entire song. - Add stub solution passing the tests. - Patch example solution to work with the new tests. --- exercises/house/HINTS.md | 18 +++ exercises/house/src/Example.hs | 4 +- exercises/house/src/House.hs | 90 +++++++++++++- exercises/house/test/Tests.hs | 212 ++++++++++++++++++--------------- 4 files changed, 229 insertions(+), 95 deletions(-) create mode 100644 exercises/house/HINTS.md diff --git a/exercises/house/HINTS.md b/exercises/house/HINTS.md new file mode 100644 index 000000000..6ee1a78ef --- /dev/null +++ b/exercises/house/HINTS.md @@ -0,0 +1,18 @@ +## Hints + +This exercise is about [code refactoring](https://en.wikipedia.org/wiki/Refactoring), +so we are providing you with a solution that already passes the tests. + +The challenge is to rewrite it until you are proud of it, and learn +something in the process. + +If you don't know where to start, here are some ideas: + +- Try to reduce repetition to a minimum. +- Try to make the code readable. + +Take your time. + +Change one thing at a time and check if your solution still passes the tests. + +Have fun! diff --git a/exercises/house/src/Example.hs b/exercises/house/src/Example.hs index 05faacd7b..495fa5dda 100644 --- a/exercises/house/src/Example.hs +++ b/exercises/house/src/Example.hs @@ -1,7 +1,9 @@ module House (rhyme) where +import Data.List (intercalate) + rhyme :: String -rhyme = unlines $ map ("This is " ++) $ scanl1 f pieces +rhyme = intercalate "\n" $ map ("This is " ++) $ scanl1 f pieces where f tail' piece = piece ++ ' ' : tail' pieces :: [String] diff --git a/exercises/house/src/House.hs b/exercises/house/src/House.hs index f6f8034a3..f920b1ff6 100644 --- a/exercises/house/src/House.hs +++ b/exercises/house/src/House.hs @@ -1,4 +1,92 @@ module House (rhyme) where rhyme :: String -rhyme = undefined +rhyme = "This is the house that Jack built.\n\ + \\n\ + \This is the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the rooster that crowed in the morn\n\ + \that woke the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the farmer sowing his corn\n\ + \that kept the rooster that crowed in the morn\n\ + \that woke the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the horse and the hound and the horn\n\ + \that belonged to the farmer sowing his corn\n\ + \that kept the rooster that crowed in the morn\n\ + \that woke the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n" diff --git a/exercises/house/test/Tests.hs b/exercises/house/test/Tests.hs index 580b4f58d..5dce04e32 100644 --- a/exercises/house/test/Tests.hs +++ b/exercises/house/test/Tests.hs @@ -1,4 +1,5 @@ -import Test.Hspec (Spec, describe, it, shouldBe) +import Control.Monad (unless) +import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe) import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith) import House (rhyme) @@ -8,96 +9,121 @@ main = hspecWith defaultConfig {configFastFail = True} specs specs :: Spec specs = describe "house" $ - it "rhyme" $ rhyme `shouldBe` expected + + describe "rhyme" $ do + + -- First we test the input, line by line, to give more + -- useful error messages. + + it "matches lines" $ sequence_ lineAssertions + + -- Finally, because testing lines we are unable + -- to detect a missing newline at the end of the + -- lyrics, we test the full song. + + it "matches full song" $ rhyme `shouldBe` lyrics where - expected = "This is the house that Jack built.\n\ - \\n\ - \This is the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the maiden all forlorn\n\ - \that milked the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the man all tattered and torn\n\ - \that kissed the maiden all forlorn\n\ - \that milked the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the priest all shaven and shorn\n\ - \that married the man all tattered and torn\n\ - \that kissed the maiden all forlorn\n\ - \that milked the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the rooster that crowed in the morn\n\ - \that woke the priest all shaven and shorn\n\ - \that married the man all tattered and torn\n\ - \that kissed the maiden all forlorn\n\ - \that milked the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the farmer sowing his corn\n\ - \that kept the rooster that crowed in the morn\n\ - \that woke the priest all shaven and shorn\n\ - \that married the man all tattered and torn\n\ - \that kissed the maiden all forlorn\n\ - \that milked the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \This is the horse and the hound and the horn\n\ - \that belonged to the farmer sowing his corn\n\ - \that kept the rooster that crowed in the morn\n\ - \that woke the priest all shaven and shorn\n\ - \that married the man all tattered and torn\n\ - \that kissed the maiden all forlorn\n\ - \that milked the cow with the crumpled horn\n\ - \that tossed the dog\n\ - \that worried the cat\n\ - \that killed the rat\n\ - \that ate the malt\n\ - \that lay in the house that Jack built.\n\ - \\n\ - \" + + lineAssertions = zipWith checkLine [1 :: Int ..] $ zipMaybe (lines rhyme) (lines lyrics) + + checkLine lineno (got, want) = + unless (got == want) $ + expectationFailure $ "mismatch at line " ++ show lineno ++ "\nexpected: " ++ show want ++ "\n but got: " ++ show got + + zipMaybe [] [] = [] + zipMaybe (x:xs) [] = (Just x , Nothing) : zipMaybe xs [] + zipMaybe [] (y:ys) = (Nothing, Just y ) : zipMaybe [] ys + zipMaybe (x:xs) (y:ys) = (Just x , Just y ) : zipMaybe xs ys + +-- Lyrics extracted from `exercism/x-common` on 2016-09-23. + +lyrics :: String +lyrics = "This is the house that Jack built.\n\ + \\n\ + \This is the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the rooster that crowed in the morn\n\ + \that woke the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the farmer sowing his corn\n\ + \that kept the rooster that crowed in the morn\n\ + \that woke the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n\ + \\n\ + \This is the horse and the hound and the horn\n\ + \that belonged to the farmer sowing his corn\n\ + \that kept the rooster that crowed in the morn\n\ + \that woke the priest all shaven and shorn\n\ + \that married the man all tattered and torn\n\ + \that kissed the maiden all forlorn\n\ + \that milked the cow with the crumpled horn\n\ + \that tossed the dog\n\ + \that worried the cat\n\ + \that killed the rat\n\ + \that ate the malt\n\ + \that lay in the house that Jack built.\n"