Skip to content

Commit

Permalink
Fix code extractor to match elm-test-rs 2.x (#38)
Browse files Browse the repository at this point in the history
* Clean up elm.json dependencies.

Closes #34.

* Expand code parsing.

Solves #30.
The code extractor can now:
- Find test/describe inside of a let declaration
- Find test/describe pretty much anywhere (if, record, tuple...)
- Handle more than one top-level `Test`
- Find tests in arbitrarily nested describe
- Write test name as "describe name 1 > describe name 2 > ... > test name"

* Minimal changes to capture description hierarchy
  • Loading branch information
jiegillet authored Apr 12, 2022
1 parent 615b672 commit 0528d8e
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 82 deletions.
19 changes: 5 additions & 14 deletions extract-test-code/elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,19 @@
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
"elm/browser": "1.0.2",
"elm/core": "1.0.4",
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/core": "1.0.5",
"elm/json": "1.1.3",
"elm/parser": "1.1.0",
"elm/regex": "1.0.0",
"elm-community/string-extra": "4.0.1",
"ktonon/elm-test-extra": "2.0.1",
"stil4m/elm-syntax": "7.2.2",
"stil4m/elm-syntax": "7.2.9",
"stil4m/structured-writer": "1.0.3"
},
"indirect": {
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/html": "1.0.0",
"elm/random": "1.0.0",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.2",
"elm-community/list-extra": "8.2.4",
"elm-explorations/test": "1.2.2",
"elm-community/list-extra": "8.5.2",
"miniBill/elm-unicode": "1.0.2",
"rtfeldman/elm-hex": "1.0.0"
}
},
Expand Down
23 changes: 0 additions & 23 deletions extract-test-code/package.json

This file was deleted.

32 changes: 19 additions & 13 deletions extract-test-code/src/ExtractTestCode.elm
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,14 @@ extractFromFunction functionDeclaration =
-- We could instead require it to have a type annotation that specifies a
-- function with no parameters that returns a Test
if name == "tests" then
extractFromExpression expression
extractFromExpression [] expression

else
[]


extractFromExpression : Expression -> List ( String, Expression )
extractFromExpression expression =
extractFromExpression : List String -> Expression -> List ( String, Expression )
extractFromExpression descriptions expression =
case expression of
Application nodeExpressions ->
let
Expand All @@ -160,10 +160,10 @@ extractFromExpression expression =
case expressions of
(FunctionOrValue _ functionName) :: xs ->
if functionName == "describe" then
extractFromDescribeFunction xs
extractFromDescribeFunction descriptions xs

else if functionName == "test" then
extractFromTestFunction xs
extractFromTestFunction descriptions xs

else
[]
Expand All @@ -174,7 +174,7 @@ extractFromExpression expression =
OperatorApplication _ _ left right ->
case Node.value left of
Application nodeExpressions2 ->
extractFromExpression (Application (nodeExpressions2 ++ [ right ]))
extractFromExpression descriptions (Application (nodeExpressions2 ++ [ right ]))

_ ->
[]
Expand All @@ -187,11 +187,11 @@ extractFromExpression expression =
list (of tests or desribe functions, which return a Test)
parameter. We want to process this list
-}
extractFromDescribeFunction : List Expression -> List ( String, Expression )
extractFromDescribeFunction expressions =
extractFromDescribeFunction : List String -> List Expression -> List ( String, Expression )
extractFromDescribeFunction descriptions expressions =
case expressions of
_ :: (ListExpr testOrDescribes) :: [] ->
List.concatMap extractFromExpression (List.map Node.value testOrDescribes)
(Literal description) :: (ListExpr testOrDescribes) :: [] ->
List.concatMap (extractFromExpression (description :: descriptions)) (List.map Node.value testOrDescribes)

_ ->
[]
Expand All @@ -201,11 +201,17 @@ extractFromDescribeFunction expressions =
the test, and then a function for the test. Only lambdas are
supported as the second parameter
-}
extractFromTestFunction : List Expression -> List ( String, Expression )
extractFromTestFunction expressions =
extractFromTestFunction : List String -> List Expression -> List ( String, Expression )
extractFromTestFunction descriptions expressions =
case expressions of
(Literal name) :: (LambdaExpression test) :: [] ->
[ ( name, Node.value test.expression ) ]
[ ( (name :: descriptions)
|> List.reverse
|> List.drop 1
|> String.join " > "
, Node.value test.expression
)
]

