2014-04-05 15 views
6

Ich teste ein Programm. Insbesondere teste ich eine Funktion isoliert. Es erfordert einen Handle, der sowohl gelesen als auch geschrieben werden kann. Das Problem ist, stdin oder stdout allein kann den Job nicht erledigen. Ich möchte meinen Code nicht nur wegen eines solchen Tests neu schreiben, noch möchte ich eine Steckdose nur für einen Test öffnen müssen. Außerdem ist das Programm noch nicht benutzbar (die Funktionen sind undefiniert), so dass ich es nicht einfach testen kann, indem ich es ausführe.`stdin` und` stdout` handle

Was ist ein Handle, das es von stdin Eingabe und Ausgabe von stdout in Haskell bekommt.

+0

Ist es unvernünftig, den Code so zu ändern, dass er zwei Griffe hat, einen für die Eingabe und einen für die Ausgabe? –

+0

Nun, es wäre sauberer ohne es denke ich. Ich denke, ich könnte das trotzdem tun. – PyRulez

+1

Ich tendiere dazu, einfach Handles herumzugeben (für stdin/out/err) und zeige sie auf ['Data.Knob'] (https://hackage.haskell.org/package/knob-0.1.1/docs/Data- Knob.html) Instanzen, wenn ich "pure" Tests brauche. –

Antwort

17

Ein einfacher Weg, dies zu tun ist, eine Pipe zu verwenden, um Lese- und Schreibzugriffe auf Handles zu abstrahieren. Ein Typ Sie verwenden können, ist:

example :: Monad m => Pipe String String m() 

Zum Beispiel lassen Sie uns sagen, dass Ihre ursprüngliche Code in etwa so aussah:

original :: IO() 
original = do 
    str1 <- getLine 
    str2 <- getLine 
    putStrLn (str1 ++ str2) 

Die neue pipes Version würde wie folgt aussehen:

import Pipes 

example :: Monad m => Pipe String String m() 
example = do 
    str1 <- await 
    str2 <- await 
    yield (str1 ++ str2) 

Dann können Sie es rein wie folgt testen:

>>> import qualified Pipes.Prelude as Pipes 
>>> Pipes.toList (each ["Hello, ", "world!"] >-> example) 
["Hello, world!"] 

... oder Sie können es mit echtem Eingang und Ausgang testen:

>>> runEffect $ Pipes.stdinLn >-> example >-> Pipes.stdoutLn 
Hello, <Enter> 
world!<Enter> 
Hello, world! 

Auf diese Weise können Sie Ihre Haupt-Logik rein halten, und dann wählen, ob sie rein oder unrein laufen.