Jugando con Scala: BDD + Play2 Framework

¿Qué quiero hacer?

En casa tenemos las tareas domésticas “bien” distribuidas: mi mujer se encarga de la ropa, yo de la cocina y tenemos una señora que nos echa un cable con el resto una vez por semana. Aún así, de vez en cuando cae algún reproche. El objetivo de esta aplicación será visualizar y recompensar el esfuerzo de cada uno en sacar adelante la casa. Para esto, primero definiremos las tareas que hay que hacer para que la familia tire adelante: ir a comprar, hacer la cena, poner la lavadora, bañar a Lucía, etc. Una vez definidas las tareas, el equipo -perdón, pareja- las estimará en función del esfuerzo necesario para realizarlas -¿he oído planning poker?-. Ahora el mecanismo es sencillo, sólo hay que hacer las tareas domésticas e ir acumulando puntos de esfuerzo por realizarlas. ¿Y que hago con estos puntos de esfuerzo? Ahí está lo mejor, los podrás cambiar por premios!! Juntamente con tu pareja podréis definir una serie de premios y los puntos necesarios para obtenerlos. Sed originales a la hora de pensar los premios!

¿Cómo lo quiero hacer?

El pasado noviembre finalicé el MOOC de Coursera Functional Programming Principles in Scala. El curso, que te sirve para refrescar los conceptos de programación funcional que vi de casualidad en la universidad hace casi 15 años y que tanto me gustaron, es una pequeña introducción a Scala, un lenguaje funcional que corre sobre la JVM. Una vez acabado el curso me quedé con ganas de más, con ganas de hacer alguna tontería con Scala y profundizar un poco. Buscando como empezar a hacer algo con cara y ojos, no me costó encontrar referencias a Play Framework, porqué hacer aplicaciones de cero mola, pero cuando no tienes ni idea un framework puede ayudar.

Por otro lado, hará cosa de un mes fui a un meetup organizado por Scala Barcelona Developers donde Jose Raya (@_joseraya) y Jordi Pradel (@agile_jordi) hicieron una pequeña demo de como montar una API REST con Scala aplicando BDD, en concreto cucumber. Apenas me defiendo en TDD, pero BDD es algo que, aunque nunca me he animado ha hacerlo, hace tiempo que quiero probar y creo que completaría mis prácticas en TDD.

Equipo:

No es necesario un IDE, pero puede facilitarte las cosas. Yo uso Eclipse Juno 4.2 + Scala IDE 3.0

¡Manos a la obra!

Lo primero es construir el esqueleto del nuevo proyecto. Ejecutaremos:

play new scala_housework

A continuación añadiremos las dependencias a cucumber. Editaremos el fichero project\plugins.sbt para añadir el repositorio de cucumber y el plugin

// Comment to get more information during initialization
logLevel := Level.Warn

// The Typesafe repository
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"

// Use the Play sbt plugin for Play projects
addSbtPlugin("play" % "sbt-plugin" % "2.1.0")

// use cucumber with sbt
resolvers += "Templemore Repository" at "http://templemore.co.uk/repo"

addSbtPlugin("templemore" % "xsbt-cucumber-plugin" % "0.6.2")

Después, en project\Build.scala añadiremos la configuración de cucumber modificando el directorio donde se encontraran nuestras features

import sbt._
import Keys._
import PlayProject._
import templemore.xsbt.cucumber.CucumberPlugin

object ApplicationBuild extends Build {

    val appName         = "housework"
    val appVersion      = "1.0-SNAPSHOT"

    val buildSettings = Defaults.defaultSettings ++
                        CucumberPlugin.cucumberSettings ++
                        Seq ( CucumberPlugin.cucumberFeaturesDir := file("./test/features/"),
                              CucumberPlugin.cucumberJunitReport := true,
                              CucumberPlugin.cucumberHtmlReport := true)

    val appDependencies = Seq(
      // Add your project dependencies here,
    )

    val main = play.Project(appName, appVersion, appDependencies, settings = buildSettings).settings(
      // Add your own project settings here
    )
}

Sólo nos queda escribir el primer escenario y empezar con el desarrollo!!

Feature: HouseworksList
  In order to manage my houseworks easily, and then I could do all my houseworks and accumulate points for win a prize.
As a couple's member
I want to manage housetasks on the web pages.

  Scenario: Puts a task
    Given Set a database
    When I go to the housework list page
    Then I should see "0 task"
    When I fill in "Housework" with "wash the dishes"
    And  I push "create"
    Then I should see "1 task"
    And I am in the housework list page
    And  I should see "wash the dishes"
D:\projects\Scala\housework>play cucumber
[info] Loading project definition from D:\projects\Scala\housework\project
[info] Set current project to housework (in build file:/D:/projects/Scala/housework/)
[info] Running cucumber...
[info]
[info]
[info] You can implement missing steps with the snippets below:
[info]
[info] Given("""^Set a database$"""){ () =>
[info]   //// Express the Regexp above with the code you wish you had
[info]   throw new PendingException()
[info] }
[info] When("""^I go to the housework list page$"""){ () =>
[info]   //// Express the Regexp above with the code you wish you had
[info]   throw new PendingException()
[info] }
[info] Then("""^I should see "([^"]*)"$"""){ (arg0:String) =>
[info]   //// Express the Regexp above with the code you wish you had
[info]   throw new PendingException()
[info] }
[info] When("""^I fill in "([^"]*)" with "([^"]*)"$"""){ (arg0:String, arg1:String) =>
[info]   //// Express the Regexp above with the code you wish you had
[info]   throw new PendingException()
[info] }
[info] When("""^I push "([^"]*)"$"""){ (arg0:String) =>
[info]   //// Express the Regexp above with the code you wish you had
[info]   throw new PendingException()
[info] }
[info] Then("""^I am in the housework list page$"""){ () =>
[info]   //// Express the Regexp above with the code you wish you had
[info]   throw new PendingException()
[info] }
[success] Total time: 1 s, completed 26/03/2013 19:22:08

tip

Si os da el siguiente error:

D:\projects\Scala\housework>play cucumber
[info] Loading project definition from D:\projects\Scala\housework\project
[info] Set current project to housework (in build file:/D:/projects/Scala/housework/)
[info] Running cucumber...
[error] Exception in thread "main" java.lang.IllegalArgumentException: <strong>Not a file or directory: D:\projects\Scala\housework\prett</strong>y
[error]         at cucumber.runtime.io.FileResourceIterator$FileIterator.<init>(FileResourceIterator.java:54)
[error]         at cucumber.runtime.io.FileResourceIterator.<init>(FileResourceIterator.java:20)
[error]         at cucumber.runtime.io.FileResourceIterable.iterator(FileResourceIterable.java:19)
[error]         at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:38)
[error]         at cucumber.runtime.RuntimeOptions.cucumberFeatures(RuntimeOptions.java:100)
[error]         at cucumber.runtime.Runtime.run(Runtime.java:92)
[error]         at cucumber.api.cli.Main.run(Main.java:20)
[error]         at cucumber.api.cli.Main.main(Main.java:12)
[success] Total time: 1 s, completed 26/03/2013 19:28:56

sólo tenéis que crear una carpeta vacía con el nombre pretty y listo! 😛

Anuncios