2014-04-05 17 views
6

Testuję program. W szczególności testuję funkcję w izolacji. Wymaga uchwytu, który można zarówno czytać, jak i pisać. Problem polega na tym, że sam stdin lub stdout nie może wykonać tej pracy. Nie chcę przepisywać mojego kodu właśnie z powodu takiego testu, ani też nie chcę otwierać gniazda tylko do testu. Ponadto program nie jest jeszcze gotowy do użytku (funkcje są niezdefiniowane), więc nie mogę go przetestować, uruchamiając go.Uchwyt `stdin` i` stdout`

Co to jest uchwyt, który pobiera dane wejściowe z stdin i wyjście z stdout w haskell.

+0

Czy nieuzasadnione jest zmienianie kodu w celu uzyskania dwóch uchwytów, jednego dla wejścia i jednego dla wyjścia? –

+0

Cóż, byłoby to czystsze bez tego, jak sądzę. Myślę, że mogłem to zrobić. – PyRulez

+1

Zazwyczaj po prostu przekazuję uchwyty (dla stdin/out/err) i kieruję je do ['Data.Knob'] (https://hackage.haskell.org/package/knob-0.1.1/docs/Data- Knob.html), jeśli potrzebuję "czystych" testów. –

Odpowiedz

17

Jednym z prostych sposobów na to jest użycie Pipe, aby zmniejszyć liczbę odczytów i zapisów do uchwytów. Jeden typ można użyć to:

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

Na przykład, powiedzmy, że oryginalny kod wyglądało mniej więcej tak:

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

Nowy pipes wersja będzie wyglądać następująco:

import Pipes 

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

Następnie można przetestować go w następujący sposób:

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

... czy można przetestować go z prawdziwym wejściu i wyjściu:

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

To pozwala zachować swoją główną logikę czystego, a następnie zdecydować, czy uruchomić go czysto lub impurely.

Powiązane problemy