Developers: No Other Automated Tests!

« Table of Contents »
Previous Page « No Other Test Cases Are Necessary!

The Behaviour Specification Handbook

Behaviour Specifications

Developers: No Other Automated Tests!

Developers in particular need to understand that they should not write any automated tests other than those that are specified by the Behaviour Specifications. Developers love writing code, and many love writing automated tests (although contrarily, many do not!). Even when the team together has specified all the required behaviours, some developers can still feel as if they should write more automated tests when they are coding.

If this is the case, it is possible that the developers need to better understand the premise and comparative benefits of Behaviour-Driven Development and also the concept of Equivalence Partitioning.

Benefits Of Behaviour-Driven Development

In previous eras of Test-Driven Development, it was common for developers to write many automated tests for each method within each different class or module. Some of the issues with that approach include:

  • A high maintenance cost of automated test assets due to brittle tests that must be refactored when the code is refactored;
  • Communication issues between developers and the rest of the team — some developers can find it difficult to effectively describe the automated tests they are coding on a daily basis. This lack of communication can lead to other team members questioning and arguing the value of such activities.
  • Developers can struggle to estimate when they will finish all of their automated testing — since the answer is “it depends”, depending on the number of classes and methods written.
  • Duplicated testing effort by test analysts — since the automated tests implemented by developers typically are not visible to the non-developers in the team, the testers usually perform many tests that may already be covered by the developer’s automated tests.

In contrast, some of the advantages of the Behaviour-Driven Development approach to implementing tests include:

  • The team agrees, up-front, on the behaviours to be implemented and afterwards there is no room for a debate about the value of any of the tests;
  • The team decides, up-front, which behaviours are implemented by the developers and which behaviours are performed by the testers — more on this later;
  • The team can more accurately provide estimates to management — since the tests are not dependent on the number of classes and methods coded;
  • There typically are fewer tests and they are less brittle. When a refactoring of the implementation code takes place, there are less refactorings of the test code to perform. Even though there are less tests, there still can be similar test coverage — because overall behaviour is being tested — not individual method functionality; and
  • Test analysts (and everyone) have visibility of all the tests of each component and therefore should not unknowingly duplicate testing effort.

Next » Overview Of The Gherkin Language

Effective Behaviour Specification Descriptions

« Table of Contents »
Previous Chapter « General Tips

The Behaviour Specification Handbook

Effective Behaviour Specification Descriptions

This chapter in The Behaviour Specification Handbook provides tips and recommendations on how to write effective Behaviour Specification Definitions for maximum understanding and maintainability.

  1. Start With Should
  2. Indicate Positive or Negative Behaviour
  3. Indicate Primary or Secondary Behaviour
  4. Unique Within Their Feature File
  5. Unique Without Their Feature File
  6. Follow This Template


Next » Start With Should


Next Chapter » Effective Behaviour Specification Steps

Effective Behaviour Specification Steps

« Table of Contents »
Previous Chapter « Effective Behaviour Specification Descriptions

The Behaviour Specification Handbook

Effective Behaviour Specification Steps

This chapter in The Behaviour Specification Handbook provides tips and recommendations on how to write effective Behaviour Specification steps.

  1. Work Backwards: Then-When-Given
  2. Avoid “I”
  3. Terminology Guidelines
  4. Reuse Steps, If Possible
  5. Understand Technical Tool Constraints
  6. Single When
  7. Guidelines For Examples and Data Tables


Next » Work Backwards: Then-When-Given


Next Chapter » The Implementation Process

Feature Files

« Table of Contents »
Previous « Thoughts On Gauge

The Behaviour Specification Handbook

Behaviour Specifications

Feature Files

A Feature file contains the Behaviour Specifications for a logical grouping of related functionality. I recommend having one feature file for each different software component involved in the same logical grouping of functionality.

File-System Folder Structure

I recommend grouping various feature files as appropriate into different file-system folders that follow a logical hierarchy. Each top-level of the hierarchy could be the name of an architectural capability, domain or whatever similar high-level grouping mechanism or category that makes sense.

