How to write task specifications

Motivation

Recommendations about writing specification are very important because misunderstandings between developers and business owners are very common. The symptoms of that are known:

  • the written code doesn’t meet the specifications because of information lack. In such situation developers implement their own understanding of a task, which doesn’t correspond the intention of the task author. This end up in the unproductive "ping-pong" rounds of rewriting code and adjusting specs. 
  • specs are very general and not too descriptive , so a developer has to ask questions around to clarify the task which leads to very unproductive interactions
  • during the implementation PMs add requirements because of lack of planning at the specification stage which leads to frustration and a lot of code rewrites
  • specs are very cryptic, so only a specialist in a narrow area can understand it. Of course this arises additional questions from devs and QAs, leading to big frustration in their work.

How to solve it

Experience shows that the most productive way of writing specifications is the behaviour driven approach. According to it the specifications are basic descriptions of user’s behaviours (user stories), written from the perspective of a silly user "from the street".

Main idea of such specifications is to find yourself in the user’s role and describe sequence of actions, which lead to the expected behaviour of an application. The approach here is very easy. Let's imagine, we have a mobile app which plays music from cloud services like Google Drive or Dropbox. Our users can enter their login info and then browse stored music files. They create playlists, move files around and of course play songs. But the app lacks download function which could allow to play songs offline when internet connection is unstable or not possible. Let's write some behaviour specifications:

Looking at the working project (Given part)

First we should try to describe the current functionality we want to change:

As a user I log in to my account, go to Google Drive or Dropbox folder and see all my songs there. I can click on any song to start playing it. 

Assuming expected behaviour (Expectations part)

Let's imagine we have a time machine and we can travel to future e.g. one month after. We see how successful our project is thanks the the new offline playback feature. Let's describe it from the prospective of "future me":

I click on a folder and see the "Download" option. When I click on it, files from that folder gets downloaded to my device. I can also save my favourite playlists. In application settings I can select the default download folder as well as the size limit which can be used by the app. When I browse folders, the downloaded ones are marked green. I can also remove downloaded files only from device.  I can play the downloaded files even in the airplane mode. 

I'm happy with the feature if... (Acceptance part)

At this stage we want to make sure that our goal is reached. Let's imagine a grocery list:

If all points are checked, I will be happy with my goal. Let's apply the same principle for the specifications part:

1. App has settings to specify the download folder location and allowed size which application can use for the downloaded content

2. I can download folders and playlists

3. I can recognised downloaded and not downloaded folders/playlists when browsing

4. I can delete downloaded folders/playlists only from device

5. I can play downloaded files in the "offline" mode

This part is practically an answer to the question: "I will be happy when points 1-5 are checked". 

We can describe behaviour driven specs as a list of following rules:

Rule 1: Description of a concrete user behaviour rather than a set of requirements how the system should work

Specifications should not be abstract, especially not defined as a list of rules how the system should work. Behaviour specs aren't "military" orders, recipe steps or requirements which is practically expressed in the language which should not contain phrases like please implement, solve, make, reorganize, improve etc. 

Good specifications should put a user in the center of the attention excluding developer from the task. The reason for it is that the general orders leave a lot of space for different interpretations for both developers and testers who will probably lack the common understanding. On the other hand this requires to think about user's prospective predicting his possible actions or problems. 

Let’s see some examples:

Full text search is not working. This should be fixed!

It’s  too abstract! Where is the full text search and what exactly is broken?

Implement a logic of adding static pages e.g. “About us”

What are static pages? What should be on that page? 

On the page of adding new products the function of picture uploading is not working, it’s needed that this function is working correctly.

Where is this page and what exactly is broken?

Specifications should be concrete, describing clear steps how to reproduce a problem or a new feature. In all cases we define the expected users behaviour, as if the new functionality already existed. 

We can have the following sections in our task definitions:

Current state of the system (given)

Here we describe preparation steps, which should be taken before the bug appears or a new functionality is used.

Example 1

Given

I am on the main page, I enter any text in the search field in footer. I hit the search button. I don’t see the page with the search results.

