Feature Organization
Adopting a Modular Approach
Many common computer interactions are reused when performing tasks even across functional areas. If an interaction is reused more than once, it should be modularized. This modularization relies on importing Scenarios and reusing Scenarios. There are a number of reasons to implement a modular approach to Feature development with Cycle:
- Reusability: Breaking functions up into their own Scenarios means that a given Scenario can be imported and reused across Features. This removes the need to rewrite the same Scenario over and over.
- Customizability: Customizing an environment for a given set of tests, for example, becomes more efficient when it can be configured in one Scenario instead of across multiple Features.
- Maintainability: When software changes, our tests need to change. It is much quicker to update one Scenario that is shared across Features than to update each individual Feature.
- “Debugability”: When Feature execution does not produce the desired results, it is easier to drill down into a specific Scenario and identify the subset of Step(s) to debug, instead of wading through longer lists of Steps under the main Feature.
- Readability: By reusing Scenarios, top-level Features can be shorter, and more focused on highlighting the business process as opposed to the detailed Steps to execute that business process.
It is therefore recommended that different functions be written into discrete Scenarios. Like Scenarios can then be grouped into the same Feature, for efficient importing and reuse by other functional Features.
One example of a useful way to implement modularization is to create a Feature File, named “Environment.feature”, containing Scenarios to configure the environment(s) for a given set of tests. This Feature can then imported into main Feature Files via the Background of Feature Files, or directly into functional Scenarios when it makes sense. Environment.feature could contain Scenarios that configure setup data like connection Information (connection strings, user, password), device codes, or any other data that might be specific to a PC or user.
Feature structure
A Feature File is made up of the following sections, in the following order:
1. Feature Header (optional, but recommended) - Using Feature Header, a Feature Header section should be added to the beginning of all Feature Files to specify the Cycle version and the application version being tested, assumptions, and usage instructions.
2. Background (optional, one per Feature) - The Background (one per Feature) is a specific type of Scenario that runs prior to every non-@wip Scenario in a Feature File. In many cases, it is useful to import Environment.feature via the Background. As described above, Environment.feature would contain Scenarios to set up the test environment for the Scenarios.
3. After Scenario (optional, one per Feature) - The After Scenario, which runs after each non-@wip Scenario in a Feature, can be used for cleaning and purging data used in Scenarios.
4. Functional Scenarios - Functional Scenarios are the main, function-specific execution Scenarios and @wip Scenarios included in the Feature File.
Recommendations for Scenarios
- A Scenario should contain a single complete and independent test.
- A Scenario should not be dependent on a specific Feature or Scenario running first to setup the data or the application.
- Exception: It is acceptable to build Scenarios that expect a common state (for example: the terminal or GUI application to be logged in and at the main menu). These Scenarios should always start by testing to confirm the appropriate starting condition.
- A Scenario should only be dependent on other Scenarios that get called/run from the Scenario.
- Note: While developing a long Scenario it is common to create a Feature containing a series of small Scenarios that run in sequence. However, the final version should be reconfigured to comply with the preceding rules.
- Try to split things up into Scenarios as much as possible.