Frage

Wer weiß, von einem guten Weg, um Unit-Test Scala Schauspieler? Im allgemeinen Sinne habe ich einen Schauspieler, der eine Nachricht und senden andere Nachrichten als Antwort erhält. Dies ist auf mehrere Threads getan, und ein Schauspieler, der entweder nicht korrekt ist, überhaupt die falschen Nachrichten oder keine Nachricht. Ich brauche eine einfache Möglichkeit, einen Mockup Schauspieler zu schaffen, sendet und empfängt Nachrichten an den Schauspieler getestet. Irgendwelche Erfahrungen in diesem Bereich?

War es hilfreich?

Lösung

Aufgrund der dynamischen Natur der Schauspieler-Stil Message Passing, Schauspieler spöttisch ist in der Regel keine Probleme überhaupt. Nur einen Schauspieler erstellen, die die gewünschte Nachricht empfängt und du bist zu Hause frei. Natürlich werden Sie auch brauchen, um sicherzustellen, dass diese Mock Schauspieler derjenige ist, an die Nachrichten sind vergangen, aber das sollte kein Problem, solange der Schauspieler sein, Sie zu testen möchten, ist einspringenden .

Andere Tipps

Ich denke, die Komplexität auf ein paar Faktoren ab ...

  1. Wie Stateful ist der Schauspieler?

Wenn es wie eine Idempotent Funktion verhält, nur asynchron, dann sollte es einen Schauspieler eine einfache Sache der spöttischen werden, die eine Nachricht sendet und dann überprüft, ob sie die erwarteten Nachrichten zurück erhalten. Sie wollen wahrscheinlich eine Reaktion / receiveWithin auf dem Mock Schauspieler verwenden, falls es Antwort innerhalb einer angemessenen Frist Sie nicht hängen ausfallen können.

Allerdings, wenn die Nachrichten sind nicht unabhängig voneinander, dann sollten Sie es mit verschiedenen Sequenzen von Nachrichten und die erwarteten Ergebnisse testen.

  1. Wie viele Akteure der Schauspieler interact getestet wird, mit?

Wenn ein Schauspieler erwartet wird, mit vielen anderen zu interagieren, und es ist Stateful, dann sollte es mit mehreren Akteuren Senden / Empfangen von Nachrichten zu prüfen. Da Sie wahrscheinlich in denen keine Garantie für den Auftrag haben, die Nachrichten ankommen, sollten Sie sicher sein, die Aufträge entweder permutieren, in dem die Akteure die Nachrichten senden oder zufällige Pausen in den Akteuren einzuführen Nachrichten zu erzeugen und den Test mehrmals ausgeführt werden.

Ich bin nicht bekannt, dass vorgefertigte Gerüste für die Akteure zu testen, aber Sie könnten möglicherweise für die Inspiration zu Erlang suchen.

http: //svn.process-one .net / contribs / trunk / eunit / doc / Überblick-summary.html

Ich habe mich gefragt, wie Schauspieler zu testen selbst.

Hier ist, was ich mit aufkommen, hat jemand Probleme sieht mit diesem Ansatz?

Anstatt direkt Nachrichten zu senden, was passiert, wenn Ihre Schauspieler Nachricht an eine Funktion delegiert Senden?

Dann können Sie Ihre Tests tauschen die Funktion mit einem heraus, dass die Anzahl der Tracks genannt und / oder Argumente, mit denen die Methode aufgerufen wurde:

class MyActor extends Actor {

  var sendMessage:(Actor, ContactMsg) => Unit = {
    (contactActor, msg) => {
      Log.trace("real sendMessage called")
      contactActor ! msg 
    }
  }

  var reactImpl:PartialFunction(Any, Unit) = {
      case INCOMING(otherActor1, otherActor2, args) => {

        /* logic to test */
        if(args){
          sendMessage(otherActor1, OUTGOING_1("foo"))

        } else {
          sendMessage(otherActor2, OUTGOING_2("bar"))
        }
      }
  }

  final def act = loop {
    react {
      reactImpl
    }
  }

Ihr Testfall enthält möglicherweise Code wie:

// setup the test
var myActor = new MyActor
var target1 = new MyActor
var target2 = new MyActor
var sendMessageCalls:List[(Actor, String)] = Nil

/*
* Create a fake implementation of sendMessage
* that tracks the arguments it was called with
* in the sendMessageCalls list:
*/
myActor.sendMessage = (actor, message) => {
  Log.trace("fake sendMessage called")
  message match {
    case OUTGOING_1(payload) => { 
      sendMessageCalls = (actor, payload) :: sendMessageCalls
    }
    case _ => { fail("Unexpected Message sent:"+message) }
  }
}

// run the test
myActor.start
myActor.reactImpl(Incoming(target1, target2, true))

// assert the results
assertEquals(1, sendMessageCalls.size)
val(sentActor, sentPayload) = sendMessageCalls(0)
assertSame(target1, sentActor)
assertEquals("foo", sentPayload)
// .. etc.

Mein Versuch Einheit testet einen Schauspieler (es funktioniert). Ich verwende Specs als Rahmen.

object ControllerSpec extends Specification {
  "ChatController" should{
    "add a listener and respond SendFriends" in{
        var res = false
        val a = actor{}
        val mos = {ChatController !? AddListener(a)}
        mos match{
             case SendFriends => res = true
             case _ => res = false
        }
        res must beTrue
    }

Wie dies funktioniert, ist durch einen synchronen Aufruf des Singleton ChatController senden. ChatController reagiert durch Verwendung von Antwort () . Die Antwort wird als Rückkehr der aufgerufenen Funktion gesendet, die in MoS gespeichert werden. Dann wird ein Spiel auf mos angewandt, um die Fallklasse erhalten, die von ChatController gesendet wurde. Wenn das Ergebnis ist, was erwartet wird (SendFriends) gesetzt res auf true. Das res muss beTrue Behauptung bestimmt den Erfolg oder Misserfolg des Tests.

Meine Schauspieler Singletons, die ich testen

import ldc.socialirc.model._

import scala.collection.mutable.{HashMap, HashSet}
import scala.actors.Actor
import scala.actors.Actor._

import net.liftweb.util.Helpers._

//Message types
case class AddListener(listener: Actor)
case class RemoveListener(listener: Actor)
case class SendFriends
//Data Types
case class Authority(usr: Actor, role: String)
case class Channel(channelName: String, password: String, creator: String, motd:   String, users: HashSet[Authority])

object ChatController extends Actor {
    // The Channel List  - Shows what actors are in each Chan
    val chanList = new HashMap[String, Channel]
    // The Actor List - Shows what channels its in
    val actorList = new HashMap[Actor, HashSet[String]]

    def notifyListeners = {

    }

    def act = {
        loop {
            react {
                case AddListener(listener: Actor)=>
                    actorList += listener -> new HashSet[String]
                    reply(SendFriends)

            }
        }
    }
    start //Dont forget to start
}

Obwohl seine nicht vollständig es macht die Sendfriends Fall Klasse zurückgeben, wie erwartet.

Suite für Unit-Tests von Schauspieler wurde vor kurzem hinzugefügt, um Akka . Sie können einige Informationen und Code-Schnipsel in finden Blogpost.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top