BDD for RIAs with JavaScript
Carlos Ble (www.carlosble.com - @carlosble)
Skills Matter - London - Sept 18, 2013
About me:
● Self-employed● Software developer● Consultant● Trainer● Author● Speaker● Program chair for the ADP conference
@carlosble
1
What problem are you solving?
RIA > operations - collaboration:Spreadsheet, accounting and billing systems, point of sale,
cad/diagramming, chat, games...
Traditional > displaying information:Searching, shopping, publishing, discussing...
@carlosble
3
What do you really need?
RIA(desktop app deployed in the browser)
● UX (user experience)
● Stateful ● Scalability● Real-time ● Off-line● Bandwidth● Access to local hardware
@carlosble
Traditional Web (UI always processed in the server side)
● Stateless● SEO friendly● Synchronization● Learning curve● Security● Compatibility
4
Sometimes it's something in between
Listen to your common sense
When it looks more like RIA:Still take advantage of what
server side offers
When it looks more like traditional:
Use progressive enhacement
@carlosble
No, everything does not look like a nail!
5
RIA: taking advantage of the traditional way
When it comes to GUI and appearance, you might go “traditional” first: - Technical debt on purpose, saves time (well thought out!). - Changing/Improving that later is not a big deal.
Examples:● Server renders js files, js objects, json,... on page load, apart from HTML and CSS.● Page reloads as view changes.● Page reloads to get an updated list of items when one of them is changed.
@carlosble
6
Behavior-driven RIAThe business DSL in the step definitions lives in the browser:
[Binding]public class UpdateHealthRecords_Steps : RpsEnd2End{ [Given(@"Bob said his last glucose value was (.*)")] public void lastGlucoseValueWas(int lastValue) { scenarioFixture.lastGlucoseValue = lastValue; var jsdate = "new Date(2013, 1, 2)"; ExecuteJavaScript( string.Format( "rps.Business.addNewGlucoseWith( {{ value: {0}, date: {1} }})", lastValue, jsdate)); }}
@carlosble
Note: Rps is the name of the sample project7
Outside-in TDD starts in the browser
- Domain objects emerge as we test-drive the code.
- The server side becomes just an adapter*, a hub. In fact, the server side would not be useful at all without the JavaScript app.
- Risk: duplicated logic in the browser and the hub. Possible solution: Use Node.js in the hub.
* see hexagonal architecture
@carlosble
8
Hub's features will emerge- Don't start off test-driving it: YAGNI.
- Business rules concerningsecurity/data-consistency, are added progressively.
@carlosble
- If you need a RESTful web API, that might be a separate application.
- Some data must bechanged by the hub exclusively. Perhapsinvisible to the app.
9
Test-driving a JavaScript application
● Absolutely everything is testable. Even test-driving most of it, everytime I feel like testing the app manually, I can add a test for it (integration tests typically).
● Event Oriented Programming & Passive view. Because low levels of abstraction should not know about higher levels.
● Frameworks? you need widgets. What do you need an IoC container for?
● Don't mock what you don't own. Use wrappers instead.
● AOP can be implemented with CSS ;-) Logic should not care about a “modal” window.
@carlosble
10
Events: DOM level 0 – Traditional model(one2one: simplicity – ideal for low level events)
@carlosble
12
Passive view: Widgets are objects
Koan: what is wrong if we want this test to be unit?
@carlosble
15
Some references
● Test-Driven JavaScript Development (book) – Christian Johansen● The Cucumber book (book) – Matt Wynne & Aslak Hellesoy● JavaScript the good parts (book) – Douglas Crockford● JavaScript Allongé (book) – Reginal Braithwaite ● Enough with the JavaScript already(talk) – Nicholas Zakas: - Hanselminutes interview. - Talk.● Test-driving events and promises (blog posts) – Carlos Ble - Promises - Events
@carlosble