Sub-folders can be used for other mid-level logical groupings of behaviour. The names of the sub-folders should include a verb, as after all, we are describing categories of behaviours, and behaviours are described with verbs. The sub-folder’s name could describe the set of processes, actions, behaviours and activities that take place, and always should be in business language — not implementation or system-specific language.

The feature files should exist within the lowest-level sub-folders.

Below is an example of the recommended folder structure:

 1Purchasing (top-level folder, also a known business capability)
 2|
 3|---- ProcessingOrders (mid-level sub-folder, a general category of behaviours)
 4        |
 5        |---- Shopping (low-level sub-folder, a general category of behaviours)
 6                |---- ManageShoppingCart.feature
 7                |---- CalculateShippingCosts.feature
 8                |---- ProcessPayments.feature
 9                |---- PlaceOrder.feature
10        |
11        |---- FulfillingOrders (low-level sub-folder, a general category of behaviours)
12                |---- PickOrderItems.feature
13                |---- ShipOrderItems.feature

Source Control Branches

Different software components may live in different code branches or projects within your source control repository. The feature files for a given software component should live in the same code branch as its component. For consistency reasons, it is helpful for the benefit of the entire team to try to keep the same folder structure for feature files across the various software components, where it makes sense.

I also highly recommend not having white-space characters in a folder or feature file name, as this can cause problems depending on the technology platform or development tools you are using.


Next Page » Feature Names

Feature Names

« Table of Contents »
Previous « Feature Files

The Behaviour Specification Handbook

Behaviour Specifications

Feature Names

At the top of a Gherkin feature file is the feature’s name or title. I recommend naming the feature with a concatenation of the full folder hierarchy and feature file name. I also recommend suffixing the feature name with the type of software component (such as User Interface, Service Layer, etcetera) so that feature files for the same related functionality are clearly discernible by the type of software component that implements them.

The template I find most useful for the name of a feature at the top of a feature file is:

1Feature: [Hierarchy-LogicalGrouping]-[FileName]-[ComponentType]

Here is an example feature name, for a User Interface component:

1Feature: Purchasing-ProcessingOrders-Shopping-ManageShoppingCart-UI

And here is the same example feature, this time for the corresponding component in the service layer:

1Feature: Purchasing-ProcessingOrders-Shopping-ManageShoppingCart-ServiceLayer

Different Feature Files, Same Behaviours

It is often the case that some of the exact same behaviour descriptions and Gherkin can be reused in the different feature files of each software component involved in the same logical grouping of functionality. For example, the feature files for both the User Interface and the back-end service layer involved in the same logical grouping of functionality could have the same behaviour descriptions and Gherkin. The back-end service may have additional behaviours for extra business logic that it alone must perform, but as a starting point, the initial set of behaviours could be the same.

As stated earlier, behaviours must always be considered and understood from within the context of and from the perspective of their software component / feature file. Even though the wording of the behaviour may be the same, the actual meaning and implementation will differ, based upon that context. This is why it is beneficial to suffix the feature name with the type of software component, as it is an important contextual differentiator.


Next » What Is A Behaviour Specification Description?

Follow This Template

« Table of Contents »
Previous « Unique Without Their Feature File

The Behaviour Specification Handbook

Effective Behaviour Specification Descriptions

Follow This Template

The complete format for a Behaviour Specification Description that I have found to be most helpful holistically, for the majority of team members is:

1    [Feature-Context]-[TestTypeAcronym]010 - [Primary/Secondary]/[Positive/Negative] - Should [...]

For example:

  • Purchasing-ProcessingOrders-Shopping-ManageShoppingCart-UI-UT010a - Primary/Positive - Should successfully validate [...]
  • Purchasing-ProcessingOrders-Shopping-ManageShoppingCart-UI-UT010b - Primary/Positive - Should provide a notification of a error when an expected error occurs when validating [...]
  • Purchasing-ProcessingOrders-Shopping-ManageShoppingCart-UI-UT010c - Secondary/Negative - Should provide a notification of a general system error when an unexpected error occurs while validating [...]
  • Purchasing-ProcessingOrders-Shopping-ManageShoppingCart-UI-UT020 - Primary/Positive - Should do something else that is not extremely closely related to the 010 behaviours, since this is 020

