Skip to content

Commit

Permalink
Move from test-unit to spec
Browse files Browse the repository at this point in the history
The migration is rather straightforward, but it brings a HUGE decrease
in the time required to run tests as determined by
`hyperfine --warmup 2 'npm test'`. Before:

Benchmark 1: npm test
  Time (mean ± σ):     71.245 s ±  0.619 s    [User: 75.323 s, System: 0.868 s]
  Range (min … max):   70.245 s … 72.363 s    10 runs

After:

Benchmark 1: npm test
  Time (mean ± σ):     18.666 s ±  0.256 s    [User: 22.082 s, System: 0.671 s]
  Range (min … max):   18.327 s … 19.048 s    10 runs
  • Loading branch information
triallax committed Jun 10, 2023
1 parent 351e90b commit 5e4f34f
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 32 deletions.
2 changes: 1 addition & 1 deletion test.dhall
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
let conf = ./spago.dhall
in conf // {
sources = conf.sources # [ "test/**/*.purs" ]
, dependencies = conf.dependencies # ["aff", "effect", "test-unit"]
, dependencies = conf.dependencies # ["aff", "effect", "spec"]
}
65 changes: 34 additions & 31 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Test.Main (main) where
import Prelude hiding (degree)

import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Aff (Aff, launchAff_)

import Data.Decimal (fromNumber)
import Data.Either (Either(..))
Expand All @@ -12,9 +12,10 @@ import Data.List (List(..), (:))
import Data.NonEmpty ((:|))
import Data.Map (insert, keys)

import Test.Unit (suite, test, failure)
import Test.Unit.Assert (equal)
import Test.Unit.Main (runTest)
import Test.Spec (describe, it)
import Test.Spec.Assertions (shouldEqual, fail)
import Test.Spec.Reporter (consoleReporter)
import Test.Spec.Runner (runSpec)

import Parsing (Position(..), parseErrorMessage, parseErrorPosition)

Expand All @@ -37,16 +38,16 @@ shouldParseAs expected input =
Left err →
case parseErrorPosition err of
Position pos →
failure $ "Parse error for input '" <> input <> "': "
fail $ "Parse error for input '" <> input <> "': "
<> parseErrorMessage err
<> " at position "
<> show pos.column
Right output →
unless (output == expected) do
failure $ "Unexpected result:\n" <>
"Input: '" <> input <> "'\n" <>
"Output: " <> show output <> "\n" <>
"Expected: " <> show expected <> "\n"
fail $ "Unexpected result:\n" <>
"Input: '" <> input <> "'\n" <>
"Output: " <> show output <> "\n" <>
"Expected: " <> show expected <> "\n"

allParseAs Statement Array String Aff Unit
allParseAs expected = traverse_ (shouldParseAs expected)
Expand All @@ -55,42 +56,44 @@ shouldFail ∷ String → Aff Unit
shouldFail input =
case parseInsect initialEnvironment input of
Left _ → pure unit
Right _ → failure $ "input is expected to throw a parse error: '" <> input <> "'"
Right _ → fail $ "input is expected to throw a parse error: '" <> input <> "'"

expectOutput Environment String String Aff Unit
expectOutput env expected inp =
let { msg: out } = repl fmtPlain env inp
in
unless (out == expected) do
failure $ "Unexpected result:\n" <>
"Input: '" <> inp <> "'\n" <>
"Output: '" <> out <> "'\n" <>
"Expected: '" <> expected <> "'\n"
fail $ "Unexpected result:\n" <>
"Input: '" <> inp <> "'\n" <>
"Output: '" <> out <> "'\n" <>
"Expected: '" <> expected <> "'\n"

prettyPrintCheck String Aff Unit
prettyPrintCheck input =
case parseInsect initialEnvironment input of
Left err →
case parseErrorPosition err of
Position pos →
failure $ "Parse error for input '" <> input <> "': "
fail $ "Parse error for input '" <> input <> "': "
<> parseErrorMessage err
<> " at position "
<> show pos.column
Right output@(Expression expr) →
shouldParseAs output (format fmtPlain (pretty expr))
_ → failure "Input is not an expression"

_ → fail "Input is not an expression"

main Effect Unit
main = runTest do
main = launchAff_ $ runSpec [consoleReporter] do
-- Helper to construct scalars
let scalar n = Scalar (fromNumber n)

