Let's say we have a class
type ThisClassIsComplicated () =
let calculateSomething a b =
a + b
In this case calculateSomething is trivial, but if it would be more complicated it may make sense to verify that the calculations done there are correct.
It might make sense to use a unit testing framework to test that private methods.
My question: how to unit test private methods in F#?
Some random thoughts:
The selected answer here, suggests to use the InternalsVisibleTo attribute which anyway is applicable only to internalmethods.
What is the route specific to F# if any? Is this better in a F# design?
let calculateSomething a b = a + b
type ThisClassIsComplicated () =
member this.Calculate a b = calculateSomething a b
Maybe the scope of calculateSomething could be even narrowed down by having a nested module.
If you feel like your code is too complicated to test it from the outside, use the latter option. And in case you want to test an inner function like
let myComplicatedOperation input =
let calculateSomething a b =
a + b
calculateSomething (fst input) (snd input)
you can always rewrite it with currying like this:
let myComplicatedOperation calculateSomething input =
calculateSomething (fst input) (snd input)
Your question does not seem to be directly related to F# though. The general way to test private methods is typically by extracting a class (or, in F#, you can also just extract a let bound function). And making your testee public on that other class / function.
I think that loosening access restrictions in a class/module to facilitate testing is often a bad idea. If you have decided something is irrelevant to know for the outside world, you wanting to test it doesn't make it any less irrelevant.
Can't you just have a public method/function in your class/module that does the testing?
type ThisClassIsComplicated () =
let calculateSomething a b =
a + b
member private this.TestInstance () =
printfn "%A" <| calculateSomething 1 2
static member Test () =
(new ThisClassIsComplicated()).TestInstance()
You can use Impromptu Interface to invoke private methods.
For example, I test the function calcNodeLabel at
https://code.google.com/p/fseye/source/browse/trunk/FsEye/Forms/WatchTreeView.fs#73 like so: https://code.google.com/p/fseye/source/browse/trunk/Test.FsEye/WatchTreeViewLabelCalculatorTests.fs#54
But you need to be careful testing hidden functions in F#: it's an implementation detail of the compiler how the function will actually be compiled (e.g. as a method, as a delegate, as a ...).
Folks will warn generally against testing private methods, but I think it is a bit simplistic to say "never test private methods", since such a declaration takes for granted that access levels as specified in the .NET framework are the only way they could be.
For example, calcNodeLabel in my example should indeed be hidden from the great wide world, but I would consider it part of the internal contract of the class. Of course, you could argue that the class view data and the view itself should be separated, but the point stands: all models are imperfect!
Related
I have written an Azure durable function in F# and am trying to write unit tests, following the guidelines at https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-unit-testing. I have attempted to use Foq to create a mock instance of the abstract class DurableOrchestrationContextBase, but that fails with the following error:
System.TypeLoadException : Method 'set_InstanceId' on type 'Mock.DurableOrchestrationContextBase1953fcc2-be15-41fc-850c-5a5813aace89' from assembly 'Foq.Dynamic, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is overriding a method that is not visible from that assembly.
The error relates to this property:
public virtual string InstanceId { get; internal set; }
Further investigation shows that Foq is able to mock non-virtual, non-abstract properties with internal setters on abstract C# classes, but can't cope with such properties if they are virtual.
Is there any way to mock such a class in an F# test? Rolling my own implementation would be awkward in this case, as DurableOrchestrationContextBase is a large class with many members that would need implementing.
In the end I worked around this issue by switching to NSubstitute, which is capable of mocking this kind of class. NSubstitute's API is relatively easy to use from F#, since (unlike in Moq, for example) you can configure most scenarios without resorting to expression trees, especially if you can leverage structural equality for verifying arguments. For example:
let returns<'T> (value: 'T) x = x.Returns(value) |> ignore
[<Fact>]
let ``should call my activity``() =
task {
// Arrange
let context = Substitute.For<DurableOrchestrationContextBase>()
context.GetInput<SomeType>() |> returns { Foo = 42 }
// Act
do! runOrchestrator context
// Assert
// In C# you would have to do Arg.Is<SomeClass>(x => x.Bar == 43 && x.Baz == "bla")
do! context.Received().CallActivityAsync("MyActivity", { Bar = 43; Baz = "bla" })
}
Take the following F# example:
let parse mapDate mapLevel mapMessge (groups : string list) =
{
DateTime =
mapDate(
groups.[2] |> Int32.Parse,
groups.[0] |> Int32.Parse,
groups.[1] |> Int32.Parse)
Level = mapLevel groups.[3]
Message = mapMessge groups.[4]
}
I can unit test the map functions independently that's ok, but how do I unit test that this function calls the functions passed in as arguments correctly?
In C# I would use mocks and verify the calls to them. I recently watched a pluralsight video that talked about how functional languages tend to use stubs instead of mocks. Here I could pass in a function that throws if it doesn't get the expected arguments but I'm not really sold on this approach.
I was just wondering if there were any patterns in functional programming in general for unit testing higher-order functions like this?
Well, let me disagree with given answer. Actually, there is a nice way to test higher order functions without even bothering about concrete types they might take (I consider typical HOF to be totally generic, however there is no difference: approach I suggest will work with more strict HFO rightly).
Let's take something really simple, something everyone is familiar with. How about ['t] -> ['t] function? It takes a single argument - a list of whatever type and returns list of the same type. Traditional OOP approach wouldn't work here: one need's to put a restriction on 't and test somewhat specific parameters of that type; the only way to make author to feel more confident with his implementation, is to increase unit tests numbers.
There is really great stuff named "category theory" in math. It's comparatively new filed of mathematics and studies things from the outside rather from than inside. In order to be able to describe things "from the outside" you need take a thing you're interested in and force it to interact with something you already know deep enough. Thus, category theory teaches to describe things in terms of their interrelations with other things. Can't we do the same here?..
Indeed, we can. That's actually quite easy: we got a f : ['t] -> ['t] already, but is there anything else such that we could make both interact and define something common - something that holds for each and every interaction regardless of any other factors? Let's take any g: 't -> 'y. Now we able to state: g (List.head (f ...) = List.head (List.map g (f ...)). I assume a certain argument of type ['t] to substitute .... Please note: given property is universal: it would hold for any pure functions composition of specified signatures regardless of their implementation. Also note how generic yet obvious it is: there are only two distinct "objects" interacting with each other via "composition", which could also be rewritten in terms of standard F#'s (|>), (<|) operators.
Now the fact is that for any higher order (pure) function there exists such kind of universal property; mostly, there are dozens of them. Thus one able to specify their properties in terms of composition (which is regular for FP) staying at the generic level. Having such a properties in the explicit form gives one chance to autogenerate hundreds of tests, based on inputs different not only by their values (which normally done by unit tests, except the fact they are rarely autogenerated), but also by types.
Pure functions are easier because you just have to test the outputs of your parse function. You shouldn't ever need to test using side effects like you do in imperative programming.
When writing most of your unit tests, you generally use the most simple possible for your function arguments, like identity or similar. Then you'd write one test named something like "mapLevel is applied to fourth group" where instead you make mapLevel something that's easy to recognize as changed, like toUpper. This lets you make sure you didn't accidentally copy/paste mapLevel to more than one output. Then a similar test for mapMessge.
If method A's single role is to call method B, should I write a test that verifies method B is called when I call method A? Or is this a waste?
EDIT: I am editing to add some context. Here is my class:
module PaidGigs
class UserValue
def initialize(user)
#user = user
end
def default_bid(multiplier = 3.5)
PaidGigs::UserValue.cpm_value(#user.instagram_follower_count, multiplier)
end
def bid_value_including_markup(user_bid, multiplier = 3)
user_bid + PaidGigs::UserValue.cpm_value(#user.instagram_follower_count, multiplier, 0)
end
def self.cpm_value(base_count, multiplier, rounder = -1)
((base_count.to_f / 1000) * multiplier).round(rounder)
end
end
end
Should I write a test that verifies '#default_bid' calls '.cpm_value' with the proper arguments? Is this a waste of time, or is there value in this?
Don't test that one method within a method calls another. This will lead to a more fragile test, and create a barrier (although a small one) to refactoring. Your test should not care about the internals that produce the result, only that it's correct.
The answer changes if the method is delegating to another class - then you absolutely need to test, in a unit test, that the delegation occurs corectly by mocking the delegate.
There's value in methods that call others within the class: the name of the methods communicates the purpose of the method (if it's named well) and that's good for the human readers of your class. Well-named methods (and everything else) is hugely powerful, and largely underutilized. The names of low-level methods within a class can create a mini-DSL (Domain Specific Language) within the class, helping the reader to quickly understand what a high-level method is doing without taking the time to dig into the details.
What you're asking about is does it make sense to explicitly test everything your object does, or do you want to implicitly test it.
This is mostly a matter of opinion.
Personally, I see no value in writing that test, because eventually you should be writing a test that mocks out the return value of the method and verifying that function your testing actually mutates the mocked value in such a way. This way you implicitly test that you're calling the function - if you weren't using the method to get your end result, then the value would not align to your expected result.
Edit: A code example in something a bit more readable:
Calculator.cs
public class Calculator {
private IAddingService _addingService;
public Calculator(IAddingService addingService) {
_addingService = addingService;
}
public AddNumbers(int valueOne, int valueTwo) {
return _addingService(valueOne, valueTwo);
}
}
CalculatorTests.cs
public class CalculatorTests {
public void test_adding_numbers() {
var addingService = new Mock<IAddingService>()
addingService.Setup(service => service.Add(1,2)).Returns(2);
var calculator = new Calculator(addingService.Object);
var result = calculator.Add(1,2);
Assert.That(result, Is.EqualTo(2));
}
}
In this example, I've implicitly tested that adding service is the way that we add things because there's no action that allows calculator to determine this on its own.
I don't see why you wouldn't test it. It's easy to do and partially prevents further refactoring of this method to break something.
In F# I want to perform unit testing on a function with several levels of nested functions.
I want to be able to test the nested functions individually as well, but I do not know how I could invoke them.
When debugging, each of these nested functions is invoked as a type of function object, but I don't know if I can access them at compile time.
I do not want to change the nesting scheme that I am using because it makes the most sense functionally to have them nested this way because there is a de facto "inheritance" of some of the function parameters at each nested level.
Is something like this possible? If not, what is the general procedure for unit testing nested functions? Are they tested individually with extra parameters and then inserted into their nested position afterwords never to be able to be tested again?
Very small example:
let range a b =
let lower = ceil a |> int
let upper = floor b |> int
if lower > upper then
Seq.empty
else
seq{ for i in lower..upper -> i}
How could I test that lower or upper are working properly without changing the nested nature of the code?
I would agree with Daniels comment - if the outer function works correctly, you should not need to test any of the inner functions. Inner functions are really an implementation detail that should not be relevant (especially in functional code, where output does not depend on anything else than inputs). In C#, you also don't test whether for loop or while loop inside your method works correctly.
If both the inner and the outer functions are too complex, then perhaps it would be better to write the inner function as a separate function anyway.
That said, you can, of course, mess with the compiled assembly using reflection and invoke the inner function. Inner functions are compiled as classes with constructor that takes the closure (captured values of the outer function) and Invoke method that takes the actual parameters.
The following trivial example works, though I have not tested it on anything more realistic:
open NUnit.Framework
// Function with 'inner' that captures the argument 'a' and takes additional 'x'
let outer a b =
let inner x = x + a + 1
(inner a) * (inner b)
// Unit tests that use reflection in a hacky way to test 'inner'
[<TestFixture>]
module Tests =
open System
open System.Reflection
// Runs the specified compiled function - assumes that 'name' of inner functions
// is unique in the current assembly (!) and that you can correctly guess what
// are the variables captured by the closure (!)
let run name closure args =
// Lots of unchecked assumptions all the way through...
let typ =
Assembly.GetExecutingAssembly().GetTypes()
|> Seq.find (fun typ ->
let at = typ.Name.IndexOf('#')
(at > 0) && (typ.Name.Substring(0, at) = name) )
let flags = BindingFlags.Instance ||| BindingFlags.NonPublic
let ctor = typ.GetConstructors(flags) |> Seq.head
let f = ctor.Invoke(closure)
let invoke = f.GetType().GetMethod("Invoke")
invoke.Invoke(f, args)
/// Test that 'inner 10' returns '14' if inside outer where 'a = 3'
[<Test>]
let test () =
Assert.AreEqual(run "inner" [| box 3 |] [| box 10 |], 14)
I have a bunch of F# functions that implement different algorithms for the same input, kind of like the Strategy pattern. To pick the right strategy, I want to pattern match on the input argument and return the function as a value :
let equalStrategy points : seq<double> =
...
let multiplyStrategy factor (points: seq<double>) =
...
let getStrategy relationship =
match relationship with
| "=" -> equalStrategy
| "*5" -> multiplyStrategy 5.0
| _ -> raise (new System.NotImplementedException(" relationship not handled"))
Now I want to write some unit tests to make sure that I return the right strategy, so I tried something like this in nUnit :
[<TestCase("=")>]
[<Test>]
member self.getEqualstrategy( relationship:string ) =
let strategy = getStrategy relationship
Assert.AreEqual( strategy, equalStrategy )
Now I think the code is correct and will do what I want, but the assertion fails because functions don't seem to have an equality operation defined on them. so my questions are :
(a) is there a way to compare 2 functions to see if they are the same, i.e. let isFoo bar = foo == bar, that I can use in an nUnit assertion?
or
(b) is there another unit testing framework that will do this assertion for me in F#?
Testing whether an F# function returned by your getStrategy is the same function as one of the funcions you defined is also essentially impossible.
To give some details - the F# compiler generates a class that inherits from FSharpFunc when you return a function as a value. More importantly, it generates a new class each time you create a function value, so you cannot compare the types of the classes.
The structure of the generated classes is something like this:
class getStrategy#7 : FSharpFunc<IEnumerable<double>, IEnumerable<double>> {
public override IEnumerable<double> Invoke(IEnumerable<double> points) {
// Calls the function that you're returning from 'getStrategy'
return Test.equalStrategy(points);
}
}
// Later - in the body of 'getStrategy':
return new getStrategy#7(); // Returns a new instance of the single-purpose class
In principle, you could use Reflection to look inside the Invoke method and find which function is called from there, but that's not going to be a reliable solution.
In practice - I think you should probably use some other simpler test to check whether the getStrategy function returned the right algorithm. If you run the returned strategy on a couple of sample inputs, that should be enough to verify that the returned algorithm is the right one and you won't be relying on implementation details (such as whether the getStrategy function just returns a named function or whether it returns a new lambda function with the same behaviour.
Alternatively, you could wrap functions in Func<_, _> delegates and use the same approach that would work in C#. However, I think that checking whether getStrategy returns a particular reference is a too detailed test that just restricts your implementation.
Functions doesn't have equality comparer:
You will have error: The type '('a -> 'a)' does not support the 'equality' constraint because it is a function type
There is a good post here
It would be very difficult for the F# compiler to prove formally that two functions always have the same output (given the same input). If that was possible, you could use F# to prove mathematical theorems quite trivially.
As the next best thing, for pure functions, you can verify that two functions have the same output for a large enough sample of different inputs. Tools like fscheck can help you automate this type of test. I have not used it, but I've used scalacheck that is based on the same idea (both are ports from Haskell's QuickCheck)