Different team members, coming from their individual roles and perspectives, can and will debate the value of all of the information that is being included into the Behaviour Specification Descriptions. From some of their differing backgrounds and individual perspectives, they may be correct. However, Behaviour Specifications are about clear communication to all types of team members, not just some roles and individual perspectives. The inclusion of all the above information in each Behaviour Specification Description makes each behaviour more meaningful to a wider range of team members, and makes each Behaviour Specification more self-contained. This makes life easier for all present and unknown future team members — especially when someone needs to reference a specific behaviour outside of the context of the feature file.

This approach provides the benefit of clearer understanding holistically for the entire team, and that has always, in my experience, trumped the small annoyance of the verbosity of the description. Someone invariably will be cursing if the information is not there and they are the poor soul that now has to find a needle in a haystack. For the little amount of discipline required, just do it, or your own slight variation — it will be worthwhile and will save the team from future pain!


Next Chapter » Effective Behaviour Specification Steps

General Tips

« Table of Contents »
Previous Chapter « The Behaviour Specification Writing Process

The Behaviour Specification Handbook

General Tips

This chapter in The Behaviour Specification Handbook provides general tips for writing effective Behaviour Specifications.

  1. The Software Component Context Is King
  2. Avoid Specifying Internal Technical Implementation Details
  3. Specify Relevant Business Capabilities
  4. Specify Component Interaction Behaviours
  5. Write One Specification For One Behaviour
  6. Use Present Tense
  7. Avoid Generic Verbs
  8. Write In Everyday Business Language
  9. SpecFlow/Cucumber Is Only The Name Of A Tool
  10. Have Different Feature Files For Different User Interfaces


Next » Software Component Context Is King


Next Chapter » Effective Behaviour Specification Descriptions

Guidelines For Examples and Data Tables

« Table of Contents »
Previous « Single When

The Behaviour Specification Handbook

Effective Behaviour Specification Steps

Guidelines For Examples and Data Tables

The most important guideline to remember is to ensure that each Behaviour Specification remains readable, easily understood and worded in everyday business language. Just because Gherkin allows for data tables to be specified, it does not mean that they always should be used. A data table after a step, or an “Examples” table at the end of a scenario has the potential to reduce the readability of a behaviour – so beware!

When using a table, ensure that the type of data specified does not jeopardize the single-purpose focus of that Behaviour Specification. For instance, it is unwise to encode multiple business rules into the table, as each business rule, for the sake of clarity, really should be its own, separate Behaviour Specification. Please note the difference between a “business rule” and individual pieces of logic that when combined may be encompassed within and make a single business rule. Tables are most useful in circumstances to provide examples of key data for specifying a single business rule.

Use general good testing practices and common sense when specifying data in a table:

  • Data that is irrelevant to the behaviour should not be specified;
  • The data specified should not be linked magically to a specific test environment, as the test should be executable in any environment. Use dynamic data for Integration Tests;
  • Data should only exist in a table if it is necessary to illustrate or trigger the conditional logic or branch paths of a business rule;
  • Data generally does not need to be repeated in the table – repeated data that never changes indicates that the behaviour is not written as simply and concisely as it could be; and
  • If possible, abstract the data into business language rather than specifying technical details.

Example Table 1

In this example, there is a manufacturing business where orders for products are taken and processed. In this business there is a software component that accepts an order into the system. A single validation-style business rule in that component could be related to ensuring that a mandatory product code has been provided for each order item, and that the product code is “valid”.

Digging deeper into the technical understanding of this business rule, there are two interesting points here:

  • The mandatory product code, in this case, is a string data type, and thus for it to be “provided”, the value must not be null (“not specified”) and it must not be an empty string with a length of zero characters (“blank”).
  • The word “valid” can sometimes be too general and cover multiple conditions depending on the business context, so be careful. In this case however, it simply means that the product code relates to a real product that is listed in the inventory.

We could thus decompose this business rule into three statements:

  • Should error when an order item has a product code that is not specified;
  • Should error when an order item has a product code that is blank; and
  • Should error when an order item has a product code that does not refer to a listed inventory item.

