Skip to content

Commit

Permalink
Fix correct Error handling 🐛 + change output to just exitcode + print
Browse files Browse the repository at this point in the history
  • Loading branch information
Freymaurer committed Nov 20, 2023
1 parent 7efcb5e commit f29c1ee
Showing 1 changed file with 36 additions and 31 deletions.
67 changes: 36 additions & 31 deletions src/Pyxpecto.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type TestCase =
| TestList of string * TestCase list
| TestListSequential of string * TestCase list

exception ExpectError of exn
type AssertException(msg) = inherit Exception(msg)

type Accuracy = { absolute: float; relative: float }

Expand Down Expand Up @@ -49,6 +49,11 @@ module BColors =
[<Emit("'\\033[0m'")>]
let ENDC : string = ""

module Helper =
let expectError (str:string) = AssertException str |> raise

open Helper

[<AutoOpen>]
module Test =
let testCase name body = SyncTest(name, body, Normal)
Expand Down Expand Up @@ -126,7 +131,7 @@ module Expect =
let errorMsg =
$" Expected: {BColors.OKCYAN}{expected}{BColors.ENDC} \n\b Actual: {BColors.FAIL}{actual}{BColors.ENDC} \n\b Message: {msg}"

raise (ExpectError(failwith errorMsg))
expectError(errorMsg)
let notEqual actual expected msg : unit =
Assert.NotEqual(actual, expected, msg)
let private isNull' cond =
Expand All @@ -135,68 +140,68 @@ module Expect =
| _ -> false
let isNull cond = equal (isNull' cond) true
let isNotNull cond = notEqual (isNull' cond) true
let isNotNaN cond msg = if Double.IsNaN cond then raise <| ExpectError(failwith msg)
let isNotInfinity cond msg = if Double.IsInfinity cond then raise <| ExpectError(failwith msg)
let isNotNaN cond msg = if Double.IsNaN cond then expectError(msg)
let isNotInfinity cond msg = if Double.IsInfinity cond then expectError(msg)
let isTrue cond = equal cond true
let isFalse cond = equal cond false
let isZero cond = equal cond 0
let isEmpty (x: 'a seq) msg = if not (Seq.isEmpty x) then raise <| ExpectError(failwithf "%s. Should be empty." msg)
let isEmpty (x: 'a seq) msg = if not (Seq.isEmpty x) then expectError(sprintf "%s. Should be empty." msg)
let pass() = equal true true "The test passed"
let passWithMsg (message: string) = equal true true message
let exists (x: 'a seq) (a: 'a -> bool) msg = if not (Seq.exists a x) then raise <| ExpectError(failwith msg)
let all (x: 'a seq) (a: 'a -> bool) msg = if not (Seq.forall a x) then raise <| ExpectError(failwith msg)
let exists (x: 'a seq) (a: 'a -> bool) msg = if not (Seq.exists a x) then expectError(msg)
let all (x: 'a seq) (a: 'a -> bool) msg = if not (Seq.forall a x) then expectError(msg)
/// Expect the passed sequence not to be empty.
let isNonEmpty (x: 'a seq) msg = if Seq.isEmpty x then raise <| ExpectError(failwithf "%s. Should not be empty." msg)
let isNonEmpty (x: 'a seq) msg = if Seq.isEmpty x then expectError(sprintf "%s. Should not be empty." msg)
/// Expects x to be not null nor empty
let isNotEmpty (x: 'a seq) msg =
isNotNull x msg
isNonEmpty x msg
/// Expects x to be a sequence of length `number`
let hasLength x number msg = equal (Seq.length x) number (failwithf "%s. Expected %A to have length %i" msg x number)
let hasLength x number msg = equal (Seq.length x) number (sprintf "%s. Expected %A to have length %i" msg x number)
/// Expects x to be Result.Ok
let isOk x message =
match x with
| Ok _ -> passWithMsg message
| Error x' -> raise <| ExpectError(failwithf "%s. Expected Ok, was Error(\"%A\")." message x')
| Error x' -> expectError(sprintf "%s. Expected Ok, was Error(\"%A\")." message x')
/// Expects the value to be a Result.Ok value and returns it or fails the test
let wantOk x message =
match x with
| Ok x' ->
passWithMsg message
x'
| Error x' -> raise <| ExpectError(failwithf "%s. Expected Ok, was Error(\"%A\")." message x')
| Error x' -> expectError(sprintf "%s. Expected Ok, was Error(\"%A\")." message x')
let stringContains (subject: string) (substring: string) message =
if not (subject.Contains(substring))
then raise <| ExpectError(failwithf "%s. Expected subject string '%s' to contain substring '%s'." message subject substring)
then expectError(sprintf "%s. Expected subject string '%s' to contain substring '%s'." message subject substring)
else passWithMsg message

/// Expects x to be Result.Error
let isError x message =
match x with
| Error _ -> passWithMsg message
| Ok x' -> raise <| ExpectError(failwithf "%s. Expected Error _, was Ok(%A)." message x')
| Ok x' -> expectError(sprintf "%s. Expected Error _, was Ok(%A)." message x')
let isSome x message =
match x with
| Some _ -> passWithMsg message
| None -> raise <| ExpectError(failwithf "%s. Expected Some _, was None." message)
| None -> expectError(sprintf "%s. Expected Some _, was None." message)
/// Expects the value to be a Some x value and returns x or fails the test
let wantSome x message =
match x with
| Some x' ->
passWithMsg message
x'
| None -> raise <| ExpectError(failwithf "%s. Expected Some _, was None." message)
| None -> expectError(sprintf "%s. Expected Some _, was None." message)
/// Expects the value to be a Result.Error value and returns it or fails the test
let wantError (x: Result<'a, 'b>) (message: string) =
match x with
| Error value ->
passWithMsg message
value
| Ok value -> raise <| ExpectError(failwithf "%s. Expected Error _, was Ok(%A)." message value)
| Ok value -> expectError(sprintf "%s. Expected Error _, was Ok(%A)." message value)
let isNone x message =
match x with
| None -> passWithMsg message
| Some x' -> raise <| ExpectError(failwithf "%s. Expected None, was Some(%A)." message x')
| Some x' -> expectError(sprintf "%s. Expected None, was Some(%A)." message x')
let private throws' f =
try f ()
None
Expand All @@ -205,12 +210,12 @@ module Expect =
/// Expects the passed function to throw an exception
let throws f msg =
match throws' f with
| None -> raise <| ExpectError(failwithf "%s. Expected f to throw." msg)
| None -> expectError(sprintf "%s. Expected f to throw." msg)
| Some _ -> ()
/// Expects the passed function to throw, then calls `cont` with the exception
let throwsC f cont =
match throws' f with
| None -> raise <| ExpectError(failwithf "Expected f to throw.")
| None -> expectError(sprintf "Expected f to throw.")
| Some exn -> cont exn