-- Helper to construct quantities
let q s u = BinOp Mul (scalar s) (Unit u)

suite "Parser - Numbers" do
-- The way we use it, `test` makes more sense than `it`.
let test = it

describe "Parser - Numbers" do
test "Simple numbers" do
allParseAs (Expression (scalar 1.0))
[ "1"
Expand Down Expand Up @@ -194,7 +197,7 @@ main = runTest do
shouldFail "0x1p-"
shouldFail "0x5.."

suite "Parser - Units (this may take some time)" do
describe "Parser - Units (this may take some time)" do
test "Simple" do
allParseAs (Expression (Unit meter))
[ "m"
Expand Down Expand Up @@ -252,7 +255,7 @@ main = runTest do
]


suite "Parser - Quantities" do
describe "Parser - Quantities" do
test "Simple" do
allParseAs (Expression (q 2.3 meter))
[ "2.3*m"
Expand Down Expand Up @@ -358,7 +361,7 @@ main = runTest do
, "2.30km per h"
]

suite "Parser - Operators" do
describe "Parser - Operators" do
test "Factorial" do
allParseAs (Expression (Factorial (scalar 4.0)))
[ "4!"
Expand Down Expand Up @@ -629,7 +632,7 @@ main = runTest do
, "metre^(-1.0)"
]

suite "Parser - Conversions" do
describe "Parser - Conversions" do
test "Simple" do
allParseAs (Expression (BinOp ConvertTo (q (2.3) meter) (Unit inch)))
[ "2.3m -> in"
Expand Down Expand Up @@ -664,7 +667,7 @@ main = runTest do
, " 36km / hour->mph "
]

suite "Parser - Identifiers" do
describe "Parser - Identifiers" do
test "Valid and invalid names" do
shouldParseAs (Expression (Variable "x")) "x"
shouldParseAs (Expression (Variable "µ")) "µ"
Expand Down Expand Up @@ -723,7 +726,7 @@ main = runTest do
for_ (keys initialEnvironment.values) \ident →
shouldParseAs (Expression (Variable ident)) ident

suite "Parser - Functions" do
describe "Parser - Functions" do
test "Simple" do
allParseAs (Expression (Apply "sin" (q 30.0 degree :| Nil)))
[ "sin(30°)"
Expand Down Expand Up @@ -762,7 +765,7 @@ main = runTest do
-- evaluated line.
let reservedNames = ["m", "meter", "kg", "kilogram", "list", "ans", "_"]

suite "Parser - Variable Assignments" do
describe "Parser - Variable Assignments" do
test "Simple" do
allParseAs (VariableAssignment "xyz_123" (scalar 1.0))
[ "xyz_123 = 1"
Expand All @@ -780,7 +783,7 @@ main = runTest do
test "Reserved names" do
for_ reservedNames \name -> shouldFail (name <> "=2")

suite "Parser - Function Assignments" do
describe "Parser - Function Assignments" do
test "Simple" do
allParseAs (FunctionAssignment "xyz_123" ("x" :| Nil) (scalar 1.0))
[ "xyz_123(x) = 1"
Expand All @@ -802,7 +805,7 @@ main = runTest do
test "Reserved names" do
for_ reservedNames \name -> shouldFail (name <> "(x)=2")

suite "Parser - Pretty print function" do
describe "Parser - Pretty print function" do
test "Simple" do
allParseAs (PrettyPrintFunction "cos")
[ "cos"
Expand All @@ -816,9 +819,9 @@ main = runTest do
_ → "Error"

let equalPretty out inp =
equal out (pretty' inp)
out `shouldEqual` (pretty' inp)

suite "Pretty printer" do
describe "Pretty printer" do
test "Consistency" do
prettyPrintCheck "-2.3e-12387"
prettyPrintCheck "2.3e-12387"
Expand Down Expand Up @@ -884,7 +887,7 @@ main = runTest do

let expectOutput' = expectOutput initialEnvironment

suite "Integration tests" do
describe "Integration tests" do
test "Simple input" do
expectOutput' "3 m" "3m"
expectOutput' "3 m" " 3.0 meter "
Expand Down

0 comments on commit 5e4f34f

Please sign in to comment.