It is not uncommon to wonder about how to create data for cukes…
- Keep it high level?
Given I have 4 products
- Or explicitly define data; e.g., using a table
As a broad answer to this question, it all depends on what behavior you are specifying. There is no single, right way.
My usual rule of thumb is to limit the setup to just those parts of the problem domain “object graph” that you care to test in the current scenario. That helps draw attention to the most “narrow” bits of the system that are under test. Otherwise, if you continue to build everything from scratch for all scenarios, it is sometimes hard to see the purpose of the test because it is lost in all of the setup code. Sometimes you care about the details in the parent object, sometimes you want to test the sum of the parts, and other times you are focused only on a small aspect of the object model.
Suppose we are making bread, and we have a set of recipes. Each recipe has a set of ingredients. When we go to make 5 loaves of bread, the list of ingredients are properly re-sized and displayed so we can mix the dough and make a new batch of bread.
My first scenario might be detailed around setting up the core recipe/ingredient relationship:
Scenario: View a recipe Given I have the following recipe: |Name | Artisan Bread | |Yield| 2 1-lb oblong loaves| |Prep | 30 min | |Proof| 3 hours | |Baking| 35 min. at 450 deg F| With the following ingredients: |Ingredient |Quantity| |White Bread Flour|6 cups | |Whole Wheat Flour|0.5 cups| |Granulated Yeast |1.5 Tbsp| |Coarse (sea) salt|1.5 Tbsp| |Water, 100 deg |3 cups | When I view the recipe Then I should see the recipe
So the above scenario gets us focused on the basic bits of the
Recipe ----*-> Ingredients part of the model, and the desired behavior of what a recipe display looks like. Note: on the “Then” I chose not to focus on how it is displayed. I could have said something like “…with the recipe info at the top, followed by a list of ingredients.”
Now suppose the next scenario we tackled was the ability to “resize” the recipe to make some multiple of the base quantity? Do we need to repeat the same sort of setup as we did above? Or can we get away with defining less information? That is, using something like FactoryGirl, we could predefine some basic recipe data, if nothing specific is needed.
Scenario: Resize the batch to triple the yield Given I have a "Hard Tack" recipe that yields "25 cakes" With the following ingredients: |Ingredient | Quantity | |Flour | 4 cups | |Water | 2 cups | |Salt | 4 tsp | When I resize the recipe to 3 times the size Then I should see the following ingredients |Ingredient | Quantity | |Flour | 12 cups | |Water | 6 cups | |Salt | 12 tsp | And a yield of "75 cakes"
While the difference is subtle, the point to the above scenario is to not clutter it with the core recipe elements as were visible in the first scenario.
For a more extreme example of “narrowing” the focus, lets look at another scenario. This time, the business tells us they want users to be able to rate the recipes.
Scenario: Users can 'Like' a recipe Given I have a "Swedish Hard Tack" recipe When I Like the recipe Then I should see the Like Count increment by one And I should not be able to Like the recipe a second time
So here you can see there is no reason whatsoever to care about the details of the recipe. In fact, I could have left off the recipe name, but sometimes I like to keep some sense of the domain visible. Had I written the Given to show all of the detailed data, it would have obscured the meaning of the scenario, as this scenario would then look like the other scenarios.
Scenario: (BULKY VERSION!) Users can 'Like' a recipe Given I have the following recipe: |Name | Artisan Bread | |Yield| 2 1-lb oblong loaves| |Prep | 30 min | |Proof| 3 hours | |Baking| 35 min. at 450 deg F| With the following ingredients: |Ingredient |Quantity| |White Bread Flour|6 cups | |Whole Wheat Flour|0.5 cups| |Granulated Yeast |1.5 Tbsp| |Coarse (sea) salt|1.5 Tbsp| |Water, 100 deg |3 cups | When I Like the recipe Then I should see the Like Count increment by one And I should not be able to Like the recipe a second time
Again, this is a subtle point. But making it easier for readers of the feature file to see differences without having to “strain” can improve understanding and reduce potential for errors.