/// Expects the `actual` sequence to contain all elements from `expected`
Expand All @@ -232,30 +237,30 @@ module Expect =
if List.isEmpty missingEls then
()
else
failwithf
sprintf
"%s. Sequence `actual` does not contain all `expected` elements. Missing elements from `actual`: %A. Extra elements in `actual`: %A"
message
missingEls
extraEls
|> ExpectError |> raise
|> expectError

/// Expects `actual` and `expected` (that are both floats) to be within a
/// given `accuracy`.
let floatClose accuracy actual expected message =
if Double.IsInfinity actual then
failwithf "%s. Expected actual to not be infinity, but it was." message
|> ExpectError |> raise
sprintf "%s. Expected actual to not be infinity, but it was." message
|> expectError
elif Double.IsInfinity expected then
failwithf "%s. Expected expected to not be infinity, but it was." message
|> ExpectError |> raise
sprintf "%s. Expected expected to not be infinity, but it was." message
|> expectError
elif Accuracy.areClose accuracy actual expected |> not then
failwithf "%s. Expected difference to be less than %.20g for accuracy {absolute=%.20g; relative=%.20g}, but was %.20g. actual=%.20g expected=%.20g"
sprintf "%s. Expected difference to be less than %.20g for accuracy {absolute=%.20g; relative=%.20g}, but was %.20g. actual=%.20g expected=%.20g"
message
(Accuracy.areCloseRhs accuracy actual expected)
accuracy.absolute accuracy.relative
(Accuracy.areCloseLhs actual expected)
actual expected
|> ExpectError |> raise
|> expectError

/// Expects `actual` to be less than `expected` or to be within a
/// given `accuracy`.
Expand Down Expand Up @@ -359,7 +364,7 @@ module Pyxpecto =
body()
this.printSuccessMsg name
with
| :? ExpectError as exn ->
| :? AssertException as exn ->
this.printErrorMsg name exn.Message false
| e ->
this.printErrorMsg name e.Message true
Expand All @@ -372,7 +377,7 @@ module Pyxpecto =
}
|> Async.RunSynchronously
with
| ExpectError(exn) ->
| :? AssertException as exn ->
this.printErrorMsg name exn.Message false
| e ->
this.printErrorMsg name e.Message true
Expand Down Expand Up @@ -420,10 +425,10 @@ module Pyxpecto =
printfn "%s" msg
match runner.ErrorTests, runner.FailedTests with
| errors,_ when errors > 0 ->
Exception($"{BColors.FAIL}❌ Exited with error code 2{BColors.ENDC}") |> raise
Exception($"{BColors.FAIL}❌ Exited with error code 2{BColors.ENDC}") |> printfn "%A"
2
| _,failed when failed > 0 ->
Exception($"{BColors.FAIL}❌ Exited with error code 1{BColors.ENDC}") |> raise
Exception($"{BColors.FAIL}❌ Exited with error code 1{BColors.ENDC}") |> printfn "%A"
1
| _ ->
printfn $"{BColors.OKGREEN}Success!{BColors.ENDC}"
Expand Down

0 comments on commit f29c1ee

Please sign in to comment.