Как проверить поведение актера akka, если он читает из `stdin` и пишет в` stdout`? - PullRequest
1 голос
/ 03 июля 2019

Я пишу интерпретатор UCI в качестве конечного автомата Akka. В соответствии со спецификацией интерпретатор должен записать свой вывод в stdout и получить его от stdin.

У меня есть тестовый костюм для актера, и я могу проверить некоторые аспекты (связанные с сообщениями) его поведения, но я не знаю, как перехватить stdout, чтобы сделать утверждения, и как отправить его на вход до stdin. Я исследовал самый масштабный API в меру своих способностей, но не могу найти, как достичь того, что мне нужно.

Это текущий тестовый класс:

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 интерпретатору, она возвращает readyok.

Возможно ли, что я слишком усложняю тест, используя akka.testkit вместо более простого фреймворка? Для простоты я хотел бы продолжать использовать единую среду тестирования, и мне нужно будет протестировать многие другие элементы системы, связанные с актерами, поэтому, если это можно будет решить, не выходя из домена akka-testkit / scalatest, это было бы замечательно.

Любая помощь будет оценена. Заранее спасибо.

1 Ответ

4 голосов
/ 03 июля 2019

Вам нужно изменить дизайн своего актера.

Актер не должен читать stdin или писать stdout напрямую. Вместо этого передайте объектам актера в Props, которые обеспечивают ввод и принимают вывод. stdin может быть чем-то вроде () => String, который вызывается каждый раз, когда требуется ввод. stdout может быть String => Unit, который вызывается каждый раз, когда генерируется вывод. Или вы можете использовать Streams или аналогичные конструкции, предназначенные для абстрактных источников и приемников данных.

В рабочем коде вы передаете объекты, которые используют stdin и stdout, но для тестового кода вы передаете объекты, которые читают и записывают буферы памяти. Затем вы можете проверить, что соответствующий вход использует Актор и что соответствующий выход генерируется Актором.

...