I've been wondering what methods (if any) are used for testing Haskell applications that do requests over the network? Coming from Ruby land, I've been searching for anything that can either stub or "simulate" network calls for the purpose of testing Haskell functions. I'm particularly interested in a "VCR"-like solution (e.g.: https://github.com/myronmarston/vcr), as it seems to be the most viable option, IMHO.
So, I want to be able to record network request/response pairs once and then reuse these records for the subsequent tests. I have come up with my own simplistic concoction that starts a web server (warp) before the tests, serving prerecorded responses, but I have to point all URLs within the application to "localhost". I presume, this is not always possible to replace all URLs within the application. Although I'm quite happy with my own setup described above (and would like to make a dedicated testing tool/framework "plugin" from it later), but I'd rather not reinvent the wheel.
Check out Control.Proxy.Tutorial. If you can write a Proxy wrapper around your type, then you can easily swap out the test interface and a real interface like this:
client <-< simulatedServer
client <-< realServer
Edit: To answer your question in the comment, you use a Server
to write a wrapper around your simpleHTTP
requests:
realServer
:: HStream ty => Request ty -> Server (Request ty) (Result (Response ty)) IO r
realServer = foreverK $ \req -> do
result <- lift $ simpleHTTP req
respond result
The simulated server would look like:
simulatedServer
:: (Monad m, HStream ty)
=> Request ty -> Server (Request ty) (Result (Response ty)) m r
simulatedServer = foreverK $ \req -> do
result <- lift $ simulatedRequest req
respond result
And your client would look like:
client
:: (Monad m, HStream ty) => () -> Client (Request ty) (Result (Response ty)) m r
client () = forever $ do
let req = <something>
result <- request req
lift $ doSomethingWith result
Then you can test the real server and fake server using:
-- Test the real server
main = runSession $ client <-< realServer
-- Test the fake server
main = runSession $ client <-< simulatedServer
The client
and simulatedServer
are polymorphic in the base monad only because I don't know what base monad they would use for your testing. The only requirement is that the two things you compose have the same base monad or that at least one is polymorphic in the base monad.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With