Features, Specs and Maps
The Map is Not The Territory
I first came across General Semantics in the works of A.E. Van Vogt. His stories from sci-fi's 'golden age' had a common theme about the infinite potential of 'the human nervous system' which was very appealing to a brainy weedy kid. Part of the development of human kind, in these stories, involved a rejection of Aristotelian thinking. This Non-Aristotelian thinking is based upon Korzybski's General Semantics. But wait a minute what has this to do with code and RSpec and Cucumber?
One of General Semantics keys is "the map is not the territory", and that is what this article is all about. Looking at features and specs as maps helps me understand how to use these tools more effectively and also addresses some common frustrations that people new to BDD and these tools experience. But first a little aside into frustration and why its such a good thing.
Frustration is good - read the signs!
Frustration is good! What are you talking about!!
Frustration is your brains way of telling you that something is fundamentally wrong. Your brain is saying STOP! Think Again! So what do we do? ... Well most of the time we ignore our brain, or we blame something/someone, or we 'work our way through it'.
See frustration as a warning light on the dashboard of a car. Don't ignore it or you'll "run out of fuel", "blow up your engine" etc. Frustration is a great early warning system, telling you that you don't really now enough about what you are doing. So stop and use the most formidable thinking machine on the entire planet - your brain!
Features as Maps
If a feature is a map what is the territory? Well I think features are a two way map between territories. These territories are
- The intentions of the application sponsor (the person or persons deciding that the application should be built and what its contents will be)
- The application
The Qualities of Maps
All maps have a scale, which performs two functions
- Show the distance represented by any two points on the map
- Determine the level of detail shown on the map
Features have a large scale, they cover a wide area with little detail. They have to be this way. The first territory they map is a vague amorphous entity which cannot be seen, touched or expressed particularly easily. This is difficult terrain to map so features use (as much as they can) one of our most powerful tools - natural language. The second terrain they map is a small precise highly defined territory. In fact it is so precise that it can be accurately described and even executed using just two characters 0 and 1. Features don't really make much of an attempt to map this terrain. They are more interested in executing (in the computational sense) the terrain. However they can be quite useful as a map of other maps of the application, its UI and source code.
Feature Frustrations
This article was inspired by frustration expressed in a post on the Cukes mailing list. This frustration (IMO) is based on not understanding the scale of features map. Detail is not appropriate in features because detail is not in the territory of the application sponsor. If developers pollute the feature map with their level of detail then the application sponsor can no longer read the map. The map becomes too large and to dense.
Fortunately features have other important functions apart from being a map, so it is reasonable (essential?) to compromise on what they show. But once we understand how detrimental detail is to features then it becomes obvious that they must be supplemented with other tools.
Writing this has made obvious something that I was barely aware of that is that software has to be specced and tested by a suite of tools. An application is too complex a territory to have just one map. Once it becomes obvious that an application cannot be mapped by one map it is a small leap to realise that an application cannot be tested with one test tool, specced with one language. Just as we have to map at different levels we have to execute and test at different levels. I used to be frustrated by having to combine features with specs, and then think about controller specs, helper specs, view specs, user acceptance testing ... Now instead of being frustrated I realise that the need to learn a suite of tools and the necessity of creating a range of maps is just a natural result of the character of the territory I am working in.
Composing Features
Composing Features
Writing good features is an art-form, a very new art-form that people are just beggining to explore. Of course people have been specifying how things should work throughout history, and people have been trying to specify what software should do (with varying degrees of failure!) since software has been written.
You can compare writing features to a new school of art e.g. pontillism. Pontillism built itself on the existing foundations of painting and art - in particular colour theory - and applied these using a new technique to create something a little different. In our new school of features we produce something a little different (a plain text executable) with a new tool (Cucumber) and the application of old and new techniques. To do this well we have to learn what works and what doesn't.
Asking Questions
When we write a feature we need to ask lots of questions. A feature is an exploration of something we want to do. Starting a feature is focused on two things, loosely describing the feature and asking the most important question.
- Why do we want to do this?
The first temptation when writing features is to skip this question! After all we know we need the feature, otherwise we wouldn't be writing it in the first place. And we want to get on with things! What's the point in wasting time on this question?
Well your about to commit a substantial amount of your time writing this feature and a substantial amount of other peoples time in implementing this feature. If it takes you 20 minutes to answer this question properly and you discard one in fifty of your potential features you will still have saved loads of time and effort.
To help you answer this question you can consider the following questions
- Whats the point?
- Can it wait?
- Is there something more important we need to do first?
Writing Scenarios
Once we get to the stage of writing scenarios, we should be fairly confident that we are not going to be wasting our time writing the scenarios. In addition to specifying what should be done, writing scenarios help us to discover things about our feature. As we write our feature we should be open to the following ideas
- We need to do something else first!
- We don't need to do this now!
- This is pointless!
- We don't need this!
Hopefully the point is made now!
Writing Scenarios (the details)
As you write a scenario its a good idea to ask a few more questions.
- What am I assuming?
- Where does this come from?
- Is this a compound statement?
- Do I know what this really means? And even if I do can anyone else?
- Who can do this?
- Who should not be allowed to do this?
- Is this name ambiguous, clumsy, accurate, intuitive?
To write scenarios efficiently we need to develop the skills to ask the write questions at the right time. A warning though - not asking questions, guarantees you will write rubbish, be innefficient, waste other peoples and never develop the skills to write scenarios quickly. Remember this is an art form you have to really work at it to get good.
I'll try below to give some illustrations of applying these questions
Examples (ECommerce Products)
NOTE: Just sketching out things here for the moment
Scenario: A product should
Illustrate composition using VAT Ask the questions
Where does the Supply Price come from? Is it more important to write about this first? Where does the VAT rate come from.
Stop writing this feature and write the feature that sets the VAT rate. As your doing this ask
How many VAT rates? What happens when the VAT rate changes? - to new sales, to old sales How do we change the VAT rate
- write the feature
Feature As a site admin I need to change the VAT rate for all products In order to comply with the national changes to VAT caused by the credit crunch
Do we need to keep the VAT rate with each purchase?
Is the VAT rate
If the supply price comes from
Pluralisations in features
Been a bit of a dummy in this one. Basically each step definition is a regular expression so if we have
When /^I add (\d+) products to the cart$/ do |n|
we can improve this to make allow both
When I add 1 product to the cart
When I add 2 products to the cart
Cucumber Webrat and Debugging Features
Debugging with Cucumber
Simple as putting a debugger statement in any steps file.
Note also that you can run just one feature at a time with cucumber using -l. See cucumber -h
Needed this when dealing with a problem with Restful Authentication forms. What I wanted to do was run the following story
Scenario: Anonymous user can create an account
Given I am on the signup page
When I fill in "Login" with "My product name"
However this kept on failing with
When I fill in "Login" with "My product name" # features/steps//common_webrat.rb:17
Could not find input "Login". (Test::Unit::AssertionFailedError)
Very puzzling as this sort of test works fine with Products. The matcher for this task is
When /^I fill in "(.*)" with "(.*)"$/ do |field, value|
fills_in(field, :with => value)
So I added a debugger and stepped into the code
When /^I fill in "(.*)" with "(.*)"$/ do |field, value|
debugger
fills_in(field, :with => value)
After a bit of traipsing around I found out that webrat uses a library called hpricot to implement most of its functionality, and that it was working fine. However the restful_authentication forms were not so good. Turns out that the labels were not matching the fields in the forms.
Learnt quite alot from this
- More about how webrat works
- How to debug a failing step
Anyhow learnt how to debug a feature