haf / expecto

A smooth testing lib for F#. APIs made for humans! Strong testing methodologies for everyone!
Apache License 2.0
663 stars 96 forks source link

testTask doesn't handle the same bindings as task expressions #488

Closed farlee2121 closed 3 months ago

farlee2121 commented 3 months ago

The F# task expression can bind Tasks, ValueTasks, and Async types. It appears testTask currently only handles Task types.

Example

let iAmTask () : Task<int> = Task.FromResult(5)
let iAmValueTask () : ValueTask<int> = ValueTask.FromResult(5)
let iAmAsync () : Async<int> = async.Return 5

// Task expression works for all types
let example () = task {
    let! boundTask = iAmTask()
    let! boundValueTask = iAmValueTask()
    let! async = iAmAsync() 
    return ()
}

// testTask errors on ValueTask and Async
let example () = testTask "I am Test" {
    let! boundTask = iAmTask()
    let! boundValueTask = iAmValueTask()
    let! async = iAmAsync() 
    return ()
}

Potential Solution

I'm still trying to understand the TaskBuilder code in F#, but I think we could get away with inheriting from TaskBuilder and overloading Run. All of the TestTaskBuilder methods except for run are a direct forwarding to TaskBuilder. This would allow us to stay in sync with whatever the task expression supports.

If inheriting doesn't work, we could probably get close enough with a few additional Bind overloads.