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.
September 2, 2009
HOWTO: Rock at CSS and keep your sanity
I happen to be good at writing robust CSS. Years of exposure to a world of broken browsers made me develop a couple of practices that make my styles break less. All these practices share a common theme: Make it easy for the browser to understand you. If you express your styles clearly, any browser will be happy to render your pages as intended.
I will dispense this advice now.
Tag anorexia is a false idol
I often see people striving for layouts using as few div
and span tags as possible. Get over it. Minimalistic tag usage is a false idol
with zero ROI and requires unmaintainable style acrobatics to make it work.
Be generous with divs and spans and your styles will be much
cleaner and easier to reuse.
Don't accept stacking margins
It is not acceptable when the margins and paddings of adjacent elements randomly stack or merge with each other, scattering gaps small and large all over your page. It shows that you have trouble making styles work together, which is more important for the overall impression of your page than the look of individual elements.
As a general rule, the paddings of adjacent elements never merge with each other. Adjacent elements try to merge their margins but it doesn't work reliably in all situations and browsers. Especially the merging of margins at the top or bottom of containers, and across different depths of the element tree is hard to manage consistently.
Strongly consider applying margins and paddings only to the right and bottom edge of elements, while resetting margin and padding at the top and left to zero. This prevents the stacking of margins in most situations and puts you back in control.
Sense ambiguities and avoid them
Develop an eye for possible ambiguities in your styles. Take this example:
<p>A paragraph</p> <strong>Some inline text</strong>
Which block element interacts with the boundary of that <p>? An imaginary <div> wrapped around
that <strong>? It would be clearer to not mix block elements and inline elements within the same parent element.
Cultivate a sense for such vagueness and avoid it.
Even if you often get away with unclear instructions it's not worth the world of pain when the next browser update starts to guess wrong.
Prevent float trouble early
Always clear your floats or your layout will break as real user content replaces your conveniently
sized lorem ipsums in production. Whenever you float something, your next concern should be clearing the float
further down. Use a zero-height <div class="clear"> if there is no other element to
do the job.
Also don't build pages where everything floats, even if those floats get cleared eventually. It's bad karma.
Default browser styles can be anything
Understand that whenever a given style isn't defined in your stylesheet, the browser can default to any value at all. Some people use reset stylesheets to regain control. At the very least you should be worried about margins and line heights whenever you use a block element.
If your site isn't a near-pixel perfect carbon copy in Firefox and IE you should be worried because it means you're relying on a default style without knowing it. Do demand control over your layout. Don't just blame IE.
Semantic markup is overrated
The selection of "semantic" tags available in HTML is so small and unexpressive it's laughable
how much bandwidth was wasted arguing over their proper usage.
Stop caring if a given element should be a <p> or a <div> or an <address>.
Do use proper headings, but other than that just use whatever is the easiest to style.
If your site looks usable when you turn off styles, you're semantic enough.
Some people will argue that semantic markup equals accessibility, which is wrong. Screen readers are better at handling tag soup than you think. They get a bad rap from people who are clueless or want to sell accessibility makeovers. Instead of guessing what a screen reader can or cannot handle, try it out yourself. Also remember that there is more to accessibility than proper markup and styles.
Fake the designer
Most of us don't have a proper design education. I know I don't. You can still produce decent results if you follow two simple rules and leave the fancy stuff to the pros:
-
Whitespace is important. Don't have different margins and paddings everywhere. Pick a standard margin that separates block elements on your page and stick with it. 15 pixels often work for me.
-
Colors are important. Never use pure colors like
#00f. Tint your colors like#12eand they will look much nicer. Also pick a color palette and stick with it. Creating a good palette is hard, but there are tools to help and sites with great premades.
Don't demand the impossible from your browser
There are times when the browser would have to read your mind in order to render your styles as intended. For instance, you have a container element with some children nested inside. The width of the container is dependent on the width of its children (it floats), but the width of a child is dependent on the width of the container (their width is defined in percent). How should a browser make sense of this undecidable mess?
Try to be as clear as possible when describing your layout. Don't make everything dependent on everything. Always root dependent styles in definite expressions such as "this column is 300 pixels wide" or "this box grabs all available space" and any browser will gladly follow your instructions.