diff --git a/knpu/bdd-features.md b/knpu/bdd-features.md index c87cb81..ee702fd 100644 --- a/knpu/bdd-features.md +++ b/knpu/bdd-features.md @@ -25,14 +25,16 @@ With BDD we break down our development process into four steps: 3. Take one feature and break it down into all of the different user stories or scenarios. 4. Write the code for the feature, since you now know how you want it to behave. -To do all this planning, Behat uses a language called Gherkin. This isn't special to Behat or PHP, +To do all this planning, Behat uses a language called **Gherkin**. This isn't special to Behat or PHP, it also exists in Ruby, Java and every other programming world out there which is a good thing. ## Writing Features Our application is already partially built, but let's pretend that it isn't and we're just in the planning stages. First we know we'll need an authentication feature. So let's go into the `features` -directory and create a new `authentication.feature` file. Each feature will have it's own file in here. +directory and create a new `authentication.feature` file. Each feature will have it's own file in here: + +[[[ code('f21554628c') ]]] We always start with the same header `Feature` and a short description of it. Here we'll just say "Authentication". The next three lines are very important. Our next line is always "In order to" @@ -45,7 +47,7 @@ what the user would actually be able to do with this feature. In our store that The most important parts are the first two lines, the business value and the user - or role - that's going to benefit from this value. If either of these are difficult to define then maybe your feature -isn't actually valuable. Or maybe noone is benefiting from it. Perhaps move onto a different task. +isn't actually valuable. Or maybe none is benefiting from it. Perhaps move onto a different task. ## Writing Good Business Values @@ -53,35 +55,31 @@ Back in the Raptor store, login with admin/admin and check out the product admin that! Back into the `features` directory and create a new `product_admin.feature` file. And we'll start the same as we always do: - Feature: Product Admin Area - In order to +[[[ code('d777b47ac7') ]]] So why do we care about having a product admin area? It's not just so we can click links and fill out boxes. Nobody cares about that. The true reason to go in there is to control the products on the frontend. So let's say just that: - In order to maintain the products shown on the site - As an admin user - I need to be able to add/edit/delete products +[[[ code('b35e47ba49') ]]] That looks good. What else do we have? Check out the "Fence Security Activated" message on the site. Let's imagine we need to create an API where someone can make an API request to turn the fence security on or off from anywhere. For example, if you're running from dinosaurs somewhere, you might want to pull out your iphone and turn the fences back on. -We'll need another feature file called `fence_api.feature`. Start with +We'll need another feature file called `fence_api.feature`. Start with: - Feature: Remote Control Fence API +[[[ code('26de64fdbc') ]]] The business value is pretty clear: - In order to control fence security from anywhere +[[[ code('acb710a390') ]]] The user that benefits from this isn't some browser-using admin user: it's a -more-advanced API user. +more-advanced API user: - As an API user - I need to be able to POST JSON instructions to turn the fence on/off +[[[ code('b642a1bae2') ]]] I feel safer already. @@ -89,9 +87,7 @@ I feel safer already. There's a common pitfall, and it looks like this: - In order to add/edit/delete products - As an admin user - I need to be able to add/edit/delete products +[[[ code('e68cbc8e28') ]]] Notice the 'In order to' and the 'I need to be able to' lines are basically the same. This is a sign of a bad business value. Being able to add/edit/delete products is not a business diff --git a/knpu/scenarios.md b/knpu/scenarios.md index 3c779d1..8a5a1ec 100644 --- a/knpu/scenarios.md +++ b/knpu/scenarios.md @@ -11,7 +11,7 @@ the admin area and click on products, I see the products listed." So let's start with: - Scenario: List available products +[[[ code('725c8fa9a6') ]]] Do keep in mind that this line doesn't matter too much, no need to be Shakespeare. For these scenarios I need you to think as if you *are* the admin user. We'll talk in @@ -23,30 +23,30 @@ see. Put yourself in their shoes. Scenarios always have three parts, the first is `Given` where you can create any type of setup before the user story starts. So in our case, if we want to list products, we need -to make there are some in the database to see. +to make there are some in the database to see: - Given there are 5 products +[[[ code('5ea4ea3ae0') ]]] Why am I saying exactly "there are 5 products"? Great question, the exact phrasing here doesn't matter at all. I'm just using whatever language sounds most clear to me. -Move on down to the next line. +Move on down to the next line: - And I am on "/admin" +[[[ code('b8454dd380') ]]] Using the word `And` here extends the `Given` line to include more setup details. With these two lines, we'll have 5 products in the database and start the test on the `/admin` page. The second part of every scenario is `When` which is the user action. Here, I the admin user -actually take action. In our case, the only action is clicking products. +actually take action. In our case, the only action is clicking products: - When I click "Products" +[[[ code('af0e00b21f') ]]] This is good because that's the name of the link and it reads very clearly. Finally, the last part of every scenario is `Then`, this is where we witness things -as the user. In our scenario, we should see the 5 products that we set up in our `Given`. +as the user. In our scenario, we should see the 5 products that we set up in our `Given`: - Then I should see 5 products +[[[ code('5c8e68652a') ]]] Always use language that is clear to you after your `Given`, `When`, `Then` or `And` in your scenarios. @@ -60,35 +60,33 @@ However, the user could see a helpful message, like "Celebrate, your product was Let's create a new scenario for functionality that doesn't actually exist yet: adding a new product. Time to plan out this scenario! - Scenario: Add a new product +[[[ code('5540e64103') ]]] -We don't need to add any products in the database before hand so we just start with +We don't need to add any products in the database before hand so we just start with: - Given I am on "/admin/products" +[[[ code('79397aa8b5') ]]] We're going to want a button on this page that says "New Product". So let's add clicking that -to the process of creating a new product. +to the process of creating a new product: - When I click "Products" +[[[ code('81308ed6d5') ]]] Clicking this will take us to another page with a form containing fields for name, price -and description. To keep our `When` going to include the action of filling out this form we'll use -`And`. +and description. To keep our `When` going to include the action of filling out this form +we'll use `And`: - And I fill in "Name" with "Veloci-chew toy" - And I fill in "Price" with "20" - And I fill in "Description" with "Have your raptor chew on this instead!" +[[[ code('075f0e0451') ]]] There *is* a secret reason of why I'm using language like "I fill in" after the `And`, which we'll cover soon. Lastly, in our process I'll expect to hit a save button to -finish creating my new product. So let's add another line to our scenario. +finish creating my new product. So let's add another line to our scenario: - And I press "Save" +[[[ code('fd94e773ab') ]]] At this point my product should be saved and I will be redirected to another page with a success message to prove that this worked. This is where we'll say: - Then I should see "Product Created FTW!" +[[[ code('ee1609baed') ]]] Isn't that a nice way to plan out your user flow? When we *do* finally code this, we'll know exactly how everything should work.