Example 2

Given

I am a logged in user. I go to the page someurl.com. I click on the button “Upload images” and select 5 files. I see the progress bar and a text field. When I click on “Save button”, nothing happens.

Example 3

Given

I am on the main page. I scroll it to the footer.

Expected state of the system (when-then)

In this section we describe the expected behaviour of the system but from the point of view of a user. This text is very important as both developer and tester will use it to understand if the task is finished or not. We describe here concrete behaviour without abstract requirements, so we continue with the examples above:

Example 1

Given

I am on the main page, I enter any text in the search field in footer. I push the search button. I don’t see the page with the search results.

Expected

I see a page (see the attached html markup file) with products, reviews, photos which contain the text I used in the search field. I see not more than 30 results. I click on the “show more” button and see the next 30 results, I can repeat this as long as all results are visible on the page.

Example 2

Given

I am a logged in user. I go to the page someurl.com. I clock on the button “upload images” and select 5 picture files. I see the progress bar and a text field. When I click on “save” button, nothing happens.

Expected

When I click on the “save” button, then I go on the product page and see all uploaded pictures under the product title. The freshly uploaded pictures are displayed in the list first.

Example 3

Given

I am on the main page. I scroll it to the footer.

Expected

I see in the footer a new link “About us”. When I click on it, then I appear on the page http://someurl.com/about-us. The page design corresponds to the one which is attached in the ticket. When I log in as admin I go to the http://someurl.com/admin page and see “static pages” menu section. When I click there, I see the menu item “about us” which corresponds to the http://someurl.com/about-us page. When I edit the text, it appears on the front page.

Acceptance criteria (the task is solved, when)

This section contains additional formal requirements for the previous text where we described the expected system behaviour. Here we can list the criteria for the task to be accepted. Here we can describe some hints for the tester who should make this decision. Acceptance criteria is a TODO list, where we chan tick the done points and stop working on the task if we reach its bottom.

Example 1

Given

I am on the main page, I enter any text in the search field in footer. I push the search button. I don’t see the page with the search results.

Expected

I see a page (see the attached html markup file) with products, reviews, photos which contain the text I used in the search field. I see not more than 30 results. I click on the “show more” button and see the next 30 results, I can repeat this as long as all results are visible on the page.

Acceptance criteria

  • Search results page corresponds to the attached html file
  • I find all products, reviews, photos with the provided search text
  • I can paginate over the search results

Example 2

Given

I am a logged in user. I go to the page someurl.com. I clock on the button “upload images” and select 5 picture files. I see the progress bar and a text field. When I click on “save” button, nothing happens.

Expected

When I click on the “save” button, then I go on the product page and see all uploaded pictures under the product title. The freshly uploaded pictures are displayed in the list first.

Acceptance criteria

  • Uploading of images results in their visibility on the product page
  • The freshly uploaded images are visible as first in the list of all images

Example 3

Given

I am on the main page. I scroll it to the footer.

Expected

I see in the footer a new link “About us”. When I click on it, then I appear on the page http://someurl.com/about-us. The page design corresponds to the one which is attached in the ticket. When I log in as admin I go to the http://someurl.com/admin page and see “static pages” menu section. When I click there, I see the menu item “about us” which corresponds to the http://someurl.com/about-us page. When I edit the text, it appears on the front page.

Acceptance criteria

  • About-us page corresponds to the attached design
  • I can edit the text the page in the admin part

Rule 2: Required screenshots and page addresses in the specs

We should always specify urls of pages, where we want to implement new behaviour or fix a bug. For each step in users behaviour it’s recommended to specify the url of a corresponding page. Compare:

I go to the page for adding photos

I go the page somepage.com/add/photo for adding photos

Of course the second is more precise and doesn’t allow misinterpretations, imagine that your application has multiple pages for adding photos, where the developer should find the one you meant? Even if there is only one such page, imagine you are a new developer and have no clue what a “page for adding photos” is.

