Making F# Test case methods public for unit testing with Nunit - f#

I'm using F# to write my test methods but Nunit complains that the methods are non public.
namespace Test
open NUnit.Framework
type public Test() =
[<Test>]
let testIt () =
Assert.AreEqual(10,10)
what do I need to change?

Since let bindings are private to the parent type, you have to use member instead:
namespace Test
open NUnit.Framework
[<TestFixture>]
type public Test() =
[<Test>]
member x.testIt() =
Assert.AreEqual(10, 10)
If you don't need complicated setups, using module-level let bindings directly should be preferable:
module Test
open NUnit.Framework
[<Test>]
let testIt() = Assert.AreEqual(10, 10)

You can put F# test cases in a module to make them public and visible to NUnit:
module Tests
open NUnit.Framework
let [<Test>] ``10 should equal 10`` () = Assert.AreEqual(10,10)

Related

How to run a Canopy test suite with xUnit?

I decided to use canopy framework to test my UI.
Most of the examples include either built-in assertion framework or Expecto. Which are both good choices yet I use xUnit everywhere else in the project and want to be uniform for now.
For xUnit I have found only this example but it contains just two very basic tests whereas I need to things like common code to run prior to all the tests. What would be an idiomatic way for canopy + xUnit?
xUnit has class fixtures and here is an example how to bring it to F# code.
Combining that with canopy scenarios, here is an example of what it can look like:
open canopy.classic
open canopy.types
open System
open Xunit
let private openApp() =
...
type Fixture() =
do
start ChromeHeadless
interface IDisposable with
member _.Dispose() =
quit()
type Tests() =
interface IClassFixture<Fixture>
[<Fact>]
member _.``Soundcheck - Server is online``() =
openApp()
[<Fact>]
member _.``Button1 is enabled``() =
openApp()
let button = element "#button1"
Assert.True button.Enabled
[<Fact>]
member _.``Button2 is disabled``() =
openApp()
let button = element "#button2"
Assert.False button.Enabled

Why Moq verify method call throws exception?

