如果从 stdin 读取并写入 stdout,如何测试 akka actor 的行为?
How to test the behaviour of an akka actor, if it reads from `stdin` and writes to `stdout`?
我正在编写一个 UCI 解释器,作为 Akka 有限状态机。根据规范,解释器必须将其输出写入 stdout
,并从 stdin
.
获取输入
我有一个演员测试服,我可以测试它行为的某些方面(与消息相关),但我不知道如何捕获 stdout
来做出断言,也不知道如何通过 stdin
将其输入发送给它。我已经尽我所能探索了最高级的 API,但找不到如何实现我需要的东西。
这是当前测试class:
package org.chess
import akka.actor.ActorSystem
import akka.testkit.{TestKit, TestProbe}
import org.chess.Keyword.Quit
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.{BeforeAndAfterAll, Matchers}
import scala.concurrent.duration._
import scala.language.postfixOps
class UCIInterpreterSpec(_system: ActorSystem)
extends TestKit(_system)
with Matchers
with AnyWordSpecLike
with BeforeAndAfterAll {
def this() = this(ActorSystem("UCIInterpreterSpec"))
override def afterAll: Unit = {
super.afterAll()
shutdown(system)
}
"A UCI interpreter" should {
"be able to quit" in {
val testProbe = TestProbe()
val interpreter = system.actorOf(UCIInterpreter.props)
testProbe watch interpreter
interpreter ! Command(Quit, Nil)
testProbe.expectTerminated(interpreter, 3 seconds)
}
}
}
当然,知道解释器可以退出是有用的……但用处不大。我需要测试,例如,如果将字符串 isready
发送给解释器,它 returns readyok
.
是否有可能我使用 akka.testkit 而不是更简单的框架使测试过于复杂?为了简单起见,我想继续使用单一的测试框架,我将需要测试系统的许多其他与参与者相关的元素,所以如果这可以在不离开 akka-testkit/scalatest 域的情况下解决,那就太棒了。
如有任何帮助,我们将不胜感激。提前致谢。
您需要更改 Actor 的设计。
Actor 不应直接读取 stdin
或直接写入 stdout
。相反,在 Props
中提供提供输入和接受输出的参与者对象。 stdin
可能类似于 () => String
,每次需要输入时都会调用它。 stdout
可以是 String => Unit
,每次生成输出时都会调用它。或者,您可以使用 Streams
或设计为抽象数据源和接收器的类似结构。
在生产代码中,您传递使用 stdin
和 stdout
的对象,但对于测试代码,您传递读取和写入内存缓冲区的对象。然后您可以检查 Actor 是否消耗了适当的输入以及 Actor 是否生成了适当的输出。
我正在编写一个 UCI 解释器,作为 Akka 有限状态机。根据规范,解释器必须将其输出写入 stdout
,并从 stdin
.
我有一个演员测试服,我可以测试它行为的某些方面(与消息相关),但我不知道如何捕获 stdout
来做出断言,也不知道如何通过 stdin
将其输入发送给它。我已经尽我所能探索了最高级的 API,但找不到如何实现我需要的东西。
这是当前测试class:
package org.chess
import akka.actor.ActorSystem
import akka.testkit.{TestKit, TestProbe}
import org.chess.Keyword.Quit
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.{BeforeAndAfterAll, Matchers}
import scala.concurrent.duration._
import scala.language.postfixOps
class UCIInterpreterSpec(_system: ActorSystem)
extends TestKit(_system)
with Matchers
with AnyWordSpecLike
with BeforeAndAfterAll {
def this() = this(ActorSystem("UCIInterpreterSpec"))
override def afterAll: Unit = {
super.afterAll()
shutdown(system)
}
"A UCI interpreter" should {
"be able to quit" in {
val testProbe = TestProbe()
val interpreter = system.actorOf(UCIInterpreter.props)
testProbe watch interpreter
interpreter ! Command(Quit, Nil)
testProbe.expectTerminated(interpreter, 3 seconds)
}
}
}
当然,知道解释器可以退出是有用的……但用处不大。我需要测试,例如,如果将字符串 isready
发送给解释器,它 returns readyok
.
是否有可能我使用 akka.testkit 而不是更简单的框架使测试过于复杂?为了简单起见,我想继续使用单一的测试框架,我将需要测试系统的许多其他与参与者相关的元素,所以如果这可以在不离开 akka-testkit/scalatest 域的情况下解决,那就太棒了。
如有任何帮助,我们将不胜感激。提前致谢。
您需要更改 Actor 的设计。
Actor 不应直接读取 stdin
或直接写入 stdout
。相反,在 Props
中提供提供输入和接受输出的参与者对象。 stdin
可能类似于 () => String
,每次需要输入时都会调用它。 stdout
可以是 String => Unit
,每次生成输出时都会调用它。或者,您可以使用 Streams
或设计为抽象数据源和接收器的类似结构。
在生产代码中,您传递使用 stdin
和 stdout
的对象,但对于测试代码,您传递读取和写入内存缓冲区的对象。然后您可以检查 Actor 是否消耗了适当的输入以及 Actor 是否生成了适当的输出。