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