I can't get this piece of code to pass.
[<Test>]
member public this.Test() =
let mock = new Mock<IList<string>>()
let mockObj = mock.Object
mockObj.Add("aaa")
mock.Verify(fun m -> m.Add(It.IsAny<string>()), Times.Once())
Exception I get:
System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'
I believe it has something to do with F# not inferring properly the data type of labda expression but I don't know how to fix that.
You are correct, this an issue with F# type inference when calling an overloaded method that accepts either Action or Func.
One option is to download the Moq.FSharp.Extensions from Nuget and change your Verify to an explicit VerifyAction, i.e.
open Moq.FSharp.Extensions
type MyTests() =
[<Test>]
member public this.Test() =
let mock = new Mock<IList<string>>()
let mockObj = mock.Object
mockObj.Add("aaa")
mock.VerifyAction((fun m -> m.Add(any())), Times.Once())
Underneath the covers the Moq.FSharp.Extensions simply defines an extension method VerifyAction that only takes an Action to avoid ambiguity:
type Moq.Mock<'TAbstract> when 'TAbstract : not struct with
member mock.VerifyAction(expression:Expression<Action<'TAbstract>>) =
mock.Verify(expression)
Another option is to use Foq, a mocking library with a similar API to Moq but designed specifically for use from F#, also available via Nuget:
[<Test>]
member public this.Test() =
let mock = Mock.Of<IList<string>>()
mock.Add("aaa")
Mock.Verify(<# mock.Add(any()) #>, once)

Union type with interface in signature file

Given the following code int the implementation file:
namespace Lib
module Test =
type ITest =
abstract member IsTest: bool
type T = Test with
interface ITest with
member this.IsTest = true
let create () = Test
And the following signature file:
namespace Lib
module Test =
[<Interface>]
type ITest =
abstract member IsTest: bool
type T
val create: unit -> T
The following warning occurs:
Warning 2. The type implements the interface 'Test.ITest' but this is not revealed by the signature. You should list the interface in the signature, as the interface will be discoverable via dynamic type casts and/or reflection.
How should the signature of type T be changed in the signature file to conform to the implementation?
You should list the interfaces in the type definition inside the module signature (fsi) file, for example:
namespace Lib
module Test =
[<Interface>]
type ITest =
abstract member IsTest: bool
type T =
interface ITest
//you can list other interfaces here
val create: unit -> T
Note, there is no member listing when you specify the interfaces in the fsi files (we omitted the IsTest member when defining type T), the member listing should be part of the module implementation (fs) file.
Update
The above example is valid for F# 4.0. Since the OP tagged the question with the F#-3.0 tag, then the syntax for the older F# should be a little different -- in the fsi file instead of
type T = ...
use
type T with ...
this has to be changed as in the original example if you plan on upgrading to F# 4+. The compiler will display the relevant warnings for this change

Auto open a namespace in F#

Hi would like to know how to make the f# compiler to auto open a namespace automatically.
I have
namespace XXX
I have to add something here do(AutoOpen("XXX.YYY")) or something like that to make the XXX.YYY module to be opened when referencing the library from external projects.
[<AutoOpen>]
module YYY =
....
Thanks
In order to open a namespace/module without opening its parent first, you have to add the attribute on assembly level.
You can do this by adding an AssemblyInfo.fs file to your project:
In the case of the following code:
namespace Framework
module GlobalFunctions =
let Test () =
10.
You would for instance add the following code to AssemblyInfo.fs:
namespace Framework
[<assembly:AutoOpen("Framework.GlobalFunctions")>]
do()
And then you can call the code from a script (.fsx) file with:
#r #"C:\PathToAssembly\Assembly.dll"
let result = Test ()
Resulting in:
--> Referenced 'C:\PathToAssembly\Assembly.dll'
val result : float = 10.0
The AutoOpen attribute can be applied only to F# module, so you won't be able to add it to an entire namespace. However, since you can place all F# declarations inside a module, that may be enough for what you need. The syntax is:
[<AutoOpen>]
module MyGlobals =
// Declarations in the module
type Foo() =
member x.Bar = 10
When you reference the assembly, you should see Foo immediately. If the declaration is placed inside another namespace (i.e. MyLibrary), then you'll need to add open MyLibrary, but MyGlobals will be accessible automatically.

F#, namespaces, modules, fs and fsx

I'm aware of other questions about modules and namespaces in F#, but they're not helping me right now.
I've got a project with
Utilities.fs
namespace Company.Project.Namespace
module Utilities =
//stuff here
Functions.fs
namespace Company.Project.Namespace
open Utilities
module Functions =
//stuff here
And I'm trying to test them in an fsx:
#load "Utilities.fs"
#load "Functions.fs"
which gives me error FS0039: The namespace or module 'Utilities' is not defined when I try to send it to FSI with Alt-Enter.
I've tried adding same namespace at the top of the script file, but it doesn't like that.
What's weird is that the background compiler doesn't shout at me.
This seems to work, but is it the right approch?
#load "Utilities.fs"
open Company.Project.Namespace
#load "Functions.fs"
Is there a 'reference' FSharp project somewhere, which contains examples of how to integrate all this stuff: namespaces, modules, classes, script files, tests etc.?
I'm not an expert with FSI, but some experimentation suggests that namespaces are only supported by #load declarations (not via typical interactions - sending a namespace declaration group to VFSI via Alt-Enter does not work), and that different interactions contribute different 'instances'. For example, with the code file
namespace Foo
type Bar() =
member this.Qux() = printfn "hi"
namespace Other
type Whatever() = class end
namespace Foo
module M =
let bar = new Bar()
bar.Qux()
if I #load it more than once I get e.g.
> [Loading C:\Program.fs]
hi
namespace FSI_0002.Foo
type Bar =
class
new : unit -> Bar
member Qux : unit -> unit
end
namespace FSI_0002.Other
type Whatever =
class
new : unit -> Whatever
end
namespace FSI_0002.Foo
val bar : Bar
> #load #"C:\Program.fs";;
> [Loading C:\Program.fs]
hi
namespace FSI_0003.Foo
type Bar =
class
new : unit -> Bar
member Qux : unit -> unit
end
namespace FSI_0003.Other
type Whatever =
class
new : unit -> Whatever
end
namespace FSI_0003.Foo
val bar : Bar
> new Foo.Bar();;
> val it : Foo.Bar = FSI_0003.Foo.Bar
Note that it seems the FSI_0003.Foo.Bar shadowed the FSI_0002 version.
So I'm thinking the part of the F# spec that says
Within a namespace declaration group,
the namespace itself is implicitly
opened if any preceding namespace
declaration groups or referenced
assemblies contribute to this
namespace, e.g.
namespace MyCompany.MyLibrary
module Values1 =
let x = 1
namespace MyCompany.MyLibrary
// Implicit open of MyCompany.MyLibrary bringing Values1 into scope
module Values2 =
let x = Values1.x
However this only opens the namespace
as constituted by preceding namespace
declaration groups.
Does not interact with FSI, given FSI's limited understanding of namespaces. Specifically, I expect that the 'second #load' from your example opens e.g. FSI_000N+1's version of the namespace, whereas the prior code was in FSI_000N. Which maybe-explains why the explicit open interaction fixes it; you bring the existing, unshadowed FSI_000N stuff up to the top level before trying to (implicitly) reference it later.
I'm relatively new at this too, but this is what works for me when I'm testing in an fsx file:
#if INTERACTIVE
#r #"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsec.dll"
#r #"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsecCS.dll"
#endif
open FParsec.Primitives
open FParsec.CharParsers
followed by my code that uses these libraries.

Resources