One could create a Behaviour Specification for each of those statements. However, those statements really refer to internal implementation details about the one, single business rule – that the product code must be valid. This is exactly the type of situation where I recommend using a table.

Below is an example Behaviour Specification for this business rule.

 1@UnitTest
 2Scenario: [Purchasing-ProcessingOrders-Ordering-Service]-010 – Primary/Positive – Should error when an order item has an invalid product code
 3
 4Given an order with an order item where the product code is invalid due to it being <An Invalid Product Code Situation>
 5When the order is submitted for processing
 6Then there is a notification that the product code is invalid
 7
 8Examples:
 9| An Invalid Product Code Situation |
10|-----------------------------------|
11| Not specified                     |
12| Blank                             |
13| Not in the inventory              |

This type of Behaviour Specification is reasonably simple for a developer to implement as a Unit Test.

Please note the language used in the Behaviour Specification – it is obvious, self-explanatory and concise. The description tells you, in natural English, that the behaviour is about invalid product codes. Also note that the information in the Examples table also is in natural English and is quick and easy to understand. A table that requires more than a few seconds to interpret or reverse engineer from actual data values back into business language is generally not a desired table!

Example Table 2

Here is another perfectly valid example Behaviour Specification for a service that performs the functionality of the “AND” logical operator of a calculator. This example is more similar to the type of samples generally found by a quick search, and is an interesting contrast to the previous because of its different nature.

 1@UnitTest
 2Scenario: [Calculations-Service]-010 – Primary/Positive – Should correctly calculate the logical AND of two binary numbers
 3
 4Given the first binary number of <Number1>
 5And the second binary number of <Number2>
 6When the logical AND operator is applied to both binary numbers
 7Then the result is <AND Result>
 8
 9Examples:
10| Value1 | Value2 | AND Result |
11|--------|--------|------------|
12| 0      | 0      | 0          |
13| 0      | 1      | 0          |
14| 1      | 0      | 0          |
15| 1      | 1      | 1          |

Again, the language used in the Behaviour Specification is as natural as possible to the business domain.


Next Chapter » The Implementation Process

Have Different Feature Files For Different User Interfaces

« Table of Contents »
Previous « SpecFlow/Cucumber Is Only The Name Of A Tool

The Behaviour Specification Handbook

General Tips

Have Different Feature Files For Different User Interfaces

How does one specify the various User Interface behaviours for keyboard or voice activation, touch-enabled device taps and mouse clicks?

The short answer is: the software component context is king!

Each different interface should be considered another dimensional axis of the same set of behaviours. In this situation, I recommend different feature files for each different type of User Interface. I suggest one feature file for the voice interface behaviours of this component, a different feature file for the touch-enabled interface behaviours, and another for the mouse-based desktop computer interactions, etcetera. Each feature file would have the exact same set of Behaviour Specifications and step wording. The context – which User Interface type the feature file refers to – conveys the understanding of the User Interface implementation mechanism, and how, for example a button’s click action is triggered.

Again, there is no need in the Behaviour Specification to specify implementation details, and if those details are desired, they should be available in the test run output.

If a team would like to document the fact that all these different User Interface interaction mechanisms are available, then fantastic – but that belongs in a User Interface Guide and not as Behaviour Specifications in a feature file!


Next Chapter » Effective Behaviour Specification Descriptions

Identify Which Developers Will Code Each Behaviour

« Table of Contents »
Previous « The Roles Of Developers and Test Analysts

The Behaviour Specification Handbook

The Implementation Process

Identify Which Developers Will Code Each Behaviour

The Behaviour Specifications are complete, and the team is ready to start the actual coding. At this point in the process, it is useful to have the team agree which developers will do the coding of each behaviour.

I generally suggest that each developer should, to begin with, take a software component / feature file each. This of course depends on the number of software components available to be developed, but this approach generally allows each developer to work with less contention.

The team also will need to pay attention to the dependencies of each software component, and try to develop the most critical, common components first.


Next » Identify Who Will Code The Automation Or Manually Perform Each Test