If you want to describe a bug, always make a screenshot! Don’t forget to make a screenshot in the way, that the page url is visible there! Compare 2 specs:

When I click on “Preview”, nothing happens. I expect to see the non editable version of the typed text.

The first question, developer will ask is where to find this block to reproduce the problem. Or maybe he finds another page with this block, where the functionality perfectly works. The correct specification should be like this:

When I click on “Preview”, nothing happens. I expect to see the non editable version of the typed text.

As you see, the page url is visible and doesn’t allow much space for the misinterpretation.

Also very important to use red arrows and texts to show the problem in place, rather than describe it in words. Sometimes one good screenshot may be 100% better than a huge chunk of text.

Rule 3: Describing hidden elements with no distinct address

Sometimes you want to describe behaviour of some dropdown menus or animations, which change their view, position or behaviour after some user interactions and the page doesn’t change its url.

You can describe specifications for such situations as a clear list of steps from the user side which lead the the expected behaviour. Of course screenshots are very important here as well.

For example we want to see the latest notifications in the expandable menu of the user profile. I can describe it very hard:

I see a side menu and scroll page down. In the lower block I see the notifications list for my logged in user. When I open the profile menu, I see the same list of notifications.

Where do I see the side menu? What is the lower block? What are the notifications? What is the profile menu and how to open it?

Let’s make it right:

I go to the main page and log in. On the opened page I can click on the arrow (see screenshot) and expand the right side menu. I scroll page down and see in the “notifications” section the list of the latest notifications.

On the same page I see the profile menu in the right top corner of the page (see screenshot). I click on the link with the user avatar and see the list of notifications.

Notifications are text messages which might be sent by admins for all logged in users.

Rule 4: Behaviours vs technical descriptions

We should never give concrete technical instructions how to implement the task. Professional texts might be cryptic for non-tech specialists, who also work with specifications. Also the developer has no chance to find a proper solution in an analytical way, as the suggested method might be not optimal.

Let's look at some very technical specs:

Add a “is_hidden” flag to the “photos” table to hide them on the main page when activated.

Apply “/[0-9]+/” regex to extract the page id from the link

Use pagination with 20 limit and 10 offset

Integrate the fancy.js library which allows to upload photos to the website.

Let's oppose them to the corresponding behaviours:

... As an admin user I can go to the oursite.com/photos/1 page to edit a photo with id 1. I see there an "is visible" checkbox. When it's on, the corresponding picture is visible on the "oursite.com" main page or not otherwise. 

... I enter the link like "/photos/x333" or "/photos/abc3-45-3", after clicking I see the result 333 or 3453 for corresponding links. I expect that no matter which symbols I enter in the field, I always get the numbers out of it or 0 otherwise. 

... I see the list of products on "/products" page. If we have more than 20 products in the shop, I see only the first 20 ordered by name. I can also see the pagination block where I can navigate over the next 20 products etc.

.. I am an admin and I am on the "/admin/files" page. I can click on the "upload" button and select multiple photos on my local machine. After selecting those files appear in the main list on the page "/files"...

Surely we want sometimes to describe technical details with useful hints, but why not using comments for that case to leave specs as "naive" as possible?

Rule 5: Extensive and precise descriptions of all possible user interactions

Very ofter specs aren't full enough discarding some useful scenarios the user can take. When describing tasks it’s very important to think about all possible ways of interacting with the application rather than describing just one use case.

Lets imagine following specs:

I am a logged in user and go to the page for adding a new article at somesite.com/articles/add. I see a form with a title, date, publication checkbox, text field and save button (see the attached markup). When I click on the save button, I should see the published article on the main page in the news list.

Such text misses following use cases:

  • what if a user didn’t fill in all field values or even none but hits the “save” button?
  • what if a non logged-in user came to this page?
  • what if a user used a too short text (like 1 letter), it cannot be ok right?
  • what if a user didn’t enable the “publication” checkbox, should the article also appear on the main page?
  • what if a user used a wrong date format or a future/past date

