Sunday 11 January 2015

Play and ScalaTest - testing controllers

I've started a pet project to play with different aspects of Play and Scala and today tried to decide which test library to use. The 2 main contenders are Specs2 and ScalaTest. After reading a great number of articles about both I concluded they are both offer similar functionality so either would be fine as a starting point.

To get ScalaTest running I followed the guide here:

However some tweaks were needed to get what I wanted so I'll step through it quickly here.

Add the appropriate dependency to build.sbt

"org.scalatestplus" %% "play" % "1.2.0" % "test"

Latest version numbers here: http://www.scalatest.org/plus/play/versions

Change my controller to be more testable

Instead of using a straight object for the controller having it as a trait means you can instantiate versions of it in your test, which gives you the ability to override some methods when you test it, I see this could be useful for when you want to test some things in isolation. 

However really for now I think I could just as easily just use the object directly (I've checked and the tests still work fine this way). I will follow the trait-object pattern as it seems to be recommended and hopefully will come in handy later.

Controller is:
trait QuestionsController {  
   this: Controller =>  
   def createQuestion = Action {  
      Ok(views.html.addQuestion())
   }
}  

object QuestionsController extends Controller with QuestionsController

Test the controller

The example given on the play site for unit testing shows the Ok call above just outputting text. As soon as you try to replace that with one that actually calls a view it will stop working, complaining that there is no started application.

The next page on the play site gives the answer to this, which is to mix in a fake application.

Complete test is:
import scala.concurrent.Future  
import org.scalatestplus.play._
import play.api.mvc._  
import play.api.test._  
import play.api.test.Helpers._

class QuestionsControllerSpec extends PlaySpec with OneAppPerSuite {
   class TestQuestionsController() extends Controller with QuestionsController
   "createQuestion" must {
      "direct to the create question page" in {  
         val controller = new TestQuestionsController()  
         val result: Future[Result] = controller.createQuestion().apply(FakeRequest())  
         val bodyText: String = contentAsString(result) bodyText must include("Add Question and Answer")
      }
   }


 So that's it, a simple controller test.

Introduction

Hi,

I have recently started a major career change - moving from generalist jobs to become a software developer. I hope to share some of the things I learn along the way through this blog.

A little background about me. I graduated with a physics degree and worked for 2 years as a support analyst - application support, training, SQL, and a taster of VBA and C#. I then signed up for a graduate scheme aimed at producing technically minded generalists. There I spent 4 years in a variety of jobs from project management, to commercial work, to requirements analysis. Mostly not very technical.

About 4 months ago I started working as a developer. There has been a huge learning curve so far and I still think I am only scratching the surface. At present the main technologies I've been using include:
- Scala and the Play framework
- NodeJS and Express
- Cucumber (both with Ruby and Cucumber-js)
- MongoDB

Hope this blog ends up being some use to someone!

Tim