SlideShare ist ein Scribd-Unternehmen logo
1 von 36
Downloaden Sie, um offline zu lesen
à la
Sebastian Nozzi
Background
• Working with Java since 2001
• Flirting with Smalltalk all these years
• Involved with Rails since September 2012
• Hooked with Scala since January 2013
• Developing with Play since June 2013
Ruby
Let’s talk about
“A dynamic, open source
programming language with
a focus on simplicity and
productivity.
It has an elegant syntax
that is natural to read and
easy to write.”
Let’s talk about
“Ruby on Rails is an open-
source web framework that’s
optimized for programmer
happiness and sustainable
productivity.
It lets you write beautiful
code by favoring convention
over configuration.”
How Ruby is (self) perceived
• Heavily inspired from Rails
• Fun. Productive. Save + Reload.
• Convention over Configuration.
• Routing. REST. MVC...
• ... but I missed some things ...
ActiveRecord
db:migrate
Cucumber + Capybara
Anorm? Slick?
Evolutions?
Specs?
Rails’ vs. Play’s default offerings
not “railsy” enough
ActiveRecord
db:migrate
Cucumber + Capybara
ActiveRecord (for Scala)
Flyway
Cucumber-JVM +
Fluentlenium
More “Rails-like” alternatives
case class User(var username: String) extends ActiveRecord {
lazy val posts = hasMany[Post]
}
case class Post(var text: String) extends ActiveRecord with
Timestamps {
var userId: Long = _
lazy val user = belongsTo[User]
}
Declaring Entities
object Tables extends ActiveRecordTables {
val users = table[User]("users")
val posts = table[Post]("posts")
}
object User extends ActiveRecordCompanion[User]
object Post extends ActiveRecordCompanion[Post]
Declaring the Schema
val newUser = User(username=“Homer”).create()
val users: List[User] = User.toList
User.findBy(“username”, “Homer”).foreach { user =>
val posts = user.posts.orderBy(_.createdAt desc).toList
...
...
user.posts << Post(“Ohhh donuts!”)
}
Basic Operations
Play Integration
object Global extends GlobalSettings {
override def onStart(app: Application) {
if(!Play.isTest) {
val flyway = new Flyway()
// .. get values from Play’s config ...
flyway.setDataSource(url, user, password)
flyway.setInitOnMigrate(true)
flyway.migrate()
}
Tables.initialize(...) // ActiveRecord
}
}
Triggering the Migrations
object Global extends GlobalSettings {
override def onStart(app: Application) {
if(!Play.isTest) {
val flyway = new Flyway()
// .. get values from Play’s config ...
flyway.setDataSource(url, user, password)
flyway.setInitOnMigrate(true)
flyway.migrate()
}
Tables.initialize(...) // ActiveRecord
}
}
Initializing ActiveRecord
SQL-based Migrations
package db.migration
class V1_03__CreateSomePosts extends JdbcMigration {
override def migrate(ignoredConnection: Connection) {
...
...
...
...
...
}
}
Code-based Migrations
package db.migration
class V1_03__CreateSomePosts extends JdbcMigration {
override def migrate(ignoredConnection: Connection) {
User.findBy("username", "Homer").foreach { homer =>
homer.posts << Post("I'm hungry")
homer.posts << Post("I should go to Moe's")
homer.posts << Post("Or order some Pizza")
}
}
}
Code-based Migrations
+ Fluentlenium
• Write in plain English
• Separation of specification / implementation
Feature: Posting status updates
The goal of the system is keep co-workers
informed by posting status updates.
Background:
Given that user "manager" exists
And that user "manager" posted
| first day at work |
| meeting people |
| working like crazy |
Scenario: Posts are ordered chronologically (newest on top)
When I go to the posts page of user "manager"
Then the post nr. 1 should contain "working"
And the post nr. 2 should contain "meeting"
And the post nr. 3 should contain "first"
When("""^I type "([^"]*)" in the "([^"]*)" field$""") {
(text: String, fieldName: String) =>
...
}
And("""^press "([^"]*)"$""") { (buttonLabel: String) =>
...
...
}
Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) =>
...
...
...
}
Step Declarations
• Part of Play2
• DSL wrapping Selenium
• PhantomJS for headless testing
Fluentlenium
When("""^I type "([^"]*)" in the "([^"]*)" field$""") {
(text: String, fieldName: String) =>
...
}
And("""^press "([^"]*)"$""") { (buttonLabel: String) =>
...
...
}
Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) =>
...
...
...
}
When("""^I type "([^"]*)" in the "([^"]*)" field$""") {
(text: String, fieldName: String) =>
browser.fill("*", withName(fieldName)).`with`(text)
}
And("""^press "([^"]*)"$""") { (buttonLabel: String) =>
val button = browser.find("button", withText(buttonLabel))
button.click()
}
Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) =>
val user = User.findBy("username", username).get
val expectedUrl = controllers.routes.UserActions.posts(user.id).url
driver.getCurrentUrl() should endWith(expectedUrl)
}
Step Implementations
Conclusions
Conclusions
• Satisfied with my choices (so far)
• Integration was doable
• Play flexible enough
• to replace some parts
• to let different libraries co-exist
• Reached a more Rails-like experience
Some Thoughts
Some Thoughts
• Programming can (and should!) be fun
• Scala embraces some of that “fun”
• ... but we can do more
• Go check Ruby / Rails
• Let’s steal get inspired from them ;-)
Thank you

Weitere ähnliche Inhalte

Was ist angesagt?

Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
Kris Wallsmith
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
Masahiro Nagano
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
Michael Peacock
 
Amazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend FrameworkAmazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend Framework
Shahar Evron
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用
Felinx Lee
 

Was ist angesagt? (20)

Deep Dive into AWS CLI - the command line interface
Deep Dive into AWS CLI - the command line interfaceDeep Dive into AWS CLI - the command line interface
Deep Dive into AWS CLI - the command line interface
 
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
Word Play in the Digital Age: Building Text Bots with Tracery
Word Play in the Digital Age: Building Text Bots with TraceryWord Play in the Digital Age: Building Text Bots with Tracery
Word Play in the Digital Age: Building Text Bots with Tracery
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Amazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend FrameworkAmazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend Framework
 
Getting Started with Microsoft Bot Framework
Getting Started with Microsoft Bot FrameworkGetting Started with Microsoft Bot Framework
Getting Started with Microsoft Bot Framework
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用
 
Realm: Building a mobile database
Realm: Building a mobile databaseRealm: Building a mobile database
Realm: Building a mobile database
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 

Ähnlich wie Play á la Rails

wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
Mat Schaffer
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
Nick Sieger
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails Bootcamp
Mat Schaffer
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
zefhemel
 
Nosql hands on handout 04
Nosql hands on handout 04Nosql hands on handout 04
Nosql hands on handout 04
Krishna Sankar
 
Terrastore - A document database for developers
Terrastore - A document database for developersTerrastore - A document database for developers
Terrastore - A document database for developers
Sergio Bossa
 

Ähnlich wie Play á la Rails (20)

wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
 
How to React Native
How to React NativeHow to React Native
How to React Native
 
PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails Bootcamp
 
Play framework
Play frameworkPlay framework
Play framework
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
Full Stack Scala
Full Stack ScalaFull Stack Scala
Full Stack Scala
 
Node.js
Node.jsNode.js
Node.js
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
 
Nosql hands on handout 04
Nosql hands on handout 04Nosql hands on handout 04
Nosql hands on handout 04
 
Terrastore - A document database for developers
Terrastore - A document database for developersTerrastore - A document database for developers
Terrastore - A document database for developers
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
mobl
moblmobl
mobl
 
AkJS Meetup - ES6++
AkJS Meetup -  ES6++AkJS Meetup -  ES6++
AkJS Meetup - ES6++
 

Kürzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Kürzlich hochgeladen (20)

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 

