2011-08-28 22 views
21

C'è qualcosa in Scalatest che mi permetterà di testare l'output allo standard tramite una dichiarazione println?Scalatest - come testare println

Finora ho utilizzato principalmente FunSuite with ShouldMatchers.

ad es. come si fa a controllare l'output stampato della

object Hi { 
    def hello() { 
    println("hello world") 
    } 
} 

risposta

24

Il solito modo per testare le dichiarazioni di stampa sulla console è quello di strutturare il programma un po 'diverso in modo da poter intercettare tali dichiarazioni. È possibile ad esempio introdurre un Output tratto:

trait Output { 
    def print(s: String) = Console.println(s) 
    } 

    class Hi extends Output { 
    def hello() = print("hello world") 
    } 

E nei test è possibile definire un altro tratto MockOutput realtà che intercettano le chiamate:

trait MockOutput extends Output { 
    var messages: Seq[String] = Seq() 

    override def print(s: String) = messages = messages :+ s 
    } 


    val hi = new Hi with MockOutput 
    hi.hello() 
    hi.messages should contain("hello world") 
+0

È necessario aggiungere "override" a MockOutput –

+0

Mi piace molto questa soluzione, @Eric c'è un modo per farlo senza dover estendere "Output". Sento che "estendere" un tratto, in cui quel tratto non è necessario in primo luogo, è un hack. Avrebbe senso se il tratto fosse già necessario e abbiamo creato un impl di test. –

+3

L'unico altro modo per evitare di estendere un tratto è fare ciò che Kevin o Matthieu consigliano. Detto questo, ho la filosofia che costruire il tuo software in modo che sia testabile è una buona decisione di progettazione. Quando persegui quel pensiero, vai fino all'introduzione di tratti per * tutte * le tue interazioni IO/sistemi esterni. – Eric

2

È possibile sostituire in cui println scrive utilizzando Console.setOut (PrintStream)

val stream = new java.io.ByteArrayOutputStream() 
Console.setOut(stream) 
println("Hello world") 
Console.err.println(stream.toByteArray) 
Console.err.println(stream.toString) 

È possibile, ovviamente, utilizzare qualsiasi tipo di flusso che si desidera. Si può fare lo stesso tipo di cosa per stderr e stdin con

Console.setErr(PrintStream) 
Console.setIn(PrintStream) 
+1

Si noti che 'Console. {setErr, setIn, setOut}' è stato deprecato a partire da 2.11.0 (~ 3 anni dopo che questa risposta è stata inviata). –

+0

I nuovi metodi sono Console. {WithOut, withIn, withErr} – Zee

57

Se si desidera solo per reindirizzare l'output della console per una durata limitata, utilizzare i withOut e withErr metodi definiti sulla Console:

val stream = new java.io.ByteArrayOutputStream() 
Console.withOut(stream) { 
    //all printlns in this block will be redirected 
    println("Fly me to the moon, let me play among the stars") 
} 
+0

Buon punto, mi sono dimenticato di quello. – Eric

+3

Questo è il modo migliore, non c'è bisogno di ristrutturare il programma per i test. – incarnate

Problemi correlati