This past Tuesday, we had James Ward, principal developer advocate for Heroku, give a presentation on the Play Framework, scala/java, and Heroku at the Nashville JUG. Suffice it to say, it was a really awesome presentation. This was far from a sales pitch, and more like a lets-get-our-hands on this framework and build a web app as fast as possible.
Sadly, I had to leave early, but I was hooked on poking my nose into Play. I have been fiddling with a small toy app using Scalatra. It is really nice where you focus on building the routes and then stir in some templates, with a little scala in there to make things nice and succinct. But I had been running into issues repeatedly with the testing. I decided from the get-go, that I would make it a test-driven project, and had built up automated testing quite nicely. I built all the REST points and had everything working with a nice stubbed out data source with future plans to replace it with a NoSQL database.
Scalatra has some nice test structures. You can either use specs or ScalaTest to check everything out. But something that nagged me for some time was how my tests would periodically fail every 3rd or 4th time. Sometimes more often than that. But since they would occasionally pass, I knew that everything worked right. It was probably just some race condition that had to do with the jetty container it used to run the tests.
When I tried to swap out my in-memory maps with MongoDB, I couldn’t get the tests to pass ever. Comment out MongoDB code; tests pass. Bring back ’em on line; fail again. It drove me nuts. I tried lots of things. This was when I saw the Play demo. Seeing that it was heavily route-based, I thought it probably wouldn’t be hard to transfer my existing test suite to a Play app, modify any API calls, and use this set of tests to rebuild the REST points in Play. Well, I was able to do it in just a few hours. And guess what? Now there are no failures…EVER!
Why did Play succeed where Scalatra failed me? I think it’s because Play has different levels of testing. They build in helpers that let you test from any angle, meaning you don’t have to test the runnable container. Instead, they offer a lot of useful angles to isolate and test things out:
- test individual units
- test templates
- test controllers
- test routes (see http://www.playframework.org/documentation/2.0.2/ScalaFunctionalTest)
- test the whole thing with an HTTP server
- test from a browser with Selenium
All these things give you the option to easily grab your existing test suite no matter how it was structured, carry it over to Play, and rebuild you app back up, one test at a time, until everything passes. Then, with your test harness in place, go back and start refactoring as you see fit!
Given all this, Play has really made it easy to put together a REST-ful web app using Scala, my primary goal. I hope you have similar experiences.