Skip to content

Instantly share code, notes, and snippets.

@rtfeldman
Created June 2, 2016 03:00
Show Gist options
  • Save rtfeldman/d773ff559c37eb96b1e513c4aefc5128 to your computer and use it in GitHub Desktop.
Save rtfeldman/d773ff559c37eb96b1e513c4aefc5128 to your computer and use it in GitHub Desktop.
module Script exposing (spec) --where
import ElmTest as Test exposing (onFail, test)
import Component.Util exposing (..)
import Html exposing (span, text)
import Dom exposing (htmlToString)
{-
Design principles:
* Tests are organized using modules, never string literals.
* Focus on reporting problems. Successes are noise.
* All tests should always run in parallel.
* Running a fuzz test instead of a static one should take barely any extra effort.
* A fuzz test that runs 200 iterations should be counted as 1 test, not 200.
Assume these functions exist:
onFail : String -> Test -> Test
batch : List Test -> Test
unit : List (() -> Test) -> Test
fuzz : Fuzzer a -> List (\a -> Test) -> Test
fuzz2 : Fuzzer a -> Fuzzer b -> List (\a b -> Test) -> Test
assertEqual : { expected : a, actual : a } -> Test
Sample CLI output:
3 of 12 TESTS FAILED:
| Component.UtilSpec
| oxfordify
✗ given an empty list, return an empty string
Expected: ""
Actual: "This sentence is empty."
| Component.UtilSpec
| oxfordify
✗ Test failed
Expected: "This sentence contains one item."
Actual: ""
| Component.UtilSpec
| oxfordifyWithHtml
✗ given a list of length 3, return an oxford-style sentence
Expected: "<span>This sentence contains <span>one item</span> <span> two
item</span><span>three item</span>.</span>"
Actual: "<span>This sentence contains <span>one item</span> <span> two
item</span>.</span>"
Sample BDD-style output: (created using the `it` and `describe` functions, below)
3 of 12 TESTS FAILED:
| Component.Util
| oxfordify
| given an empty list
✗ it returns an empty string
Expected: ""
Actual: "This sentence is empty."
| Component.Util
| oxfordify
| given one item
✗ it contains one item
Expected: "This sentence contains one item."
Actual: ""
| Component.Util
| oxfordifyWithHtml
| given a list of length 3
✗ it returns an oxford-style sentence
Expected: "<span>This sentence contains <span>one item</span> <span> two
item</span><span>three item</span>.</span>"
Actual: "<span>This sentence contains <span>one item</span> <span> two
item</span>.</span>"
-}
spec : Test
spec =
Test.batch
[ oxfordifySuite
, oxfordifyWithHtmlSuite
]
|> onFail "Component.UtilSpec"
{-| Prefix-style alternative to onFail
import Test.Bdd exposing (unit, it)
describe "spline reticulator"
(fuzz2 string string)
[ \str1 str2 ->
it "properly reticulates splines"
assertEqual
{ expected = foo
, actual = bar
}
]
-}
describe : String -> (a -> Test) -> a -> Test
describe description getTest getTestArg =
getTest getTestArg
|> onFail description
{-| Lets you write BDD-style assertions, e.g.
\arg1 arg2 ->
it "properly reticulates splines"
assertEqual
{ expected = arg1 ++ arg2
, actual = blah
}
-}
it : String -> (a -> Test) -> a -> Test
it description =
describe ("it " ++ description)
fuzzSuite : Test
fuzzSuite =
(Test.fuzz2 string string)
[ \name punctuation ->
{ expected = ""
, actual = oxfordify "This sentence is empty" "." []
}
|> assertEqual
|> onFail "given an empty list, return an empty string"
, \name punctuation ->
{ expected = "This sentence contains one item."
, actual = oxfordify "This sentence contains " "." ["one item"]
}
|> assertEqual
, \name punctuation ->
{ expected = "This sentence contains one item and two item."
, actual = oxfordify "This sentence contains " "." ["one item", "two item"]
}
|> assertEqual
|> onFail "given an empty list, return an empty string"
, \name punctuation ->
{ expected = "This sentence contains one item, two item, and three item."
, actual = oxfordify "This sentence contains " "." ["one item", "two item", "three item"]
}
|> assertEqual
|> onFail "given a list of length 3, return an oxford-style sentence"
]
|> onFail "oxfordify"
oxfordifySuite : Test
oxfordifySuite =
Test.unit
[ \_ ->
{ expected = ""
, actual = oxfordify "This sentence is empty" "." []
}
|> assertEqual
|> onFail "given an empty list, return an empty string"
, \_ ->
{ expected = "This sentence contains one item."
, actual = oxfordify "This sentence contains " "." ["one item"]
}
|> assertEqual
, \_ ->
{ expected = "This sentence contains one item and two item."
, actual = oxfordify "This sentence contains " "." ["one item", "two item"]
}
|> assertEqual
|> onFail "given an empty list, return an empty string"
, \_ ->
{ expected = "This sentence contains one item, two item, and three item."
, actual = oxfordify "This sentence contains " "." ["one item", "two item", "three item"]
}
|> assertEqual
|> onFail "given a list of length 3, return an oxford-style sentence"
]
|> onFail "oxfordify"
oxfordifyWithHtmlSuite : Test
oxfordifyWithHtmlSuite =
suite
[ \_ ->
{ expected = []
, actual = oxfordifyWithHtml "This sentence is empty" "." []
}
|> assertEqual
|> onFail "given an empty list, return an empty string"
, \_ ->
{ expected = [ "This sentence contains ", "one item", "."] |> textify |> spanify |> (span [])
, actual = defaultOxfordifyHtml [ "one item" ])
}
|> assertHtmlStringsEqual
|> onFail "given a list of length 1, return a list of html comprising a sentence"
, \_ ->
{ expected =
([ "This sentence contains ", "one item", " and ", "two item", "."]
|> textify |> spanify |> (span [])
)
, actual = defaultOxfordifyHtml ([ "one item", "two item" ])
}
|> assertHtmlStringsEqual
|> onFail "given a list of length 2, return a sentence with and-separation"
, \_ ->
{ expected =
([ "This sentence contains ", "one item", ", ", "two item", ", and ", "three item", "." ]
|> textify |> spanify |> (span [])
)
, actual = defaultOxfordifyHtml [ "one item", "two item", "three item" ]
}
|> assertHtmlStringsEqual
|> onFail "given a list of length 3, returns an oxford-style sentence"
]
|> onFail "oxfordifyWithHtml"
defaultOxfordifyHtml : List String -> Html.Html
defaultOxfordifyHtml listItems =
listItems
|> textify
|> spanify
|> oxfordifyWithHtml "This sentence contains " "."
|> span []
textify : List String -> List Html.Html
textify =
List.map (\contents -> text contents)
spanify : List Html.Html -> List Html.Html
spanify =
List.map (\contents -> span [] [ contents ])
assertHtmlStringsEqual : { expected : Html.Html, actual : Html.Html ) -> Test
assertHtmlStringsEqual { expected, actual } =
{ expected = htmlToString expected
, actual = htmlToString actual
}
|> assertEqual
|> onFail "html strings were not equal etc" -- optional...good idea?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment