SlideShare uma empresa Scribd logo
1 de 48
Baixar para ler offline
INTEGRATION TESTING
WITH SCALATEST,
MONGODB AND PLAY!
EXPERIENCE FROM PLAY! PROJECT
By /Michal Bigos @teliatko
AGENDA
1. Integration testing, why and when
2. ScalaTest for integration testing with MongoDB and Play!
3. Custom DSL for integration testing and small extensions to
Casbah
CONTEXT
FROM WHERE THIS ALL CAME FROM...
Social network application with mobile clients
Build on top of Play! 2
Core API = REST services
MongoDB used as main persistent store
Hosted on Heroku
Currently in beta
INTEGRATION TESTING, WHY AND WHEN?
PART ONE
DEFINITION
Wikipedia:
“ The phase in software testing in which
individual software modules are combined
and tested as a group. ”
ANOTHER ONE :)
Arquillian:
“ Testing business components, in particular,
can be very challenging. Often, a vanilla unit
test isn't sufficient for validating such a
component's behavior. Why is that? The
reason is that components in an enterprise
application rarely perform operations which
are strictly self-contained. Instead, they
interact with or provide services for the
greater system. ”
UNIT TESTS 'VS' INTEGRATION TESTS
UNIT TESTS PROPERTIES:
Isolated - Checking one single concern in the system. Usually
behavior of one class.
Repeateable - It can be rerun as meny times as you want.
Consistent - Every run gets the same results.
Fast - Because there are loooot of them.
UNIT TESTS 'VS' INTEGRATION TESTS
UNIT TESTS TECHNIQUES:
Mocking
Stubing
xUnit frameworks
Fixtures in code
UNIT TESTS 'VS' INTEGRATION TESTS
INTEGRATION TESTS PROPERTIES:
Not isolated - Do not check the component or class itself, but
rather integrated components together (sometimes whole
application).
Slow - Depend on the tested component/sub-system.
UNIT TESTS 'VS' INTEGRATION TESTS
VARIOUS INTEGRATION TESTS TYPES:
Data-driven tests - Use real data and persistent store.
In-container tests - Simulates real container deployment,
e.g. JEE one.
Performance tests - Simulate traffic growth.
Acceptance tests - Simulate use cases from user point of
view.
UNIT TESTS 'VS' INTEGRATION TESTS
KNOWN FRAMEWORKS:
Data-driven tests - DBUnit, NoSQL Unit...
In-container tests - Arquillian...
Performance tests - JMeter...
Acceptance tests - Selenium, Cucumber...
WHY AND WHEN ?
WHAT CANNOT BE WRITTEN/SIMULATED IN UNIT TEST
Interaction with resources or sub-systems provided by
container.
Interaction with external systems.
Usage of declarative services applied to component at
runtime.
Testing whole scenarions in one test.
Architectural constraints limits isolation.
OUR CASE
ARCHITECTURAL CONSTRAINTS LIMITING ISOLATION:
Lack of DI
Controller depends directly on DAO
object CheckIns extends Controller {
...
def generate(pubId: String) = Secured.withBasic { caller: User =>
Action { implicit request =>
val pubOpt = PubDao.findOneById(pubId)
...
}
}
}
object PubDao extends SalatDAO[Pub, ObjectId](MongoDBSetup.mongoDB("pubs
")) {
...
}
OUR CASE
DEPENDENCIES BETWEEN COMPONENTS:
OUR CASE
GOALS:
Integration tests with real DAOs and DB
Writing them like unit tests
SCALATEST FOR INTEGRATION TESTING WITH
MONGODB AND PLAY!
PART TWO
TESTING STRATEGY
Responsibility - encapsulate domain logic
Unit test - testing the correctness of domain logic
TESTING STRATEGY
Responsibility - read/save model
Integration test - testing the correctness of queries and
modifications, with real data and DB
TESTING STRATEGY
Responsibility - serialize/deserialize model to JSON
Integration test - testing the correctness of JSON output,
using the real DAOs
TESTING FRAMEWORKS
SCALATEST
Standalone xUnit framework
Can be used within JUnit, TestNG...
Pretty DSLs for writing test, especially FreeSpec
Personal preference over specs2
Hooks for integration testing BeforeAndAfterand
BeforeAndAfterAlltraits
TESTING FRAMEWORKS
PLAY!'S TESTING SUPPORT
Fake application
Real HTTP server
it should "Test something dependent on Play! application" in {
running(FakeApplication()) {
// Do something which depends on Play! application
}
}
"run in a server" in {
running(TestServer(3333)) {
await(WS.url("http://localhost:3333").get).status must equalTo(OK)
}
}
TESTING FRAMEWORKS
DATA-DRIVEN TESTS FOR MONGODB
- Mock implementation of the MongoDB
protocol and works purely in-memory.
- More general library for testing with various
NoSQL stores. It can provide mocked or real MongoDB
instance. Relies on JUnit rules.
- Platform independent way of running local
MongoDB instances.
jmockmongo
NoSQL Unit
EmbedMongo
APPLICATION CODE
Configuration of MongoDB in application
... another object
trait MongoDBSetup {
val MONGODB_URL = "mongoDB.url"
val MONGODB_PORT = "mongoDB.port"
val MONGODB_DB = "mongoDB.db"
}
object MongoDBSetup extends MongoDBSetup {
private[this] val conf = current.configuration
val url = conf.getString(MONGODB_URL).getOrElse(...)
val port = conf.getInt(MONGODB_PORT).getOrElse(...)
val db = conf.getString(MONGODB_DB).getOrElse(...)
val mongoDB = MongoConnection(url, port)(db)
}
APPLICATION CODE
Use of MongoDBSetupin DAOs
We have to mock or provide real DB to test the DAO
object PubDao extends SalatDAO[Pub, ObjectId](MongoDBSetup.mongoDB("pubs
")) {
...
}
APPLICATION CODE
Controllers
... you've seen this already
object CheckIns extends Controller {
...
def generate(pubId: String) = Secured.withBasic { caller: User =>
Action { implicit request =>
val pubOpt = PubDao.findOneById(pubId)
...
}
}
}
OUR SOLUTION
Embedding * to ScalaTestembedmongo
trait EmbedMongoDB extends BeforeAndAfterAll { this: BeforeAndAfterAll with Suite =>
def embedConnectionURL: String = { "localhost" }
def embedConnectionPort: Int = { 12345 }
def embedMongoDBVersion: Version = { Version.V2_2_1 }
def embedDB: String = { "test" }
lazy val runtime: MongodStarter = MongodStarter.getDefaultInstance
lazy val mongodExe: MongodExecutable = runtime.prepare(new MongodConfig(embedMongoDBV
ersion, embedConnectionPort, true))
lazy val mongod: MongodProcess = mongodExe.start()
override def beforeAll() {
mongod
super.beforeAll()
}
override def afterAll() {
super.afterAll()
mongod.stop(); mongodExe.stop()
}
lazy val mongoDB = MongoConnection(embedConnectionURL, embedConnectionPort)(embedDB)
}
*we love recursion in Scala isn't it?
OUR SOLUTION
Custom fake application
Trait configures fake application instance for embedded
MongoDB instance. MongoDBSetupconsumes this values.
trait FakeApplicationForMongoDB extends MongoDBSetup { this: EmbedMongoDB =>
lazy val fakeApplicationWithMongo = FakeApplication(additionalConfiguration = Map(
MONGODB_PORT -> embedConnectionPort.toString,
MONGODB_URL -> embedConnectionURL,
MONGODB_DB -> embedDB
))
}
OUR SOLUTION
Typical test suite class
class DataDrivenMongoDBTest extends FlatSpec
with ShouldMatchers
with MustMatchers
with EmbedMongoDB
with FakeApplicationForMongoDB {
...
}
OUR SOLUTION
Test method which uses mongoDBinstance directly
it should "Save and read an Object to/from MongoDB" in {
// Given
val users = mongoDB("users") // this is from EmbedMongoDB trait
// When
val user = User(username = username, password = password)
users += grater[User].asDBObject(user)
// Then
users.count should equal (1L)
val query = MongoDBObject("username" -> username)
users.findOne(query).map(grater[User].asObject(_)) must equal (Some(user))
// Clean-up
users.dropCollection()
}
OUR SOLUTION
Test method which uses DAO via
fakeApplicationWithMongo
it should "Save and read an Object to/from MongoDB which is used in application" in {
running(fakeApplicationWithMongo) {
// Given
val user = User(username = username, password = password)
// When
UserDao.save(user)
// Then
UserDao.findAll().find(_ == user) must equal (Some(user))
}
}
OUR SOLUTION
Example of the full test from controller down to model
class FullWSTest extends FlatSpec with ShouldMatchers with MustMatchers with EmbedMongo
DB with FakeApplicationForMongoDB {
val username = "test"
val password = "secret"
val userJson = """{"id":"%s","firstName":"","lastName":"","age":-1,"gender":-1,"state
":"notFriends","photoUrl":""}"""
"Detail method" should "return correct Json for User" in {
running(TestServer(3333, fakeApplicationWithMongo)) {
val users = mongoDB("users")
val user = User(username = username, password = md5(username + password))
users += grater[User].asDBObject(user)
val userId = user.id.toString
val response = await(WS.url("http://localhost:3333/api/user/" + userId)
.withAuth(username, password, AuthScheme.BASIC)
.get())
response.status must equal (OK)
response.header("Content-Type") must be (Some("application/json; charset=utf-8"))
response.body must include (userJson.format(userId))
}
}
}
CUSTOM DSL FOR INTEGRATION TESTING AND
SMALL EXTENSIONS TO CASBAH
PART THREE
WORK IN PROGRESS
MORE DATA
Creating a simple data is easy, but what about collections...
We need easy way to seed them from prepared source and
check them afterwards.
CUSTOM DSL FOR SEEDING THE DATA
Principle
Seed the data before test
Use them in test ... read, create or modify
Check them after test (optional)
CUSTOM DSL FOR SEEDING THE DATA
Inspiration - ,
Based on JUnit rules or verbose code
NoSQL Unit DBUnit
public class WhenANewBookIsCreated {
@ClassRule
public static ManagedMongoDb managedMongoDb = newManagedMongoDbRule().mongodPath("/
opt/mongo").build();
@Rule
public MongoDbRule remoteMongoDbRule = new MongoDbRule(mongoDb().databaseName("test
").build());
@Test
@UsingDataSet(locations="initialData.json", loadStrategy=LoadStrategyEnum.CLEAN_INS
ERT)
@ShouldMatchDataSet(location="expectedData.json")
public void book_should_be_inserted_into_repository() {
...
}
}
This is Java. Example is taken from NoSQL Unit documentation.
CUSTOM DSL FOR SEEDING THE DATA
Goals
Pure functional solution
Better fit with ScalaTest
JUnit independent
CUSTOM DSL FOR SEEDING THE DATA
Result
it should "Load all Objcts from MongoDB" in {
mongoDB seed ("users") fromFile ("./database/data/users.json") and
seed ("pubs") fromFile ("./database/data/pubs.json")
cleanUpAfter {
running(fakeApplicationWithMongo) {
val users = UserDao.findAll()
users.size must equal (10)
}
}
// Probably will be deprecated in next versions
mongoDB seed ("users") fromFile ("./database/data/users.json") now()
running(fakeApplicationWithMongo) {
val users = UserDao.findAll()
users.size must equal (10)
}
mongoDB cleanUp ("users")
}
CUSTOM DSL FOR SEEDING THE DATA
Already implemented
Seeding, clean-up and clean-up after for functional and
non-funtional usage.
JSON fileformat similar to NoSQL Unit - difference, per
collection basis.
CUSTOM DSL FOR SEEDING THE DATA
Still in pipeline
Checking against dataset, similar to
@ShouldMatchDataSet annotation of NoSQL Unit.
JS file format of mongoexport. Our biggest problem here
are Dates (proprietary format).
JS file format with full JavaScript functionality of mongo
command. To be able to run commands like:
db.pubs.ensureIndex({loc : "2d"})
NoSQL Unit JSON file format with multiple collections and
seeding more collections in once.
TOPPING
SMALL ADDITIONS TO CASBAH FOR BETTER QUERY SYNTAX
We don't like this*
... I cannot read it, can't you?
* and when possible we don't write this
def findCheckInsBetweenDatesInPub(
pubId: String,
dateFrom: LocalDateTime,
dateTo: LocalDateTime) : List[CheckIn] = {
val query = MongoDBObject("pubId" -> new ObjectId(pubId), "created" ->
MongoDBObject("$gte" -> dateFrom, "$lt" -> dateTo))
collection.find(query).map(grater[CheckIn].asObject(_)).toList.headOpt
ion
}
TOPPING
SMALL ADDITIONS TO CASBAH FOR BETTER QUERY SYNTAX
We like pretty code a lot ... like this:
Casbah query DSL is our favorite ... even when it is not
perfect
def findBetweenDatesForPub(pubId: ObjectId, from: DateTime, to: DateTime
) : List[CheckIn] = {
find {
("pubId" -> pubId) ++
("created" $gte from $lt to)
} sort {
("created" -> -1)
}
}.toList.headOption
TOPPING
SMALL ADDITIONS TO CASBAH FOR BETTER QUERY SYNTAX
So we enhanced it:
def findBetweenDatesForPub(pubId: ObjectId, from: DateTime, to: DateTime
) : List[CheckIn] = {
find {
("pubId" $eq pubId) ++
("created" $gte from $lt to)
} sort {
"created" $eq -1
}
}.headOption
TOPPING
SMALL ADDITIONS TO CASBAH FOR BETTER QUERY
Pimp my library again and again...
// Adds $eq operator instead of ->
implicit def queryOperatorAdditions(field: String) = new {
protected val _field = field
} with EqualsOp
trait EqualsOp {
protected def _field: String
def $eq[T](target: T) = MongoDBObject(_field -> target)
}
// Adds Scala collection headOption operation to SalatCursor
implicit def cursorAdditions[T <: AnyRef](cursor: SalatMongoCursor[T]) = new {
protected val _cursor = cursor
} with CursorOperations[T]
trait CursorOperations[T <: AnyRef] {
protected def _cursor: SalatMongoCursor[T]
def headOption : Option[T] = if (_cursor.hasNext) Some(_cursor.next()) else None
}
THANKS FOR YOUR ATTENTION

Mais conteúdo relacionado

Mais procurados

Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQueryKnoldus Inc.
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit TestChiew Carol
 
PHP Unit Testing in Yii
PHP Unit Testing in YiiPHP Unit Testing in Yii
PHP Unit Testing in YiiIlPeach
 
Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012Hazem Saleh
 
Automated php unit testing in drupal 8
Automated php unit testing in drupal 8Automated php unit testing in drupal 8
Automated php unit testing in drupal 8Jay Friendly
 
Tellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.TestingTellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.TestingJohn.Jian.Fang
 
Test all the things! Automated testing with Drupal 8
Test all the things! Automated testing with Drupal 8Test all the things! Automated testing with Drupal 8
Test all the things! Automated testing with Drupal 8Sam Becker
 
Codeception presentation
Codeception presentationCodeception presentation
Codeception presentationAndrei Burian
 
Unit-testing and E2E testing in JS
Unit-testing and E2E testing in JSUnit-testing and E2E testing in JS
Unit-testing and E2E testing in JSMichael Haberman
 
081107 Sammy Eclipse Summit2
081107   Sammy   Eclipse Summit2081107   Sammy   Eclipse Summit2
081107 Sammy Eclipse Summit2mkempka
 
Ten Minutes To Tellurium
Ten Minutes To TelluriumTen Minutes To Tellurium
Ten Minutes To TelluriumJohn.Jian.Fang
 
Protractor Testing Automation Tool Framework / Jasmine Reporters
Protractor Testing Automation Tool Framework / Jasmine ReportersProtractor Testing Automation Tool Framework / Jasmine Reporters
Protractor Testing Automation Tool Framework / Jasmine ReportersHaitham Refaat
 
Automated Smoke Tests with Protractor
Automated Smoke Tests with ProtractorAutomated Smoke Tests with Protractor
Automated Smoke Tests with Protractor🌱 Dale Spoonemore
 
Automation testing with Drupal 8
Automation testing with Drupal 8Automation testing with Drupal 8
Automation testing with Drupal 8nagpalprachi
 
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debuggingATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debuggingAgile Testing Alliance
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java DevelopersYakov Fain
 
Advanced Selenium Workshop
Advanced Selenium WorkshopAdvanced Selenium Workshop
Advanced Selenium WorkshopClever Moe
 
Selenium interview questions and answers
Selenium interview questions and answersSelenium interview questions and answers
Selenium interview questions and answerskavinilavuG
 

Mais procurados (20)

Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit Test
 
Codeception
CodeceptionCodeception
Codeception
 
PHP Unit Testing in Yii
PHP Unit Testing in YiiPHP Unit Testing in Yii
PHP Unit Testing in Yii
 
Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012
 
Automated php unit testing in drupal 8
Automated php unit testing in drupal 8Automated php unit testing in drupal 8
Automated php unit testing in drupal 8
 
Tellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.TestingTellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.Testing
 
Test all the things! Automated testing with Drupal 8
Test all the things! Automated testing with Drupal 8Test all the things! Automated testing with Drupal 8
Test all the things! Automated testing with Drupal 8
 
Codeception presentation
Codeception presentationCodeception presentation
Codeception presentation
 
Unit-testing and E2E testing in JS
Unit-testing and E2E testing in JSUnit-testing and E2E testing in JS
Unit-testing and E2E testing in JS
 
Selenium Overview
Selenium OverviewSelenium Overview
Selenium Overview
 
081107 Sammy Eclipse Summit2
081107   Sammy   Eclipse Summit2081107   Sammy   Eclipse Summit2
081107 Sammy Eclipse Summit2
 
Ten Minutes To Tellurium
Ten Minutes To TelluriumTen Minutes To Tellurium
Ten Minutes To Tellurium
 
Protractor Testing Automation Tool Framework / Jasmine Reporters
Protractor Testing Automation Tool Framework / Jasmine ReportersProtractor Testing Automation Tool Framework / Jasmine Reporters
Protractor Testing Automation Tool Framework / Jasmine Reporters
 
Automated Smoke Tests with Protractor
Automated Smoke Tests with ProtractorAutomated Smoke Tests with Protractor
Automated Smoke Tests with Protractor
 
Automation testing with Drupal 8
Automation testing with Drupal 8Automation testing with Drupal 8
Automation testing with Drupal 8
 
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debuggingATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
Advanced Selenium Workshop
Advanced Selenium WorkshopAdvanced Selenium Workshop
Advanced Selenium Workshop
 
Selenium interview questions and answers
Selenium interview questions and answersSelenium interview questions and answers
Selenium interview questions and answers
 

Semelhante a Integration Testing With ScalaTest and MongoDB

Test Automation for NoSQL Databases
Test Automation for NoSQL DatabasesTest Automation for NoSQL Databases
Test Automation for NoSQL DatabasesTobias Trelle
 
Will your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry GervinWill your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry GervinBarry Gervin
 
Knockoutjs databinding
Knockoutjs databindingKnockoutjs databinding
Knockoutjs databindingBoulos Dib
 
Bringing the light to the client with KnockoutJS
Bringing the light to the client with KnockoutJSBringing the light to the client with KnockoutJS
Bringing the light to the client with KnockoutJSBoyan Mihaylov
 
MVC pattern for widgets
MVC pattern for widgetsMVC pattern for widgets
MVC pattern for widgetsBehnam Taraghi
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e bigAndy Peterson
 
Testing the frontend
Testing the frontendTesting the frontend
Testing the frontendHeiko Hardt
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
EJB et WS (Montreal JUG - 12 mai 2011)
EJB et WS (Montreal JUG - 12 mai 2011)EJB et WS (Montreal JUG - 12 mai 2011)
EJB et WS (Montreal JUG - 12 mai 2011)Montreal JUG
 
Android Unit Test
Android Unit TestAndroid Unit Test
Android Unit TestPhuoc Bui
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsHassan Abid
 
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
BDD, ATDD, Page Objects: The Road to Sustainable Web TestingBDD, ATDD, Page Objects: The Road to Sustainable Web Testing
BDD, ATDD, Page Objects: The Road to Sustainable Web TestingJohn Ferguson Smart Limited
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsReact Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsMatteo Manchi
 
Dependency injection in scala
Dependency injection in scalaDependency injection in scala
Dependency injection in scalaMichal Bigos
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
Testing your application on Google App Engine
Testing your application on Google App EngineTesting your application on Google App Engine
Testing your application on Google App EngineInphina Technologies
 
Testing Your Application On Google App Engine
Testing Your Application On Google App EngineTesting Your Application On Google App Engine
Testing Your Application On Google App EngineIndicThreads
 

Semelhante a Integration Testing With ScalaTest and MongoDB (20)

Test Automation for NoSQL Databases
Test Automation for NoSQL DatabasesTest Automation for NoSQL Databases
Test Automation for NoSQL Databases
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
Will your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry GervinWill your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry Gervin
 
Knockoutjs databinding
Knockoutjs databindingKnockoutjs databinding
Knockoutjs databinding
 
Bringing the light to the client with KnockoutJS
Bringing the light to the client with KnockoutJSBringing the light to the client with KnockoutJS
Bringing the light to the client with KnockoutJS
 
MVC pattern for widgets
MVC pattern for widgetsMVC pattern for widgets
MVC pattern for widgets
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
 
Testing the frontend
Testing the frontendTesting the frontend
Testing the frontend
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
EJB et WS (Montreal JUG - 12 mai 2011)
EJB et WS (Montreal JUG - 12 mai 2011)EJB et WS (Montreal JUG - 12 mai 2011)
EJB et WS (Montreal JUG - 12 mai 2011)
 
Android Unit Test
Android Unit TestAndroid Unit Test
Android Unit Test
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
BDD, ATDD, Page Objects: The Road to Sustainable Web TestingBDD, ATDD, Page Objects: The Road to Sustainable Web Testing
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsReact Native for multi-platform mobile applications
React Native for multi-platform mobile applications
 
Data access
Data accessData access
Data access
 
Dependency injection in scala
Dependency injection in scalaDependency injection in scala
Dependency injection in scala
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Testing your application on Google App Engine
Testing your application on Google App EngineTesting your application on Google App Engine
Testing your application on Google App Engine
 
Testing Your Application On Google App Engine
Testing Your Application On Google App EngineTesting Your Application On Google App Engine
Testing Your Application On Google App Engine
 

Último

Lilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptxLilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptxABMWeaklings
 
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girlsPooja Nehwal
 
Call Girls In Andheri East Call US Pooja📞 9892124323 Book Hot And
Call Girls In Andheri East Call US Pooja📞 9892124323 Book Hot AndCall Girls In Andheri East Call US Pooja📞 9892124323 Book Hot And
Call Girls In Andheri East Call US Pooja📞 9892124323 Book Hot AndPooja Nehwal
 
办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改
办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改
办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改atducpo
 
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual serviceanilsa9823
 
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改atducpo
 
Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...
Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...
Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...Leko Durda
 
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝soniya singh
 
CALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female serviceanilsa9823
 
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...ur8mqw8e
 
call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..nishakur201
 
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,dollysharma2066
 
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual serviceanilsa9823
 
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdfREFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdfssusere8ea60
 
Postal Ballot procedure for employees to utilise
Postal Ballot procedure for employees to utilisePostal Ballot procedure for employees to utilise
Postal Ballot procedure for employees to utiliseccsubcollector
 
Dhule Call Girls #9907093804 Contact Number Escorts Service Dhule
Dhule Call Girls #9907093804 Contact Number Escorts Service DhuleDhule Call Girls #9907093804 Contact Number Escorts Service Dhule
Dhule Call Girls #9907093804 Contact Number Escorts Service Dhulesrsj9000
 
The Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by MindbrushThe Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by MindbrushShivain97
 
Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666nishakur201
 

Último (20)

Lilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptxLilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptx
 
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
 
Call Girls In Andheri East Call US Pooja📞 9892124323 Book Hot And
Call Girls In Andheri East Call US Pooja📞 9892124323 Book Hot AndCall Girls In Andheri East Call US Pooja📞 9892124323 Book Hot And
Call Girls In Andheri East Call US Pooja📞 9892124323 Book Hot And
 
办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改
办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改
办理国外毕业证学位证《原版美国montana文凭》蒙大拿州立大学毕业证制作成绩单修改
 
Model Call Girl in Lado Sarai Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Lado Sarai Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Lado Sarai Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Lado Sarai Delhi reach out to us at 🔝9953056974🔝
 
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
 
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
 
Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...
Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...
Reinventing Corporate Philanthropy_ Strategies for Meaningful Impact by Leko ...
 
escort service sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974
escort service  sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974escort service  sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974
escort service sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974
 
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
 
CALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Adil Nagar Lucknow best Female service
 
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
 
call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..
 
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
 
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
 
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdfREFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
 
Postal Ballot procedure for employees to utilise
Postal Ballot procedure for employees to utilisePostal Ballot procedure for employees to utilise
Postal Ballot procedure for employees to utilise
 
Dhule Call Girls #9907093804 Contact Number Escorts Service Dhule
Dhule Call Girls #9907093804 Contact Number Escorts Service DhuleDhule Call Girls #9907093804 Contact Number Escorts Service Dhule
Dhule Call Girls #9907093804 Contact Number Escorts Service Dhule
 
The Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by MindbrushThe Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by Mindbrush
 
Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666
 

Integration Testing With ScalaTest and MongoDB

  • 1. INTEGRATION TESTING WITH SCALATEST, MONGODB AND PLAY! EXPERIENCE FROM PLAY! PROJECT By /Michal Bigos @teliatko
  • 2. AGENDA 1. Integration testing, why and when 2. ScalaTest for integration testing with MongoDB and Play! 3. Custom DSL for integration testing and small extensions to Casbah
  • 3. CONTEXT FROM WHERE THIS ALL CAME FROM... Social network application with mobile clients Build on top of Play! 2 Core API = REST services MongoDB used as main persistent store Hosted on Heroku Currently in beta
  • 4. INTEGRATION TESTING, WHY AND WHEN? PART ONE
  • 5. DEFINITION Wikipedia: “ The phase in software testing in which individual software modules are combined and tested as a group. ”
  • 6. ANOTHER ONE :) Arquillian: “ Testing business components, in particular, can be very challenging. Often, a vanilla unit test isn't sufficient for validating such a component's behavior. Why is that? The reason is that components in an enterprise application rarely perform operations which are strictly self-contained. Instead, they interact with or provide services for the greater system. ”
  • 7. UNIT TESTS 'VS' INTEGRATION TESTS UNIT TESTS PROPERTIES: Isolated - Checking one single concern in the system. Usually behavior of one class. Repeateable - It can be rerun as meny times as you want. Consistent - Every run gets the same results. Fast - Because there are loooot of them.
  • 8. UNIT TESTS 'VS' INTEGRATION TESTS UNIT TESTS TECHNIQUES: Mocking Stubing xUnit frameworks Fixtures in code
  • 9. UNIT TESTS 'VS' INTEGRATION TESTS INTEGRATION TESTS PROPERTIES: Not isolated - Do not check the component or class itself, but rather integrated components together (sometimes whole application). Slow - Depend on the tested component/sub-system.
  • 10. UNIT TESTS 'VS' INTEGRATION TESTS VARIOUS INTEGRATION TESTS TYPES: Data-driven tests - Use real data and persistent store. In-container tests - Simulates real container deployment, e.g. JEE one. Performance tests - Simulate traffic growth. Acceptance tests - Simulate use cases from user point of view.
  • 11. UNIT TESTS 'VS' INTEGRATION TESTS KNOWN FRAMEWORKS: Data-driven tests - DBUnit, NoSQL Unit... In-container tests - Arquillian... Performance tests - JMeter... Acceptance tests - Selenium, Cucumber...
  • 12. WHY AND WHEN ? WHAT CANNOT BE WRITTEN/SIMULATED IN UNIT TEST Interaction with resources or sub-systems provided by container. Interaction with external systems. Usage of declarative services applied to component at runtime. Testing whole scenarions in one test. Architectural constraints limits isolation.
  • 13. OUR CASE ARCHITECTURAL CONSTRAINTS LIMITING ISOLATION: Lack of DI Controller depends directly on DAO object CheckIns extends Controller { ... def generate(pubId: String) = Secured.withBasic { caller: User => Action { implicit request => val pubOpt = PubDao.findOneById(pubId) ... } } } object PubDao extends SalatDAO[Pub, ObjectId](MongoDBSetup.mongoDB("pubs ")) { ... }
  • 14.
  • 16. OUR CASE GOALS: Integration tests with real DAOs and DB Writing them like unit tests
  • 17. SCALATEST FOR INTEGRATION TESTING WITH MONGODB AND PLAY! PART TWO
  • 18. TESTING STRATEGY Responsibility - encapsulate domain logic Unit test - testing the correctness of domain logic
  • 19. TESTING STRATEGY Responsibility - read/save model Integration test - testing the correctness of queries and modifications, with real data and DB
  • 20. TESTING STRATEGY Responsibility - serialize/deserialize model to JSON Integration test - testing the correctness of JSON output, using the real DAOs
  • 21. TESTING FRAMEWORKS SCALATEST Standalone xUnit framework Can be used within JUnit, TestNG... Pretty DSLs for writing test, especially FreeSpec Personal preference over specs2 Hooks for integration testing BeforeAndAfterand BeforeAndAfterAlltraits
  • 22. TESTING FRAMEWORKS PLAY!'S TESTING SUPPORT Fake application Real HTTP server it should "Test something dependent on Play! application" in { running(FakeApplication()) { // Do something which depends on Play! application } } "run in a server" in { running(TestServer(3333)) { await(WS.url("http://localhost:3333").get).status must equalTo(OK) } }
  • 23. TESTING FRAMEWORKS DATA-DRIVEN TESTS FOR MONGODB - Mock implementation of the MongoDB protocol and works purely in-memory. - More general library for testing with various NoSQL stores. It can provide mocked or real MongoDB instance. Relies on JUnit rules. - Platform independent way of running local MongoDB instances. jmockmongo NoSQL Unit EmbedMongo
  • 24. APPLICATION CODE Configuration of MongoDB in application ... another object trait MongoDBSetup { val MONGODB_URL = "mongoDB.url" val MONGODB_PORT = "mongoDB.port" val MONGODB_DB = "mongoDB.db" } object MongoDBSetup extends MongoDBSetup { private[this] val conf = current.configuration val url = conf.getString(MONGODB_URL).getOrElse(...) val port = conf.getInt(MONGODB_PORT).getOrElse(...) val db = conf.getString(MONGODB_DB).getOrElse(...) val mongoDB = MongoConnection(url, port)(db) }
  • 25. APPLICATION CODE Use of MongoDBSetupin DAOs We have to mock or provide real DB to test the DAO object PubDao extends SalatDAO[Pub, ObjectId](MongoDBSetup.mongoDB("pubs ")) { ... }
  • 26. APPLICATION CODE Controllers ... you've seen this already object CheckIns extends Controller { ... def generate(pubId: String) = Secured.withBasic { caller: User => Action { implicit request => val pubOpt = PubDao.findOneById(pubId) ... } } }
  • 27. OUR SOLUTION Embedding * to ScalaTestembedmongo trait EmbedMongoDB extends BeforeAndAfterAll { this: BeforeAndAfterAll with Suite => def embedConnectionURL: String = { "localhost" } def embedConnectionPort: Int = { 12345 } def embedMongoDBVersion: Version = { Version.V2_2_1 } def embedDB: String = { "test" } lazy val runtime: MongodStarter = MongodStarter.getDefaultInstance lazy val mongodExe: MongodExecutable = runtime.prepare(new MongodConfig(embedMongoDBV ersion, embedConnectionPort, true)) lazy val mongod: MongodProcess = mongodExe.start() override def beforeAll() { mongod super.beforeAll() } override def afterAll() { super.afterAll() mongod.stop(); mongodExe.stop() } lazy val mongoDB = MongoConnection(embedConnectionURL, embedConnectionPort)(embedDB) }
  • 28. *we love recursion in Scala isn't it?
  • 29. OUR SOLUTION Custom fake application Trait configures fake application instance for embedded MongoDB instance. MongoDBSetupconsumes this values. trait FakeApplicationForMongoDB extends MongoDBSetup { this: EmbedMongoDB => lazy val fakeApplicationWithMongo = FakeApplication(additionalConfiguration = Map( MONGODB_PORT -> embedConnectionPort.toString, MONGODB_URL -> embedConnectionURL, MONGODB_DB -> embedDB )) }
  • 30. OUR SOLUTION Typical test suite class class DataDrivenMongoDBTest extends FlatSpec with ShouldMatchers with MustMatchers with EmbedMongoDB with FakeApplicationForMongoDB { ... }
  • 31. OUR SOLUTION Test method which uses mongoDBinstance directly it should "Save and read an Object to/from MongoDB" in { // Given val users = mongoDB("users") // this is from EmbedMongoDB trait // When val user = User(username = username, password = password) users += grater[User].asDBObject(user) // Then users.count should equal (1L) val query = MongoDBObject("username" -> username) users.findOne(query).map(grater[User].asObject(_)) must equal (Some(user)) // Clean-up users.dropCollection() }
  • 32. OUR SOLUTION Test method which uses DAO via fakeApplicationWithMongo it should "Save and read an Object to/from MongoDB which is used in application" in { running(fakeApplicationWithMongo) { // Given val user = User(username = username, password = password) // When UserDao.save(user) // Then UserDao.findAll().find(_ == user) must equal (Some(user)) } }
  • 33. OUR SOLUTION Example of the full test from controller down to model class FullWSTest extends FlatSpec with ShouldMatchers with MustMatchers with EmbedMongo DB with FakeApplicationForMongoDB { val username = "test" val password = "secret" val userJson = """{"id":"%s","firstName":"","lastName":"","age":-1,"gender":-1,"state ":"notFriends","photoUrl":""}""" "Detail method" should "return correct Json for User" in { running(TestServer(3333, fakeApplicationWithMongo)) { val users = mongoDB("users") val user = User(username = username, password = md5(username + password)) users += grater[User].asDBObject(user) val userId = user.id.toString val response = await(WS.url("http://localhost:3333/api/user/" + userId) .withAuth(username, password, AuthScheme.BASIC) .get()) response.status must equal (OK) response.header("Content-Type") must be (Some("application/json; charset=utf-8")) response.body must include (userJson.format(userId)) } }
  • 34. }
  • 35. CUSTOM DSL FOR INTEGRATION TESTING AND SMALL EXTENSIONS TO CASBAH PART THREE WORK IN PROGRESS
  • 36. MORE DATA Creating a simple data is easy, but what about collections... We need easy way to seed them from prepared source and check them afterwards.
  • 37. CUSTOM DSL FOR SEEDING THE DATA Principle Seed the data before test Use them in test ... read, create or modify Check them after test (optional)
  • 38. CUSTOM DSL FOR SEEDING THE DATA Inspiration - , Based on JUnit rules or verbose code NoSQL Unit DBUnit public class WhenANewBookIsCreated { @ClassRule public static ManagedMongoDb managedMongoDb = newManagedMongoDbRule().mongodPath("/ opt/mongo").build(); @Rule public MongoDbRule remoteMongoDbRule = new MongoDbRule(mongoDb().databaseName("test ").build()); @Test @UsingDataSet(locations="initialData.json", loadStrategy=LoadStrategyEnum.CLEAN_INS ERT) @ShouldMatchDataSet(location="expectedData.json") public void book_should_be_inserted_into_repository() { ... } }
  • 39. This is Java. Example is taken from NoSQL Unit documentation.
  • 40. CUSTOM DSL FOR SEEDING THE DATA Goals Pure functional solution Better fit with ScalaTest JUnit independent
  • 41. CUSTOM DSL FOR SEEDING THE DATA Result it should "Load all Objcts from MongoDB" in { mongoDB seed ("users") fromFile ("./database/data/users.json") and seed ("pubs") fromFile ("./database/data/pubs.json") cleanUpAfter { running(fakeApplicationWithMongo) { val users = UserDao.findAll() users.size must equal (10) } } // Probably will be deprecated in next versions mongoDB seed ("users") fromFile ("./database/data/users.json") now() running(fakeApplicationWithMongo) { val users = UserDao.findAll() users.size must equal (10) } mongoDB cleanUp ("users") }
  • 42. CUSTOM DSL FOR SEEDING THE DATA Already implemented Seeding, clean-up and clean-up after for functional and non-funtional usage. JSON fileformat similar to NoSQL Unit - difference, per collection basis.
  • 43. CUSTOM DSL FOR SEEDING THE DATA Still in pipeline Checking against dataset, similar to @ShouldMatchDataSet annotation of NoSQL Unit. JS file format of mongoexport. Our biggest problem here are Dates (proprietary format). JS file format with full JavaScript functionality of mongo command. To be able to run commands like: db.pubs.ensureIndex({loc : "2d"}) NoSQL Unit JSON file format with multiple collections and seeding more collections in once.
  • 44. TOPPING SMALL ADDITIONS TO CASBAH FOR BETTER QUERY SYNTAX We don't like this* ... I cannot read it, can't you? * and when possible we don't write this def findCheckInsBetweenDatesInPub( pubId: String, dateFrom: LocalDateTime, dateTo: LocalDateTime) : List[CheckIn] = { val query = MongoDBObject("pubId" -> new ObjectId(pubId), "created" -> MongoDBObject("$gte" -> dateFrom, "$lt" -> dateTo)) collection.find(query).map(grater[CheckIn].asObject(_)).toList.headOpt ion }
  • 45. TOPPING SMALL ADDITIONS TO CASBAH FOR BETTER QUERY SYNTAX We like pretty code a lot ... like this: Casbah query DSL is our favorite ... even when it is not perfect def findBetweenDatesForPub(pubId: ObjectId, from: DateTime, to: DateTime ) : List[CheckIn] = { find { ("pubId" -> pubId) ++ ("created" $gte from $lt to) } sort { ("created" -> -1) } }.toList.headOption
  • 46. TOPPING SMALL ADDITIONS TO CASBAH FOR BETTER QUERY SYNTAX So we enhanced it: def findBetweenDatesForPub(pubId: ObjectId, from: DateTime, to: DateTime ) : List[CheckIn] = { find { ("pubId" $eq pubId) ++ ("created" $gte from $lt to) } sort { "created" $eq -1 } }.headOption
  • 47. TOPPING SMALL ADDITIONS TO CASBAH FOR BETTER QUERY Pimp my library again and again... // Adds $eq operator instead of -> implicit def queryOperatorAdditions(field: String) = new { protected val _field = field } with EqualsOp trait EqualsOp { protected def _field: String def $eq[T](target: T) = MongoDBObject(_field -> target) } // Adds Scala collection headOption operation to SalatCursor implicit def cursorAdditions[T <: AnyRef](cursor: SalatMongoCursor[T]) = new { protected val _cursor = cursor } with CursorOperations[T] trait CursorOperations[T <: AnyRef] { protected def _cursor: SalatMongoCursor[T] def headOption : Option[T] = if (_cursor.hasNext) Some(_cursor.next()) else None }
  • 48. THANKS FOR YOUR ATTENTION