F# UnitTesting function with side effect - unit-testing

I am C# dev that has just starting to learn F# and I have a few questions about unit testing. Let's say I want to the following code:
let input () = Console.In.ReadLine()
type MyType= {Name:string; Coordinate:Coordinate}
let readMyType =
input().Split(';')
|> fun x -> {Name=x.[1]; Coordinate = {
Longitude = float(x.[4].Replace(",","."))
Latitude =float(x.[5].Replace(",","."))
}}
As you can notice, there are a few points to take in consideration:
readMyType is calling input() with has a side effect.
readMyType assume many thing on the string read (contains ';' at least 6 columns, some columns are float with ',')
I think the way of doing this would be to:
inject the input() func as parameter
try to test what we are getting (pattern matching?)
Using NUnit as explained here
To be honest I'm just struggling to find an example that is showing me this, in order to learn the syntax and other best practices in F#. So if you could show me the path that would be very great.
Thanks in advance.

First, your function is not really a function. It's a value. The distinction between functions and values is syntactic: if you have any parameters, you're a function; otherwise - you're a value. The consequence of this distinction is very important in presence of side effects: values are computed only once, during initialization, and then never change, while functions are executed every time you call them.
For your specific example, this means that the following program:
let main _ =
readMyType
readMyType
readMyType
0
will ask the user for only one input, not three. Because readMyType is a value, it gets initialized once, at program start, and any subsequent reference to it just gets the pre-computed value, but doesn't execute the code over again.
Second, - yes, you're right: in order to test this function, you'd need to inject the input function as a parameter:
let readMyType (input: unit -> string) =
input().Split(';')
|> fun x -> {Name=x.[1]; Coordinate = {
Longitude = float(x.[4].Replace(",","."))
Latitude =float(x.[5].Replace(",","."))
}}
and then have the tests supply different inputs and check different outcomes:
let [<Test>] ``Successfully parses correctly formatted string``() =
let input() = "foo;the_name;bar;baz;1,23;4,56"
let result = readMyType input
result |> should equal { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } }
let [<Test>] ``Fails when the string does not have enough parts``() =
let input() = "foo"
(fun () -> readMyType input) |> shouldFail
// etc.
Put these tests in a separate project, add reference to your main project, then add test runner to your build script.
UPDATE
From your comments, I got the impression that you were seeking not only to test the function as it is (which follows from your original question), but also asking for advice on improving the function itself, so as to make it more safe and usable.
Yes, it is definitely better to check error conditions within the function, and return appropriate result. Unlike C#, however, it is usually better to avoid exceptions as control flow mechanism. Exceptions are for exceptional situations. For such situations that you would have never expected. That is why they are exceptions. But since the whole point of your function is parsing input, it stands to reason that invalid input is one of the normal conditions for it.
In F#, instead of throwing exceptions, you would usually return a result that indicates whether the operation was successful. For your function, the following type seems appropriate:
type ErrorMessage = string
type ParseResult = Success of MyType | Error of ErrorMessage
And then modify the function accordingly:
let parseMyType (input: string) =
let parts = input.Split [|';'|]
if parts.Length < 6
then
Error "Not enough parts"
else
Success
{ Name = parts.[0]
Coordinate = { Longitude = float(parts.[4].Replace(',','.')
Latitude = float(parts.[5].Replace(',','.') }
}
This function will return us either MyType wrapped in Success or an error message wrapped in Error, and we can check this in tests:
let [<Test>] ``Successfully parses correctly formatted string``() =
let input() = "foo;the_name;bar;baz;1,23;4,56"
let result = readMyType input
result |> should equal (Success { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } })
let [<Test>] ``Fails when the string does not have enough parts``() =
let input() = "foo"
let result = readMyType input
result |> should equal (Error "Not enough parts)
Note that, even though the code now checks for enough parts in the string, there are still other possible error conditions: for example, parts.[4] may be not a valid number.
I am not going to expand on this further, as that will make the answer way too long. I will only stop to mention two points:
Unlike C#, verifying all error conditions does not have to end up as a pyramid of doom. Validations can be nicely combined in a linear-looking way (see example below).
The F# 4.1 standard library already provides a type similar to ParseResult above, named Result<'t, 'e>.
For more on this approach, check out this wonderful post (and don't forget to explore all links from it, especially the video).
And here, I will leave you with an example of what your function could look like with full validation of everything (keep in mind though that this is not the cleanest version still):
let parseFloat (s: string) =
match System.Double.TryParse (s.Replace(',','.')) with
| true, x -> Ok x
| false, _ -> Error ("Not a number: " + s)
let split n (s:string) =
let parts = s.Split [|';'|]
if parts.Length < n then Error "Not enough parts"
else Ok parts
let parseMyType input =
input |> split 6 |> Result.bind (fun parts ->
parseFloat parts.[4] |> Result.bind (fun lgt ->
parseFloat parts.[5] |> Result.bind (fun lat ->
Ok { Name = parts.[1]; Coordinate = { Longitude = lgt; Latitude = lat } } )))
Usage:
> parseMyType "foo;name;bar;baz;1,23;4,56"
val it : Result<MyType,string> = Ok {Name = "name";
Coordinate = {Longitude = 1.23;
Latitude = 4.56;};}
> parseMyType "foo"
val it : Result<MyType,string> = Error "Not enough parts"
> parseMyType "foo;name;bar;baz;badnumber;4,56"
val it : Result<MyType,string> = Error "Not a number: badnumber"

This is a little follow-up to the excellent answer of #FyodorSoikin trying to explore the suggestion
keep in mind though that this is not the cleanest version still
Making the ParseResult generic
type ParseResult<'a> = Success of 'a | Error of ErrorMessage
type ResultType = ParseResult<Defibrillator> // see the Test Cases
we can define a builder
type Builder() =
member x.Bind(r :ParseResult<'a>, func : ('a -> ParseResult<'b>)) =
match r with
| Success m -> func m
| Error w -> Error w
member x.Return(value) = Success value
let builder = Builder()
so we get a concise notation:
let parse input =
builder {
let! parts = input |> split 6
let! lgt = parts.[4] |> parseFloat
let! lat = parts.[5] |> parseFloat
return { Name = parts.[1]; Coordinate = { Longitude = lgt; Latitude = lat } }
}
Test Cases
Tests are always fundamental
let [<Test>] ``3. Successfully parses correctly formatted string``() =
let input = "foo;the_name;bar;baz;1,23;4,56"
let result = parse input
result |> should equal (ResultType.Success { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } })
let [<Test>] ``3. Fails when the string does not have enough parts``() =
let input = "foo"
let result = parse input
result |> should equal (ResultType.Error "Not enough parts")
let [<Test>] ``3. Fails when the string does not contain a number``() =
let input = "foo;name;bar;baz;badnumber;4,56"
let result = parse input
result |> should equal (ResultType.Error "Not a number: badnumber")
Notice the usage of a specific ParseResult from the generic one.
minor note
Double.TryParse is just enough in the following
let parseFloat (s: string) =
match Double.TryParse s with
| true, x -> Success x
| false, _ -> Error ("Not a number: " + s)

Related

Testing functions returning option<T>

Consider unit-testing a module defining strings of constrained length as a type for representing user names:
module UserName
type T = UserName of string
let create (userName : string) =
if userName.Length >= 6 && userName.Length <= 16
then Some (UserName userName)
else None
let apply f (UserName userName) = f userName
let value userName = apply id userName
A unit test to ensure that the function returns None for an invalid input looks simple:
[<Fact>]
let ``UserName must have at least six characters`` () =
UserName.create "aaa" |> should equal None
However, a unit test for the case when the function returns Some appears to require an extra line for completeness of the match expression:
[<Fact>]
let ``Valid UserName`` () =
match UserName.create "validname" with
| Some result ->
UserName.value result |> should equal "validname"
| None -> Assert.True(false)
This does not look right to me, because my tests must define code for testing the "unhappy" path that must yield a failure anyway.
I wish I could write this instead
[<Fact>]
let ``Valid UserName`` () =
UserName.create "validname" |> should equal (Some (UserName "validname"))
but it does not compile (The value or constructor 'UserName' is not defined).
Is there a way to write a unit test of a function returning option<T> that does not require an explicit check of the "unhappy" path (e.g. | None -> Assert.True(false))? I am open to adding more types and/or functions to the UserName module to make it more testable.
Apply value to the inside of Some and then compare:
UserName.create "validname"
|> Option.map UserName.value
|> should equal (Some "validname")

How do you createRef in Suave Fable?

I have a text input, and I've managed to debounce input. However, my keypress listener won't wait for text input events to flush before processing the enter key which would end edits without getting the latest value in the uncontrolled component.
Since I'm in webpack, React... is undefined so I can't just React.createRef() The current source code shows the function exists https://github.com/fable-compiler/fable-react/blob/e904add886bab45003c074cd2b06b8834fddf65b/src/Fable.React.Helpers.fs#L366
However it doesn't resolve/compile.
paket.lock shows Fable.React 4.1.3, Fable.Elmish.React 2.1.
createRef is available only since version 5.x something so you need to update to latest version. To be sure, I encourage you to upgrade to the latest version at the time of writing 5.2.3.
This means you will need to upgrade your application to Fable.Core v3, you can read more about it here.
When done you can use createRef like that:
open Fable.React
open Fable.React.Props
type MapComponent(initProps) =
inherit Fable.React.Component<MapComponentProps, obj>(initProps)
let mapRef : IRefHook<Browser.Types.HTMLDivElement option> = createRef None
override this.render() =
div [ RefValue mapRef ]
[ str "..." ]
As it turned out, for what I needed, the ref wasn't necessary, however I did get one going.
type IReactRef =
inherit Browser.Element
[<Emit("React.createRef")>]
let createRef(): IReactRef = jsNative
type TextInputProps =
{ Ident: string
Delay: int
AddedAttributes: IHTMLProp list
DefaultValue: string option
OnChange: (string -> unit)
OnEscape: (unit -> unit) option
OnEnter: (string -> unit) option
}
type TextInputState = InputState
let textInputDelayDefault = 500
type TextInputComponent(props) =
inherit React.Component<TextInputProps, TextInputState>(props)
let mutable textInput: obj = null
let debouncer = Eventing.Debouncer<string>.Create props.Ident props.Delay
do
textInput <- react.createRef()
base.setInitState InputState
member __.TextInput: IReactRef option =
textInput
|> Option.ofObj
|> Option.map unbox
// provide cancel edit extension point (Escape doesn't fire keypress)
member this.OnKeyUp(e: React.KeyboardEvent) =
if e.key = "Escape" then
match this.props.OnEscape with
| Some f ->
e.preventDefault()
f()
| None -> ()
// provide finish edit extension point
member this.OnKeyPress(e: React.KeyboardEvent) =
let value =
e
|> unbox
|> Eventing.getTargetValue
if e.key = "Enter" then
this.props.OnEnter
|> Option.iter (fun f ->
e.preventDefault()
debouncer.Clear()
// send the current value in case the onChange did not send the current value due to debouncing
f value)
override this.render() =
let r =
input [ yield R.Props.Ref(unbox textInput)
yield R.Props.OnKeyPress this.OnKeyPress
yield R.Props.OnKeyUp this.OnKeyUp
yield Eventing.onDebChange debouncer this.props.OnChange
yield R.Props.DefaultValue(this.props.DefaultValue |> Option.defaultValue "")
yield! this.props.AddedAttributes ]
r
let inline textInputComponent props = Fable.Helpers.React.ofType<TextInputComponent, _, _> props []

Ocaml if-then-else Syntax Error

Why is this Ocaml statement giving me a syntax error?
let a = 0;; if a = 0 then let b = 0;;
Do if then else statements always have to return a value?
EDIT: Here is the code I am struggling with. I want to apply this function over a list with the map function. The function is supposed to look at each word in the list wordlist and add to the stringmap. If it has already been added to the string map then add 1 to its password.
module StringMap = Map.Make(String)
let wordcount = StringMap.empty
let findword testword =
let wordcount = (if (StringMap.mem testword wordcount)
then (StringMap.add testword ((StringMap.find testword wordcount)+1) wordcount)
else (StringMap.add testword 1 wordcount))
List.map findword wordlist
You can only have an if then without else if the then expression evaluates to unit () Otherwise, the expression will not type check. An if without an else is equivalent to writing if x then y else () which can only type check if y is unit.
Check this out for a reference.
(Terminology note: there are no statements in OCaml because everything is an expression, so the term "if statement" doesn't quite apply. I still understood what you meant, but I thought this was worth noting)
Yes, if is an expression in OCaml, not a statement. The best way to look at it is that there are no statements in OCaml. Everything is an expression. (Admittedly there are expressions that return (), which are similar to statements.)
You can only have if b then e if the type of e is unit (i.e., if it returns ()).
Note also that you can't just say let v = e, except at the top level of a module. At the top level it defines a global name in the module. In other cases you need to say let v = e1 in e2; the let defines a local symbol v for use in the expression e2.
One answer to the let b = problem - it works like this:
let a = 0
let b = if a = 0 then 0 else 1
(* or whatever value you need in the else branch *)
And then the Map problem: the manual says Map is applicative - that means Stringmap.add returns a new map. You must use a ref to store your map - see this ocaml toplevel protocol:
# module StringMap = Map.Make(String);;
# let mymap = ref StringMap.empty ;;
val mymap : '_a StringMap.t ref = {contents = <abstr>}
# mymap := StringMap.add "high" 1 !mymap;;
- : unit = ()
# StringMap.mem "high" !mymap;;
- : bool = true
# StringMap.mem "nono" !mymap;;
- : bool = false
# StringMap.find "high" !mymap;;
- : int = 1
# StringMap.find "nono" !mymap;;
Exception: Not_found.

What's the difference between "let ()=" and "let _=" ;

let () = Random.self_init();;
let _ = Random.self_init ();;
│- : unit = ()
It seems "let ()" returns nothing ?
Sincerely!
let is the keyword used to define new variables, like in the following construct:
let pattern = expr
For instance
let a = 2
assigns the value 2 to the name a. (Note this is not a way to assign a value to an already existing variable, but this is another topic).
But the pattern to the left of the = sign can be more than just a name. For instance
let (a,b) = (42,"foo")
defines both a and b, to be respectively 42 and "foo".
Of course, the types on both sides must match.
Which is the case here: both sides are of type int * string.
The expressions to the right of the = sign can also be elaborated, for instance
let foo =
let temp = String.make 10 'a' in
temp.[2] <- 'b';
temp
defines foo as the string "aabaaaaaaa". (As a side note, it also ensures that temp is local to this code snippet).
Now, let's use both: on the left, a pattern matching values of type unit, and on the right, an expression of type unit:
let () = Printf.printf "Hello world!\n"
Which explains the let () = construct.
Now, about the let _, one simply needs to know that _ can be used in a pattern as a wildcard: it matches values of any type and does not bind any name. For instance
let (a,_) = (42,"foo")
defines a as 42, and discards the value "foo". _ means "I know there is something here and I explicitly say I will not use it, so I don't name it". Here _ was used to match values of type string, but it can match value of any type, like int * string:
let _ = (42,"foo")
which does not define any variable and is not very useful. Such constructs are useful when the right hand side has side effects, like this:
let _ = Printf.printf "Hello world!\n"
which explains the second part of the question.
Practical purposes
Both are used and it's rather a matter of taste whether to use one or the other.
let () = is slightly safer as it has the compiler check that the right hand side is of type unit.
A value of any other type than unit is often a bug.
let _ = is slightly shorter (I've seen this argument). (Note that with an editor that automatically closes parenthesizes, the number of keystrokes is the same ;-)
I'm not an OCaml expert, although let me share something :)
The let in OCaml can represent two things:
The way you can assign variables;
The way you can declare functions or assign functions to names;
Using examples, you can see clearly how it works:
Assigning variables:
# let ten = 10;;
val ten : int = 10
# let hello_world_string = "Hello World";;
val hello_world_string : string = "Hello World"
Declaring functions:
# let sum a b = a+b;;
val sum : int -> int -> int = <fun>
# sum 2 3;;
- : int = 5
So, answering the question the difference between let ()= and let _= is:
At first example, you are declaring a function that doesn't have name, parameters nor instructions that should output an unit. The second example, you aren't assigning to _, that is OCaml's wildcard, any value.
As we can see below, we can define a function, that will be executed immediatly because we won't be able to call it anymore:
# let () = print_string "Hello";;
Hello
Or assign to OCaml's wildcard a type and value, or a function:
# let _ = 10;;
- : int = 10
# let _ = print_string "Maybe I answered your question :) ";;
Maybe I answered your question :) - : unit = ()

F# Active Pattern List.filter or equivalent

I have a records of types
type tradeLeg = {
id : int ;
tradeId : int ;
legActivity : LegActivityType ;
actedOn : DateTime ;
estimates : legComponents ;
entryType : ShareOrDollarBased ;
confirmedPrice: DollarsPerShare option;
actuals : legComponents option ;
type trade = {
id : int ;
securityId : int ;
ricCode : string ;
tradeActivity : TradeType ;
enteredOn : DateTime ;
closedOn : DateTime ;
tradeLegs : tradeLeg list ;
}
Obviously the tradeLegs are a type off of a trade. A leg may be settled or unsettled (or unsettled but price confirmed) - thus I have defined the active pattern:
let (|LegIsSettled|LegIsConfirmed|LegIsUnsettled|) (l: tradeLeg) =
if Helper.exists l.actuals then LegIsSettled
elif Helper.exists l.confirmedPrice then LegIsConfirmed
else LegIsUnsettled
and then to determine if a trade is settled (based on all legs matching LegIsSettled pattern:
let (|TradeIsSettled|TradeIsUnsettled|) (t: trade) =
if List.exists (
fun l ->
match l with
| LegIsSettled -> false
| _ -> true) t.tradeLegs then TradeIsSettled
else TradeIsUnsettled
I can see some advantages of this use of active patterns, however i would think there is a more efficient way to see if any item of a list either matches (or doesn't) an actie pattern without having to write a lambda expression specifically for it, and using List.exist.
Question is two fold:
is there a more concise way to express this?
is there a way to abstract the functionality / expression
(fun l ->
match l with
| LegIsSettled -> false
| _ -> true)
Such that
let itemMatchesPattern pattern item =
match item with
| pattern -> true
| _ -> false
such I could write (as I am reusing this design-pattern):
let curriedItemMatchesPattern = itemMatchesPattern LegIsSettled
if List.exists curriedItemMatchesPattern t.tradeLegs then TradeIsSettled
else TradeIsUnsettled
Thoughts?
To answer your question about active patterns, let me use a simpler example:
let (|Odd|Even|) n =
if n % 2 = 0 then Even else Odd
When you declare a pattern that has multiple options using (|Odd|Even|), then the compiler understands it as a function that returns a value of type Choice<unit, unit>. So, the active pattern that you can work with is the whole combination |Odd|Even| and not just two constructs that you could use independently (such as |Odd| and |Even|).
It is possible to treat active patterns as first class functions, but if you're using patterns with multiple options, you cannot do much with it:
let pattern = (|Odd|Even|);;
val pattern : int -> Choice
You can write function that tests whether a value matches a specified pattern, but you'd need a lot of functions (because there are many Choice types overloaded by the number of type parameters):
let is1Of2 pattern item =
match pattern item with
| Choice1Of2 _ -> true
| _ -> false
> is1Of2 (|Odd|Even|) 1
val it : true
Something like this would work in your case, but it is far from being perfect.
You can do a little better job if you declare multiple partial active patterns (but then you of course loose some nice aspects of full active patterns such as completeness checking):
let (|Odd|_|) n =
if n % 2 = 0 then None else Some()
let (|Even|_|) n =
if n % 2 = 0 then Some() else None
Now you can write a function that checks whether a value matches pattern:
let matches pattern value =
match pattern value with
| Some _ -> true
| None -> false
> matches (|Odd|_|) 1;;
val it : bool = true
> matches (|Even|_|) 2;;
val it : bool = true
Summary While there may be some more or less elegant way to achieve what you need, I'd probably consider whether active patterns give you any big advantage over using standard functions. It may be a better idea to implenent the code using functions first and then decide which of the constructs would be useful as active patterns and add active patterns later. In this case, the usual code wouldn't look much worse:
type LegResult = LegIsSettled | LegIsConfirmed | LegIsUnsettled
let getLegStatus (l: tradeLeg) =
if Helper.exists l.actuals then LegIsSettled
elif Helper.exists l.confirmedPrice then LegIsConfirmed
else LegIsUnsettled
// Later in the code you would use pattern matching
match getLegStatus trade with
| LegIsSettled -> // ...
| LegIsUnSettled -> // ...
// But you can still use higher-order functions too
trades |> List.exist (fun t -> getLegStatus t = LegIsSettled)
// Which can be rewritten (if you like point-free style):
trades |> List.exist (getLegStatus >> ((=) LegIsSettled))
// Or you can write helper function (which is more readable):
let legStatusIs check trade = getLegStatus trade = check
trades |> List.exist (legStatusIs LegIsSettled)
In addition to Tomas's points on the actual details of active patterns, note that you can always shorten fun x -> match x with |... to function | ..., which will save a few keystrokes as well as the need to make up a potentially meaningless identifier.