Day 3 of RailsConf Europe
Functional Testing – Lessons Learned
presented by Jay Fields
“Testing is hard” (so true …). Jay states that you can’t learn TDD by just reading a book.
Jay thinks that test code is just as important as application code. If your application is never going to change and only you yourself are working on it – well, don’t have tests. But Jay stresses that this is usually not the case and tests help keeping the application working and also to document what the application does to other (new) developers. No automated test suite can, of course, replace exploratory testing – you still need your QA team.
Jay suggests creating tests that test important things – 100% coverage isn’t necessarily always the right goal. You should test the features that make it a great application. Finally, tests are needed to prove that the system works as expected.
The problems with functional tests, according to Jay, are that they don’t verify corner cases and also that they tend to run pretty long which is why he suggests to not have too many functional tests. Instead, he suggests to use unit tests to test functionality in isolation and run these unit tests constantly. In addition, you also have a couple functional tests that integrates databases and/or APIs and you can run these functional tests separately from unit tests every now and then (e.g. before pushing changes to your source code repository).
test/unit, for Jay, is bad because it’s QA-unfriendly due to its ugly syntax. Also, tests are procedural rather than really object-oriented (the test suite is but a test itself isn’t). The good things are that it is easily understandable and that it provides good help to trace your errors (e.g. stack trace). All in all, Jay considers test/unit to be a decent choice.
Regarding Selenium, Jay thinks it’s awfully slow and he hates that browser bugs can cause failures. It’s also hard to find the defect location and you have to track bugs down yourself. The good thing is that it runs the full application – they actually ensure that users get what they expect. It’s also easy for developers and tests to use. Summarizing, Jay’s opinion is that it’s too brittle and slow to be used on a regular basis.
Bad things about RSpec: It’s got a pretty steep learning curve (coming from test/unit) and Jay says that even he needs to look up some details every now and again. Moreover, RSpec is pretty hard to extend – Jay considers custom matchers are a way out but it’s still not a good code base. On the other hand, Jay loves that it encourages behavioral testing and, therefore, helps you writing better tests in general. Developers and testers can use and even understand tests – it allows you to sit down with QA and even business people and they are likely to understand the test code. No surprise: RSpec is Jay’s preferred solution for tests.
Jay suggests writing smoke tests to ensure that the most important parts and paths of your app work – he calls them smoke tests.
Subsystems can be a pain in the … (well, you know). Jay stresses that you really should test subsystems you own (like databases) but not subsystems you don’t own (like Twitter, your credit card provider, etc.). Instead, stub 3rd party sub systems and create an external test suite – maybe even a semi-automatic one – that you run against the real 3rd party API. Jay showed a simple example for stubbing where he had a FeedBurnerGateway and stubbed out its methods for the test.
Jay suggests that unit tests and functional tests should be top priority when bugs occur. Of course, you also have to work on failing smoke tests and external tests – but they shouldn’t be your to priority.
Regarding data, Jay stresses that you should not re-import reference data (e.g. the states of the US) for every single tests but you definitely need to have fresh state data (e.g. a shopping carts) for every test. For state data, Jay suggests using a factory such as Dan Manges’ factory and the tests should create the state data they need by themselves. Jay also states that he really doesn’t like fixtures because they’re slow and unmaintainable, and in his opinion moving away from fixtures has always paid off.
- Move corner cases from unit tests.
- Remove painful tests that provide little value (writing them is easy, deleting them is hard).
- As tests break, migrate them to better written RSpec tests.
- Create stubs for sub systems that you don’t own.
- Break data into reference data and state data and refactor tests so they share reference data but create their own state data.
Jay’s talk was the most valuable session for me so far and I’ve really taken away a lot from it. He gave a really well-rounded presentation (actually, I think he was the first speaker to provide a real summary at the end) that was full of useful content. If you’re not subscribed yet, definitely check out his blog.
I wrote about the great food yesterday. I took a picture with my iPhone today so you can check it out yourself at Flickr
The Future of I18n/L10n in Ruby on Rails
presented by Sven Fuchs
Disclaimer: I’m kinda partial to Sven’s work so please forgive me if it turns out that I’m not entirely objective on his talk.
Sven started his talk with the “official Rails i18n hymn” – Judas Priest’s Painkiller and a short introduction about himself.
After that, he gave a brief overview about the past regarding i18n in Rails: Of course, there were Ruby Gettext, GLoc, Globalize, etc. But the problem about these was that they often were isolated, incompatible solutions with bad support and lots of monkey patching that tended to break with every new Rails release. The wheel was constantly re-implemented.
Sven proceeded to explain how the Rails i18n project was born: Pretty much everyone that has contributed in one way or another in i18n stuff was invited to join in the effort to finally create a working, unified i18n solution for Rails. After lots of discussion about implementation details, the team came up with a draft of what Rails i18n should be able to do. Here are the key dcisions:
- 100% swappable translation logic
- Always do the simplest thing that could ever work.
- Rails i18n doesn’t want to be a full-blown i18n/l10n solution.
Instead, Rails i18n aims to provide a powerful i18n API – it’s only a blueprint of what the real translation implementations should do. Additionally, Rails ships with the Simple backend to support Rails’ standard en-US localization.
Translations are stored in YAML files by default – optionally, you can also use Ruby files if you need more complex translations using lambdas and other complex Ruby logic.
Sven then showed the basic API of the i18n plugin: The methods translate and localize. He also explained how lookups work and how you structure your locales using scopes, interpolation of translations and pluralization rules. He also demonstrated how you can swap the Simple backend with your own customized backend.
After that, Sven did a short live coding session where he showed how you can easily provide simple translation for static texts and load and set locales on the fly.
In Sven’s opinion, by using the Rails i18n API, we do win a lot because
- we need less monkey patching,
- we have one common API for all plugins
- we can share locale data
- and we’ll finally get better plugins.
Sven proposes to continue work on Rails i18n by implementing features, collecting and reviewing them and afterwards aim for another big Rails core patch when the time is right.
After that, Sven showed a video interview with Joshua Harvey, the original author of Globalize and also mentioned some details about the upcoming Globalize 2.
He closed his talk by explaining how everybody can take part and contribute to the ongoing efforts in making i18n/l10n in Rails work even better than they already do.
I think, Sven managed to give people a good overview of what i18n can do for you right now and about its plans for the near future. I guess everything will become pretty great as soon as the plugin landscape becomes more diverse, especially with the advent of Globalize 2. Thumbs up, buddy!
- Presentation in multiple formats
- Sven Fuchs’ blog
- Rails i18n project
- Technical overview of the Rails i18n API
Treading the Rails with Ruby Shoes
presented by Eleanor McHugh and Romek Szczesniak
I’ve spent some time letting Eleanor’s and Romek’s talk sink because it was kinda weird. The title suggested that it was about using why’s Shoes framework together with Ruby on Rails but that made only for about 5 minutes of the talk. The rest was about, well, everything and nothing at the same time. Eleanor and Romek had a lively and funny dialogue going on between them, talking about the history of the Internet, cryptography, sockets, etc. without a really clear direction – at least it wasn’t clear to me. It seems they held a similar talk at last year’s conference so maybe this was a kind of prerequisite for really getting them.
All in all, it was – as I said – a really weird discussion. It wasn’t bad but I didn’t really take away something from it. Eleanor and Romek went over lots of different topics but never really sticked with one topic long enough so people could actually understand where they were coming from. Plus, they showed slides with huge amounts of code that was barely legible from the third row where I was sitting – let alone in the back of the room – not good. In short: It was amusing but not really valuable.
I Heart Complexity
presented by Adam Keys
Adam started his presentation talking about domain modeling: Customers talk about accounts, credits, etc. and developers talk about users, addition, subtraction, etc. The goal of domain modeling is that you break it down to one common language or jargon that both, business people and developers speak – also called an ubiquitous language. Adam says that this results in less documentation needed because it avoids misunderstanding between the business and development team – business people should actually be able to read code (similar to what Jay Fields talked about earlier). If you put the domain together with the intent of the application, you get the essence of the application – after this, we can focus on more complex (and more interesting) challenges. Adam then made his point showing how he refactored a bad, anemic domain to a richer, strong domain.
State, according to Adam, is the most important part of our application because it displays the life cycle of our actual objects. This is why you should spend a good amount of time thinking about your application’s stateful logic. Again, he made his point by refactoring an app by using a state machine to define state transition rules – according to Adam, this makes it easier to understand and easier to see what’s important.
Another challenge is handling money: Language designers are way too cool to package money classes with their standard libraries. Adam discourages the use of floats because they are imprecise. Instead, he suggests extracting money into its own class and storing the value in cents plus its respective currency.
Adam then proceeded to talk about time travel: It turns out a lot of people need to travel back and forth in time. This basically refers to versioning your domain objects (e.g. using Rick Olson’s acts_as_versioned) as to allow to viewing given objects and their changes over time.
His final topic, asynchronous processing, was basically about queuing (because you really shouldn’t rely on multithreading in Rails just yet ;-)). Adam used a moderation queue as an example where all product changes in an application should go through a moderation process before being published to the live site. For large queues, Adam suggests using tools like Beanstalk or Starling – for smaller scale projects, putting them directly in your domain model may just be the right choice.
In my opinion, Adam gave a great overview of methods to reduce complexity and also made a point of showing that there are also plenty of options out there that are ready to be used in your everyday Rails application. I kinda expected him to be a little funnier – but probably this is because so far I’ve only seen him in the MVC videos with RailsEnvy that are, after all, just hilarious. A well-rounded talk and all in all a really worthy end of the official RailsConf Europe 2008 presentation.
Day 3 resumé
I started day 3 a little later (even geeks need sleep every now and again) so I missed the symposium about different Ruby implementations – I heard it was quite interesting. Regarding quality, day 3’s sessions were en par with day 2’s – at least the sessions I’ve been to. I heard that some of the other sessions weren’t quite that good – but then again, I guess you can’t really equally satisfy 700 people.
I especially enjoyed Jay Fields’ talk about his experiences with functional testing. Among other things, he was one of the very few speakers that ended their talk with a summary of what they’d discussed during their session. Sven Fuchs’ introduction to the Rails i18n plugin was also very interesting. I also really loved that David, Koz and Jeremy sat through Sven’s talk as well which, in my opinion, showed that they really do care about Rails’ latest internationalization efforts.
Something I definitely missed on the last conference day was a real closing event like a final keynote speech or at least some kind of official fare-well drink. Other than that it made a good last day for a really great conference.