_ ->
[]
80 changes: 62 additions & 18 deletions extract-test-code/tests/MultipleDescribesSingleTest.elm
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
module MultipleDescribesSingleTest exposing (..)

import Expect exposing (Expectation)
import Expect
import ExtractTestCode
import Json.Encode
import Test exposing (..)


tests : Test
tests =
test "Can extract tests in multiple describe wrappers" <|
\_ ->
"""module AnnalynsInfiltrationTests exposing (tests)
describe "Can extract tests in multiple describe wrappers"
[ test "Can extract tests with 2 describe layers" <|
\_ ->
"""module AnnalynsInfiltrationTests exposing (tests)
import Test exposing (..)
Expand Down Expand Up @@ -39,30 +40,73 @@ tests =
]
]
"""
|> ExtractTestCode.extractTestCode
|> Expect.equal
(Json.Encode.encode 2
(Json.Encode.list ExtractTestCode.encode
[ { name = "Cannot execute fast attack if knight is awake"
, testCode =
"""let
|> ExtractTestCode.extractTestCode
|> Expect.equal
(Json.Encode.encode 2
(Json.Encode.list ExtractTestCode.encode
[ { name = "AnnalynsInfiltration task 1 > Cannot execute fast attack if knight is awake"
, testCode =
"""let
knightIsAwake =
True
in
canFastAttack knightIsAwake |> Expect.equal False"""
}
, { name =
"Can execute fast attack if knight is sleeping"
, testCode = """let
}
, { name = "AnnalynsInfiltration task 2 > Can execute fast attack if knight is sleeping"
, testCode =
"""let
knightIsAwake =
False
in
canFastAttack knightIsAwake |> Expect.equal True"""
}
]
}
]
)
)
)
, test "Can extract tests with 4 describe layers" <|
\_ ->
"""module AnnalynsInfiltrationTests exposing (tests)
import Test exposing (..)
tests : Test
tests =
describe "AnnalynsInfiltration"
[ describe "layer 2"
[ describe "layer 3"
[ describe "layer 4"
[ test "Cannot execute fast attack if knight is awake" <|
\\_ ->
let
knightIsAwake =
True
in
canFastAttack knightIsAwake
|> Expect.equal False
]
]
]
]
"""
|> ExtractTestCode.extractTestCode
|> Expect.equal
(Json.Encode.encode 2
(Json.Encode.list ExtractTestCode.encode
[ { name = "layer 2 > layer 3 > layer 4 > Cannot execute fast attack if knight is awake"
, testCode =
"""let
knightIsAwake =
True
in
canFastAttack knightIsAwake |> Expect.equal False"""
}
]
)
)
]
2 changes: 1 addition & 1 deletion extract-test-code/tests/SingleDescribeMultipleTests.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module SingleDescribeMultipleTests exposing (..)

import Expect exposing (Expectation)
import Expect
import ExtractTestCode
import Json.Encode
import Test exposing (..)
Expand Down
28 changes: 15 additions & 13 deletions extract-test-code/tests/SingleDescribeSingleTest.elm
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
module SingleDescribeSingleTest exposing (..)

import Expect exposing (Expectation)
import Expect
import ExtractTestCode
import Json.Encode
import Test exposing (..)


tests : Test
tests =
test "Can extract single test in describe wrapper" <|
\_ ->
"""module AnnalynsInfiltrationTests exposing (tests)
describe "single tests in describe"
[ test "Can extract single test in describe wrapper" <|
\_ ->
"""module AnnalynsInfiltrationTests exposing (tests)
import Test exposing (..)
Expand All @@ -26,19 +27,20 @@ tests =
canFastAttack knightIsAwake
|> Expect.equal False
]"""
|> ExtractTestCode.extractTestCode
|> Expect.equal
(Json.Encode.encode 2
(Json.Encode.list ExtractTestCode.encode
[ { name = "Cannot execute fast attack if knight is awake"
, testCode = """let
|> ExtractTestCode.extractTestCode
|> Expect.equal
(Json.Encode.encode 2
(Json.Encode.list ExtractTestCode.encode
[ { name = "Cannot execute fast attack if knight is awake"
, testCode = """let
knightIsAwake =
True
in
canFastAttack knightIsAwake |> Expect.equal False"""
}
]
}
]
)
)
)
]

0 comments on commit 0528d8e

Please sign in to comment.