Getting started with Behavior Driven Development (BDD) in .NET using SpecFlow

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nick and today i'm going to show you how you can get started with bdd or behavior driven development in dot net and i'm going to be using something called spec flow to achieve that uh there are multiple libraries uh for you to be able to implement or actually practice bdd in dot net but spec flow is the most mature and it actually has um the biggest ecosystem around everything else so i'm gonna be using that there are many others and by no means am i saying that spec flow is the best but it does the fundamentals right so that's why i'm going to be showing you uh the concept using that library what i want to say is that i'm not going to be diving into the concept itself in this video this is more about how you can actually get your hands dirty and write using bdd write code there are plenty of videos explaining the concept and for you to be landing here i'm assuming that you've watched one you want to see how you can actually implement it in c sharp and dot net that being said i'm gonna briefly explain what bdd is now but if you just care about the code you skip to the timestamp in the timeline of the video and go straight into the implementation now behavior different development or bdd sounds a lot like a test driven development or tdd which we've talked uh in this channel before and the idea that carries over is that you don't start from your code your implementation you start from an external point which is trying to test or drive the implementation and tdds your unit test and you say what the unit should be doing in bdd it is the acceptance criteria or the feature or the scenario uh those different meanings and i'm going to explain where they are as i'm writing them um the the advantage of bdd is that anybody can write at least the specification of a test in bdd and anybody can read it i can give it to my business analyst product owner in fact ideally you want your product people your business people to actually write the specs and you just do the mapping and you implement the code behind that spec this will make way more sense as i am actually showing you how to do this in practice but fundamentally it's the idea that the behavior of your system drives the code and the implementation of the system you can think of it as an evolution from tdd or like a very nice marriage between tdd and atd which is acceptance test driven development those are concepts that are just lending ideas from one another to achieve this one and if you see this from a ddd perspective domain driven development perspective it is actually diving more into the domain itself rather than something like tdd which is very focused on the unit uh let's just dive straight into the code because i think you're gonna understand the concept if you're even if you're unfamiliar with it a way easier by watching me actually practice it and talk you through the process so what i'm going to do first is i'm going to create a test project i'm not going to use a unit test project here i'm just going to go ahead and create a simple class library and i'm going to copy that and i'm going to say i could say bdd i'm going to say tests naming is completely up to you i could just say test.behavioral or behavior and now i have that i'm going to go ahead and create it i'm going to add a few new packages or libraries in this project the first thing i want to add is let's go to the new packages i want to go ahead and add spec flow so i'm going to type specflow dot x unit so it's spec flow with x unit as a runner behind the scenes and i'm going to go ahead and install that then i'm going to add fluent assertions which is my favorite package for doing a sessions during testing we will be asserting different values so i want to have that here i'm also going to add the microsoft dot where is it dot net.test.sdk this is the main testing.net library and that should be it so now i have my class library and i have the libraries and so what i want to do now is i'm going to go ahead and create three folders i'm going to create one called features another one called hooks and another one called steps so in bdd we have something called a feature and a feature is a feature of your system very self-explanatory and those features are satisfied based on scenarios and scenarios you can think of them as acceptance criteria if you work in an agile team that is using gyro tickets and you're doing your sessions or your acceptance criteria based on the given when then approach it's very much the same thing and that's what we're trying to achieve here a human readable in plain english feature or test and we can drive our tests through that feature what i should say is that in my idea which is jetbrains rider i have actually installed the spec flow plugin which enables support for syntax highlighting i go to reference auto create steps and stuff like that there's similar extension for visual studio if you're using it i don't know about visual studio code but i think there is something for that as well so that's also something else that you basically need to get started so what i'm going to do is i'm going to create a feature file and i'm going to talk to you about what we're going to be doing in this video right so imagine there's a system where we are selling clothes and if you're a logged out user so a guest and you're buying something you're paying full price for the items so if a t-shirt is costing you a hundred dollars um then you're gonna pay that amount but if you're a logged in user you get an exclusive discount and you're gonna pay five percent less so 95 uh dollars so we're going to be implementing that logic into our feature through a couple of scenarios so let's start with that and i'm going to say logged in discount dot feature so we have a dot feature file and actually writer has specific highlighting for that because that feature is detected as something that is expecting to have a syntax called gherkin and gherkin is effectively english in a very structured way i'm gonna show you how that looks like so first you start with a feature so you say feature and you describe your feature and you say logged in users have a discount simple as that and then after that you say as uh and the persona as a user i want to have a five percent uh discount when i am logged in so this very much reads like english now there's no mapping in that specific phrase but just by looking at the feature this should describe what this specific feature file is dedicated to what are you doing okay i'm checking and making sure i'm testing for a user that has a five percent discount uh when they're logged in so let's go ahead and create the couple of scenarios right the ones we want to implement so scenario and we give it a name guest users so users are not logged out logged in should pay full price and we're going to describe this scenario in gherkin with given when then and you can have the end word as well so it looks like this given a user that is not logged in when a t-shirt is added to the basket in fact a t-shirt that costs 5 gbp is added to the basket then the basket value is 5 gbp this looks very much like english you can see it and you can read it we have read squiggly lines and that's because we don't have steps uh implementing those ideas but fundamentally that's what your test looks like that's what you could be given by your product analyst or your business analyst product owner and they could write this anybody could write this anybody can read this is the beauty of it and we can actually make this a bit more elaborate right so what we can say is given a user that is not logged in and an empty basket when a t-shirt that costs 5gb is out to the basket then the value is 5gbp now this is one of the scenarios i'm gonna also write the other one which is and i'm actually going to copy it i'm just going to type it so scenario 2 is logged in users should have a 5 discount i'm going to say given a user that is logged in and an empty basket when a t-shirt or when i don't know address that costs 100 gbp is added to the basket then the basket value is where it should be 95 gbp right because we want to represent the five percent discount so now we have our tests and we're ready to generate our steps what you're seeing here is my automatic test running every time i save i'm running my tests and you will see that currently there's no tests to run but when we start implementing that you're going to see them there so now i have my feature if i was to build that project a c-sharp file called loggedindiscount.feature.cs would show up with a whole bunch of generated code the beauty of specflow is that it will actually generate the c-sharp code to make those tests run using the runner you selected so what i'm going to do is i'm going to leave this as it is and i'm gonna create under steps a new class and i'm gonna call this logged in uh discount steps i'm not gonna do anything all i'm gonna do is i'm gonna add a binding attribute at the top of the class and i need this so my feature file detects the steps in my steps file so i'm going to go here and because i have the plugin i can do create step and this will automatically go to the only step finder i have and create the step and generate the code for it if this was if i had more than one step then i would be able to choose where i wanted to be generated but now i have my given generated for me and then i can do the same for the second one so an empty basket is also generated now i have this and i'll come back to that in a second and then i have the last one as well um you will see that the squiggly lines here are still here because this is not created so i'm going to create that as well but i'm not going to attach these two because a good thing about this language is that you can actually parameterize it so let me move that up top and i'm not going to implement the methods but i'm going to parameterize the given one events a little bit to make them more generic so what i want to do is i want to see okay this looks fine this looks fine i don't need to touch this this looks fine here i could actually parameterize this to make it more generic a t-shirt is just an item name so what i'm going to do instead is i'm going to say i can use regex here and you can see i have autocomplete with with rider and i'm going to match one parameter with regex which is the item name so string item name or product name and then i'm gonna also do that for the price i could do it for the currency as well if you want to check fx rates and stuff like that and i'm gonna say decimal price and now this is generic and i'm going to also do the same thing for the thing at the bottom so as the 5gbp i'm going to say basket value and now the moment i save these squiggly lines here should go away and they do go away indeed because the given one vans are matching the regex and i can actually reuse the same steps because the logic is the same it's the parameters that are different so things like 5 5 95 those are parameters now which i can bake into my logic and i can reuse the steps it starts coming together doesn't it i think it's a very elegant way in a very readable way now to write your behavior the problem with this concept altogether or the drawback is that because there's no mocking involved and you're actually running the thing targeting potentially a mock database but with integrated systems it can take way longer than what um a unit test would take you know you just usually take seconds this can actually take minutes to run because you are targeting a real system and you're validating it um across the feature not across a unit um what i'm not gonna be talking about this video but if you want me to i can actually make a follow-up video to this is hooks and hooks give us the ability to create um setups and tear downs in our tests so we can say that before you run this feature or before you run this scenario spin up a database or create this or shut down the database and tear it down we're not going to be doing it here because i want to keep the video small and the scope small but realistically you would also be using hooks i will have links in the documentation of spec flow in the description so you can actually go and check it out yourself if you want but for now we're gonna only be focusing on features and steps now what i'm also gonna do is i'm gonna create a new project and i'm gonna call it um i don't know service which is the pricing service or whatever service we're going to be pretending that we're using in in this system because i want to add a few uh things like a pricing service and a basket service maybe just some logic in there and what i'm gonna do is i'm gonna go ahead and say uh i'm gonna add a reference to the file so refer to that project and that's where we're gonna create our code when we start running our tests now if i was to save and trigger a test running you should be able to see the the two features i have so guest users should pay full price and logged in users should pay a five percent discount if i run those tests because i have the pending step they will fail and now we're in the red step of the process where now we need to implement the code to satisfy those conditions you could actually already have the code satisfy those conditions in some scenarios because i mean it's called behavior driven development but it's something you can implement halfway through the project as well it's not prohibitive like what unit testing would be so keep that in mind so i'm gonna hide that for now and what i'm going to do is i'm going to copy a bunch of code that i already have and i'm going to talk you through the code it's the service code which we will be using so now i'm pretending that i'm writing code that satisfies those conditions so now i've copied over my code and i have a bunch of classes in the same file it's not the best practice you should actually separate them and properly structure this project for economy of time and economy of this video i'm actually just going to have it in the same file but don't do this so now that i have the code i'm going to start satisfying those conditions to make the tests pass so let me just expand this so you can see them running and failing and i'm going to enable continuous testing so every time i uh save so control s it's going to rerun the tests that's what you can see now every time i save so perfect i'm going to go ahead and start satisfying those tests and first what i want is i'm going to have a user so private user and that's the user we're going to use for those tests side note for those who are more familiar with spec flow i'm well aware that you can actually inject and share context and do way more complicated things um but this is something we're gonna follow up in a next video not on this one so i know that some of those things are not the absolute best practice but for the sake of what i'm showing here and with the runner i'm using this unit um it it will work fine so we have the user which we're gonna create in either of the givens that refer to the user then we have the the basket which we're gonna initialize in that step and then we need products so i can have actually a list of products based on how many closes i have and add them in the basket actually i'll see if i need this let me comment let me comment it out first what i need is a user so what i'm going to say is given a user that is not logged in so i'm going to say user equals new user is logged in equals false and let me just make it clearer so we have a user that is not logged in and we also have the uh given a user that is logged in and in this scenario i'm going to say logged in true now we also have an empty basket and the basket is tied to the user so i'm going to say basket equals new basket and we have user equals the user we have initialized already so this is failing because the code wasn't compiling uh my tests are still failing because they're validating against the behavior that's the beauty of it we're gonna we're gonna possibly gonna pass when we satisfy those conditions with our code and then what i need is to let me just put that in a new line so you can see what's going on and then we need to do the math and say willing to use a pricing service actually so i'm going to create a pricing service here private read only i pricing service pricing service equals a new pricing service and i'm gonna use that below so what i'm gonna say is when a t-shirt that costs 1 gbp is added to the basket uh actually i'm not i'm just using it here here what i want to say is basket.products.add and i'm going to add this new product which is name item name and price equals price here we go and last but not least i'm gonna get the basket that's the expected basket value so i'm gonna say expected basket value and then i'm gonna get the actual so basket value equals underscore pricing service dot get basket total amount which we're gonna use the basket for here you go and we're gonna set that so basket value should be and then we gonna use the expected and if i press save my test should be passing and they are passing because my conditions in the feature file are now satisfied if i was to change that so let's let's do an experiment right let's say that uh the basket value is not 95 the basket value is 50. so 50 discount if i save and my test run one of them is failing because this condition this behavioral condition is not satisfied that is what we are achieving with this thing and the good thing about this is i can give this to my product manager my product owner my product whatever and i can see exactly what my application is doing in order for you to successfully implement such a thing in your team everybody needs to be on the same page including product qa engineers it's absolutely not something which you can just drop in and expect everybody to be on the same page but i think that with proper training if you feel the need to have something like that in your team you can actually get quite a bit out of it the problem with that test however is that yes a test can fail but can fail for any reason and usually you don't exactly know why it failed because in unit tests you have this very isolated unit that you're testing you know exactly what happened the behavioral test can actually be testing external services as well as part of the flow so mocked or not so it becomes harder to identify exactly what's going wrong as a first step i think that this explains a real-world scenario where you can actually use bdd that being said we only are scratching the surface so if you want me to continue the series please leave a comment description down below and i'm more than happy to make more videos on the subject that's all i have for you for today thank you very much for watching special thanks to my patrons for making this videos possible if you want to support me as well you're going to find the link in description down below leave a like if you liked this video subscribe for more content like this and ring the bell as well and i'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 19,683
Rating: 4.9627328 out of 5
Keywords: Elfocrash, elfo, coding, asp.net, .netcore, dot net, core, C#, how to code, tutorial, asp.net core, js, csharp, rest api, lesson, dev, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, asp.net core 3, .net core for beginners, .net 5, asp.net core 5, Getting started with Behavior Driven Development (BDD) in .NET, BDD in .NET, behavior driven development, ddd, domain driven development, bdd, unit testing, specflow, gherkin, feature, scenario, dotnet, .net
Id: EEeVU0z26u0
Channel Id: undefined
Length: 22min 17sec (1337 seconds)
Published: Mon Feb 15 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.