Adventures in TDDing Scala Actors with Scalatest

February 28, 2010 Glenn Jahnke

Recently, Martin Odersky and David Pollak visited Pivotal Labs to show off Scala and its Lift web framework. I have an ongoing interest in concurrent programming and this resparked my interest in Scala and its Actors, a library that leverages the Erlang style concurrency model but with a (relatively) more familiar JVM language. I began spiking on a project with Actors some time ago but hit several issues that made me really want to test-drive the project to both drive out better design, and hopefully eliminate some of these bugs in a more productive manner.

After some effort reading documentation about both ScalaTest and Scala’s Actors, and wrangling with the compiler for a while, here is where I am so far.

The test for a very simple Square class that accepts three messages, then returns the maximum.

package test

import org.scalatest._
import matchers.MustMatchers
import main.Square

class SquareSpec extends Spec with MustMatchers {
  describe("Square") {
    it("returns the max of 3 messages received") {
      val timeout = 500
      val square = new Square
      square ! 1
      square ! 3
      (square !? (timeout, 2)).get must equal(3)
    }
  }
}

Here is the implementation.

package main

import scala.actors.Actor
import scala.actors.Actor._

class Square extends Actor {
  var numMessagesReceived = 0
  var maxMessageReceived = Integer.MIN_VALUE
  this.start
  def act() {
    loop {
      react {
        case msg : Int => replyWhenNecessary(msg)
      }
    }
  }

  def replyWhenNecessary(msg : Int) {
    println(msg)
    maxMessageReceived = if(maxMessageReceived > msg) {maxMessageReceived} else {msg}
    numMessagesReceived += 1
    if(numMessagesReceived == 3) {
      reply(maxMessageReceived)
      exit
    }
  }
}

Things I learned:

Scala

  • Scala’s classes don’t call out the main constructor, you just dump the class variables in parentheses after the class name and constructor code inside the body of the class

Actors

  • You can use the method!?(timeout, message) in place of !(message) to synchronously, and with a timeout, get a return message from the actor. The actor must reply though. The timeout is great for testing, often you’ll have an actor in an infinite loop and your test won’t complete instead of failing nicely.

ScalaTest

  • ScalaTest has several flavors of test, but the one that most Rubyists will appreciate is having your test class extend Spec as it is most similar to RSpec.

General

  • IntelliJ Community Edition with the Scala plugin is pretty awesome.

Hopefully I’ll have more later as I continue my effort to learn how to test concurrent programming.

About the Author

Biography

Previous
New Yorkers, looking for a new challenge? Come work for a Pivotal client!
New Yorkers, looking for a new challenge? Come work for a Pivotal client!

At Pivotal Labs, one of the services we provide is bootstrapping startups, including helping them interview...

Next
webOS Workshop Tech Talk posted
webOS Workshop Tech Talk posted

As promised, the video from the webOS Workshop we held on January 23rd is posted on our talks page. It's f...