Scala单元测试stdin / stdout

时间:2014-06-15 08:39:09

标签: scala unit-testing scalatest

单元测试stdIn / stdOut是否常见?如果是这样,那你将如何测试这样的东西:

import scala.io.StdIn._

object Test {

    def main(args: Array[String]) = {

        println("Please input your text. Leaving an empty line will indicate end of the input.")

        val input = Iterator.continually(readLine()).takeWhile(_ != "").mkString("\n")

        val result = doSomethingWithInput(input)

        println("Result:")
        println(result)

    }

}

我通常使用ScalaTest,如果这有任何区别。

3 个答案:

答案 0 :(得分:4)

由于Scala在后台使用标准Java流(System.outSystem.in),您可以通过将自定义流替换标准流来进行测试,您可以进一步检查。 See here了解更多详情。

实际上,虽然我主要关注确保doSomethingWithInput已经过全面测试,并且可能会跟进输入读数的测试(以确保停止条件和输入字符串构造按预期工作)。 / p>

如果您已经测试过您要访问println的值,那么确保将其发送到控制台流只会给您带来很多好处。此外,这样的测试案例将是继续前进的痛苦。一如既往,这取决于您的使用案例,但在大多数情况下,我不会对其进行测试。

答案 1 :(得分:0)

我会更改doSomethingWithInput以将BufferedSource作为参数,这样您就可以使用任何源流编写单元测试而不仅仅是stdin

答案 2 :(得分:0)

Console对象提供了withInwithOut方法,可以临时重定向stdin和stdout。这是一个测试示例vulcanIO的有效示例,该方法同时读取并打印到stdin / stdout:

import java.io.{ByteArrayOutputStream, StringReader}
import org.scalatest._
import scala.io.StdIn

class HelloSpec extends FlatSpec with Matchers {
  def vulcanIO(): Unit = {
    println("Welcome to Vulcan. What's your name?")
    val name = StdIn.readLine()
    println("What planet do you come from?")
    val planet = StdIn.readLine()
    println(s"Live Long and Prosper ?, $name from $planet.")
  }

  "Vulcan salute" should "include ?, name, and planet" in {
    val inputStr =
      """|Jean-Luc Picard
         |Earth
      """.stripMargin
    val in = new StringReader(inputStr)
    val out = new ByteArrayOutputStream()
    Console.withOut(out) {
      Console.withIn(in) {
        vulcanIO()
      }
    }
    out.toString should (include ("?") and include ("Jean-Luc Picard") and include ("Earth"))
  }
}

请注意内部重定向的发生方式

Console.withOut(out) {
  Console.withIn(in) {
    vulcanIO()
  }
}

以及我们如何在输出流out上断言

out.toString should (include ("?") and include ("Jean-Luc Picard") and include ("Earth"))