Play á la Rails

  • 2. Background • Working with Java since 2001 • Flirting with Smalltalk all these years • Involved with Rails since September 2012 • Hooked with Scala since January 2013 • Developing with Play since June 2013
  • 4.
  • 5. “A dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.”
  • 7.
  • 8. “Ruby on Rails is an open- source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration.”
  • 9. How Ruby is (self) perceived
  • 10. • Heavily inspired from Rails • Fun. Productive. Save + Reload. • Convention over Configuration. • Routing. REST. MVC... • ... but I missed some things ...
  • 11. ActiveRecord db:migrate Cucumber + Capybara Anorm? Slick? Evolutions? Specs? Rails’ vs. Play’s default offerings
  • 13. ActiveRecord db:migrate Cucumber + Capybara ActiveRecord (for Scala) Flyway Cucumber-JVM + Fluentlenium More “Rails-like” alternatives
  • 14.
  • 15. case class User(var username: String) extends ActiveRecord { lazy val posts = hasMany[Post] } case class Post(var text: String) extends ActiveRecord with Timestamps { var userId: Long = _ lazy val user = belongsTo[User] } Declaring Entities
  • 16. object Tables extends ActiveRecordTables { val users = table[User]("users") val posts = table[Post]("posts") } object User extends ActiveRecordCompanion[User] object Post extends ActiveRecordCompanion[Post] Declaring the Schema
  • 17. val newUser = User(username=“Homer”).create() val users: List[User] = User.toList User.findBy(“username”, “Homer”).foreach { user => val posts = user.posts.orderBy(_.createdAt desc).toList ... ... user.posts << Post(“Ohhh donuts!”) } Basic Operations
  • 18.
  • 20. object Global extends GlobalSettings { override def onStart(app: Application) { if(!Play.isTest) { val flyway = new Flyway() // .. get values from Play’s config ... flyway.setDataSource(url, user, password) flyway.setInitOnMigrate(true) flyway.migrate() } Tables.initialize(...) // ActiveRecord } } Triggering the Migrations
  • 21. object Global extends GlobalSettings { override def onStart(app: Application) { if(!Play.isTest) { val flyway = new Flyway() // .. get values from Play’s config ... flyway.setDataSource(url, user, password) flyway.setInitOnMigrate(true) flyway.migrate() } Tables.initialize(...) // ActiveRecord } } Initializing ActiveRecord
  • 23. package db.migration class V1_03__CreateSomePosts extends JdbcMigration { override def migrate(ignoredConnection: Connection) { ... ... ... ... ... } } Code-based Migrations
  • 24. package db.migration class V1_03__CreateSomePosts extends JdbcMigration { override def migrate(ignoredConnection: Connection) { User.findBy("username", "Homer").foreach { homer => homer.posts << Post("I'm hungry") homer.posts << Post("I should go to Moe's") homer.posts << Post("Or order some Pizza") } } } Code-based Migrations
  • 26. • Write in plain English • Separation of specification / implementation
  • 27. Feature: Posting status updates The goal of the system is keep co-workers informed by posting status updates. Background: Given that user "manager" exists And that user "manager" posted | first day at work | | meeting people | | working like crazy | Scenario: Posts are ordered chronologically (newest on top) When I go to the posts page of user "manager" Then the post nr. 1 should contain "working" And the post nr. 2 should contain "meeting" And the post nr. 3 should contain "first"
  • 28. When("""^I type "([^"]*)" in the "([^"]*)" field$""") { (text: String, fieldName: String) => ... } And("""^press "([^"]*)"$""") { (buttonLabel: String) => ... ... } Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) => ... ... ... } Step Declarations
  • 29. • Part of Play2 • DSL wrapping Selenium • PhantomJS for headless testing Fluentlenium
  • 30. When("""^I type "([^"]*)" in the "([^"]*)" field$""") { (text: String, fieldName: String) => ... } And("""^press "([^"]*)"$""") { (buttonLabel: String) => ... ... } Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) => ... ... ... }
  • 31. When("""^I type "([^"]*)" in the "([^"]*)" field$""") { (text: String, fieldName: String) => browser.fill("*", withName(fieldName)).`with`(text) } And("""^press "([^"]*)"$""") { (buttonLabel: String) => val button = browser.find("button", withText(buttonLabel)) button.click() } Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) => val user = User.findBy("username", username).get val expectedUrl = controllers.routes.UserActions.posts(user.id).url driver.getCurrentUrl() should endWith(expectedUrl) } Step Implementations
  • 33. Conclusions • Satisfied with my choices (so far) • Integration was doable • Play flexible enough • to replace some parts • to let different libraries co-exist • Reached a more Rails-like experience
  • 35. Some Thoughts • Programming can (and should!) be fun • Scala embraces some of that “fun” • ... but we can do more • Go check Ruby / Rails • Let’s steal get inspired from them ;-)