Scala单元测试stdin / stdout

Cab*_*ero 4 unit-testing scala 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)

    }

}
Run Code Online (Sandbox Code Playgroud)

我通常使用ScalaTest,如果有什么区别。

Mar*_*lic 6

Console对象提供了withIn启用withOutstdin 和 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"))
  }
}
Run Code Online (Sandbox Code Playgroud)

注意重定向是如何在内部发生的

Console.withOut(out) {
  Console.withIn(in) {
    vulcanIO()
  }
}
Run Code Online (Sandbox Code Playgroud)

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

out.toString should (include ("") and include ("Jean-Luc Picard") and include ("Earth"))
Run Code Online (Sandbox Code Playgroud)


Nor*_*dyk 5

由于斯卡拉使用标准的Java流(System.out,System.in幕后),您可以测试它,通过它,你可以进一步检查您的自定义流替换标准流。有关更多详细信息,请参见此处。

实际上,尽管我主要集中精力确保doSomethingWithInput已完全测试,并且可能会跟进测试输入读数(以确保停止条件和输入字符串构造按预期工作)。

如果您已经测试了将要使用的值,println那么确保将其发送到控制台流不会带来很多好处。而且,这样的测试用例将是维持未来发展的痛苦。与往常一样,它取决于您的用例,但是在大多数情况下,我只是避免对其进行测试。