September 4, 2009
Should I test for translated strings?
Last night I visited the Ruby User Group Berlin where Clemens Kofler and Sven Fuchs were talking about the future of the Rails I18n API. Many friendly and smart people made for a wonderful evening.
After the talk I brought up the question whether tests should call the translation API when checking for the presence of a string.
Take this simple Cucumber story:
When I go to my bookings page And I press "Delete booking" Then I should see "Booking deleted"
This story will fail when the locale comes back from an external translator who deemed "Remove" a friendlier label for that button. We discussed some ideas how to make our stories less brittle in the face of translation changes.
One idea was to have the tests look up keys in the translation store:
When I go to my bookings page And I press the translation of "bookings.index.delete" Then I should see the translation of "bookings.index.deleted"
This story would survive translation changes, but pollutes your pretty Cucumber stories with implementation details. You also need to extend existing step definitions to look up translation keys.
Nico Hagenburger came up with the idea of using a translation store that just returns the translation key as its translation, so you could just use existing step definitions:
When I go to my bookings page And I press "bookings.index.delete" Then I should see "bookings.index.deleted"
Clemens' advice was to ninja around naming actual strings by checking the DOM tree for the presence or absence of elements:
When I go to my bookings page And I press the delete button Then I should see a confirmation flash
I like how this tests for the confirmation message. This probably won't work as well for following links and pressing buttons, where you need to distinguish that one link from the 50 other links. Already the step "When I press the delete button" from our example above is tricky to implement well.
A workable compromise might be to only check for text fragments:
When I go to my bookings page And I press "Delete" Then I should see "deleted"
While this might break after a translation change, you're cool as long as the new translation contains the word "deleted".
Another interesting idea is to keep around a development locale which never gets shipped to the translator. The development locale would retain all the labels, messages and terminology used during initial development of the application. The translator creates an English locale based on it but never changes the development locale. Your tests would never break from translation changes, at the expense of maintaining one additional locale.
Comments
I like Nico’s idea the best, by a wide margin. It’s effectively identical with the “development locale” suggestion, but with the added benefit that the labels are really really unambiguous and reliable. And unlike asking for “the translation of”, these suggestions do not involve leaking containable complexities (such as i18n) from the callee into the caller. The result may not attain an Uncanny Valley level of natural English resemblance – but a foolish consistency is the hobgoblin of little minds anyway, so…
Posted by Aristotle Pagaltzis (#)
Post a comment
Your comment will be published as soon as I approve it, usually within 24 hours.