# Idiomatic F# unit test using xunit and unquote

I'm writing some unit tests for testing C# code but I'm using F# and Unquote for the first time for the unit tests and would like some input as to how I might make the tests more 'f-sharpier' to take advantage of and learn more about the functional approach in F#. Here's an example of one of my tests - please make recommendations:

[<Fact>]
let Two courses, one with one time and one with two times that all differ, returns two unique schedules with two entries each() =
// arrange
let course1 = getCourse1()
let course2 = getCourse2()
let time1 = getTime1()
let time2 = getTime2()
let time3 = getTime3()

let courses = List<Course>()

let scheduleEntry1 = ScheduleEntry(course1, time1)
let scheduleEntry2 = ScheduleEntry(course2, time2)
let scheduleEntry3 = ScheduleEntry(course2, time3)

// act
let schedules = courses |> ScheduleGenerator.Schedulize

// assert
test <@ schedules.Count() = 2 @>

let allSchedulesHave2Entries = schedules.All(fun schedule -> schedule.Count() = 2)
test <@ allSchedulesHave2Entries @>

let hasSchedule entries = schedules.Any(fun schedule -> schedule.ToArray() = entries)
test <@ hasSchedule [| scheduleEntry1; scheduleEntry2 |] @>
test <@ hasSchedule [| scheduleEntry1; scheduleEntry3 |] @>


ScheduleGenerator.Schedulize returns an IEnumerable<IEnumerable<ScheduleEntry>> which is the type of schedules. So the type of schedule is just IEnumerable<ScheduleEntry>.

What ScheduleGenerator.Schedulize does is take a set of courses IEnumerable<Course>, where each course contains all available times for the course, and computes the Cartesian product for all the times across all the courses and then filters out any schedule which contains conflicting times.

• why not just let courses = [|course1; course2 |] instead of let courses = List<Course>() [|course1; course2 |] |> courses.AddRange?
– user110704
Aug 5 '16 at 17:31
• And instead of schedules.All better schedules |> Seq.forall - more F#-style.
– user110704
Aug 5 '16 at 17:35
• It is really weird to me seeing <@ @> and the test function. This is type provider syntax right ? What is the advantage of simply using the Assert methods? Aug 5 '16 at 18:08
• @asibahi, Its Unquote
– user110704
Aug 5 '16 at 18:38
• @FoggyFinder I looked it up but if I understand correctly it doesn't change xUnit's behavior, right? It is only different from regular asserts when printing to FSI? Aug 5 '16 at 18:39

I guess I mostly needed to figure out how to replace LINQ with F# equivalents and then refactor a bit. Now I have this:

let ToArrays schedules =
schedules
|> Seq.map (fun schedule -> schedule |> Seq.toArray)
|> Seq.toArray

[<Fact>]
let Two courses, one with one time and one with two times that all differ, returns two unique schedules with two entries each() =
// arrange
let course1 = getCourse1()
let course2 = getCourse2()
let time1 = getTime1()
let time2 = getTime2()
let time2a = getTime2a()

let schedulesExpected =
[|
[| ScheduleEntry(course1, time1); ScheduleEntry(course2, time2) |]
[| ScheduleEntry(course1, time1); ScheduleEntry(course2, time2a) |]
|]

// act
let schedulesActual = [| course1; course2 |] |> ScheduleGenerator.Schedulyze

// assert
test <@ schedulesActual |> ToArrays = schedulesExpected @>

• instead of |> Seq.map (fun schedule -> schedule |> Seq.toArray)  you can use just |> Seq.map (Seq.toArray)
– user110704
Aug 6 '16 at 6:09
• @FoggyFinder - it's IEnumerable<IEnumerable<ScheduleEntry>>` so both the inner and outer need to be converted to arrays to get structural equality required in the test. And thanks for your earlier comments which got me pointed in the right path Aug 6 '16 at 17:31