The developer with certainly come across such questions, which leads again to misinterpretations and code rewrites. When writing specs, don’t always think about “happy” cases or situations when everything works as expected and user does the exactly things which lead to a positive result.

“Unhappy” cases should be described too, where a user makes something completely wrong or unexpected, e.g. uploads a too large file or forgets to enter some data.

Here are some recipes about making full specs:

  1. If you have a form, think about validation of the entered data. For each field describe the behaviour, when user gives some unexpected data – too large/short text, too big/small file, no value at all, doesn’t select anything in the dropdown etc.
  2. Forms have always some behaviour after pushing the “save” button, don’t forget to mention it: I go to page /saved and see the article
  3. Your user might be logged in or not. A guest user can always go to the hidden page (if he knows the url), that’s why if you have a behaviour which is only available for a logged in user, you should also think about a guest user when trying to do same actions: I’m a logged in user and I am on the page for adding articles /articles/add. If I am not a logged in user and go to this page, I should see the login form. After a successful authorisation, I should be on this page.
  4. Users might have different rights to do some actions. Don't forget to clearly describe the differences between a normal and advanced user behaviours of course if it's important for the corresponding use case.
  5. Any data you see on the page should always come from somewhere. In the most of the cases they are added on an admin page, so when describing a new page think and specify how this content is added. Add specifications for a corresponding admin page. Don’t hesitate to describe admin actions also from the prospective of an admin user.
  6. Admins or even users should be able to update and delete data. Imagine that you expect to see a news list on your website. Describing the news page isn't enough, as news should be added (by users or admins?), but also changed or deleted (admins/moderators/users). In the case with deletion think about possibility to mark something as deleted rather than physically delete it (e.g. accounting details). 
  7. If a user posts some information, ask yourself if you want this data to appear immediately or after moderation from admin. Should admins be notified about the posted data or not?

Rule 6: Don’t “poison” specifications with an unneeded information

The specifications should be concrete and pragmatic. We describe only one feature/bug rather than giving as much “world” context as possible. Let’s have examples of wrong texts:

  • Don’t describe some future intents in the acceptance criteria:

... I see the list of uploaded images. Later this list will be moved to a separate page

  • Don’t repeat requirements of one task inside another one

... I see the list of uploaded images. The images are cropped to the size 300x300 px by a media library (see task A for this)

You can always specify a related task in the comments to the specifications.

  • Don’t mention the features which are not implemented as if they are implemented and not intended to be done in the current task. Simple example:

... I go the product page /product/1 and see the following data of product with id 1: title, image, description, price

Below I see the list of similar products which are recommended to the current one

The last requirement is meant to be as just a static hardcoded information which is intended to be implemented in future as an additional task (as it’s obvious that the programming of a product details page cannot include such complex topic as a recommendations engine, however this is mentioned). Let’s fix this:

I go the product page /product/1 and see the following data of product with id 1: title, image, description, price

Below I see the static list of 5 random products (which will become a list of recommended products in some future iterations).

Rule 7: Think about testability of the requirements

According to this rule, you should write a text not only for a developer but also for a tester. For that we included the “Acceptance criteria block” with a "grocery-like" list. To write this block correctly you should think if expectations are possible to test. Let’s see some examples to clarify problems with the testability of the requirements:

When I clock on the “Save” button, nothing happens (bug is reproducible sometimes, but I am not sure how)

Find a way to reproduce it always otherwise doing such task will be a waste of time.

When Google bot scans product pages, it should not find any missing pages

Such kind of requirement is not testable at all, because tester cannot trigger the Google bot. Even if it would be possible it’s still not clear when it happens and how Google algorithm gets the list of pages which are identified as missing. The correct specification in this case would be:

When I go to /old-product/1 and /old-product/2 (see the full list in the attached file), I should be redirected to /new-product/1 and /new-product/2 with the code 301.

Summary

Writing qualitative specifications is an essential part of a successful IT project. Behaviour driven approach gives a clear understanding of requirements for all project participants – PMs, business owners, testers and developers reducing the time needed for specs clarification and excluding the later code adjustments and QA loops.