I would just like to say that myself and my brother really appreciate your insightful videos. They seem to be a very clear cut crystalisation of many of the GOTO conference videos we have avidly watched over the last few months. I have been at times been quite cynical of TDD in certain forms but in one of your other videos (BDD vs TDD) as well as this one, I can see that BDD is really an effective and potent customer-relevant tool. In your BDD vs TDD video in particular I like your applied checklist for things like separation of concerned, etc - and basically everything one thinks makes good internal quality of software. That as a checklist for BDD for me makes the whole concept much more effective and very lucrative. We both liked your amoeba illustrations there mapping tests to code and how you can just be doing tests tokenly if the BDD tests not created first. As a small business owner, I am more keen on the BDD interpretation than the more technical TDD. In fact, I am thinking of having some days to dream up my own BDD requirements to try and improve current facilities. Thank you for sharing your great insights. Cheers, Tryfon
I'm a simple man. I see new CD video, i click Like. :) Thank you for sharing your knowledge. :) One thing i am thinking about is... to model systems the way that they are always easy to transform. Rename things, move around etc. Like.. "The Change" should be first class citizen. You never will be able to establish ubiquitous language upfront. You never will find The Domain Expert who will tell how to name and group domains, etc. So... you should be able to go with whatever works today, but be deeply comfortable to change that thing whenever a better idea will came into your mind. I could trace that even back to monorepo/polyrepo battle/setup, build systems, issue tracking, feature toggles, etc. The infrastructure should be in place to be comfortable with refactoring. If you are not comfortable with refactoring, this will lead to really bad products.
First thanks for that, I am pleased that you like them. Second, 💯 yes my approach to software dev is wholly an iterative, incremental one. I believe that ib pretty much every aspect, SW dev is an exercise in learning and discovery. Certainly when it comes to building a Ubiquitous Language, and so a test DSL. You will learn new things that you want to add, and find better ways to express things that you already have and find that you got it wrong earlier on. Organising our work so that we are able to make mistakes and grow our learning seems fundamental to me. So I agree completely with your comment.
In my career it always seems like there is too little focus on the product and understanding its use cases. Developers just start to write code without proper analysis and design.The focus then is on structure and how to map what is in "User Stories" - since there are no clear mapping between code and Use Case. Understanding the product and code is largely two different things. And yes programmers like to tackle problems from a technical perspective, that is what most focus should be if you ask them and not meetings. But I argue it is rather about understanding the domain.
With an ubiquitous language we also solve the problem of using the same term for 2 different things. The current example from my experience was "a partition" which was used in terms of the group of rows in database and the Spark dataset partitioning. So when someone said a partition ID I was confused what are we talking about. Also for me learning a domain language, when joining a new ptoject is one of priorities. I'm always looking for joining beginner courses or trainings at the start of a new project. Like the "Payments 101" course when worked for a payment processor, or the junior energy analitics training when worked on a energy bills validation system.
3 года назад+4
In my projects BDD meets the DDD at the domain service layer. BDD creates the interface and DDD creates the implementation.
Hi Andrej, this is the level of scope that I am very much interested in. I see the value in system-level acceptance tests testing a GUI, REST API, etc. However, I want to better understand how best to apply BDD to a service layer consisting of Command handlers (i.e. hexagonal/clean). Do you use a Gherkin-based BDD framework or something more code-based like what Dave shows?
I would like to see a video where you walk us through creating executable BDD specifications. There are some examples in this video of them, but how did you arrive there? How to go from mere specifications to executable specifications? Any tips? Steps involved? Thought process?
Well, this video is demonstrating the approach that I recommend, albeit with simple tests. 1. Write stories from the perspective of users in the Ubiquitous Language. Adopt the discipline to say NOTHING about how the system works in these stories. 2. Think of examples that would demonstrate that the need that the story captures is met. Write those down in the UL. 3. Translate these descriptions into executable specifications in your DSL. 4. Add any missing test-infrastructure or DSL concepts that didn't exist before, but that you test case relies upon. In this step concentrate on keeping the DSL 'clean' of anything about "how" the system works, isolate that understanding in your Protocol Drivers. There are code-examples on-screen for all of these steps in this video. If you'd like to see some different angles on this I have a series of videos on BDD and Acceptance testing on the channel, take a look here: ruclips.net/p/PLwLLcwQlnXBzwEqy9R3odTJKURxfwqDXa For a little more detail on the plumbing to support the DSL, checkout this conference talk: ruclips.net/video/Rmz3xobXyV4/видео.html
Thank you so much for the content you create. It's helped me and our team take a different mindset. We are still not there but moving slowly there. It's quite hard advocating for this on the gamedev industry.
Hi Dave, thx for sharing your knowledge. A question regarding BDD, you described a case when it is well imiplemented, but what if it isn't well implemented, what are the pro/con to trying to refactor/reimplement BDD the correct way?
Hard too answer in general terms. It depends how badly implemented, and how useful the resulting, poor, tests are. I think, in general, it is better to improve going forward than to look back. So I'd begin by improving how you create new tests for new work. This will make it easier to learn how to do it well. It will also help you to establish the basics of your DSL. A slight modification to that, is it may help to identify a simple, but very common representative use-case for your system and use that to begin you DSL with, even if you do have some tests that cover that already - re-implement tests for this simple scenario in your new DSL. So don't try to back-fill the tests, start with some simple cases to establish the test infrastructure and DSL. Only later decide which of the old bad tests to replace. Once you have a DSL in-place, it may be easier than you think to replace the old tests - as long as you know what it is that they test.
Thank you for the video - I appreciate the simple and concise examples, and I am a huge advocate for DDD. But I do have a question regarding your examples. How is the acceptance test evaluated here? There does not seem to be any assertions in the specification's test class. Is this simply an oversight in the example?
Not an oversight, I probably made it more opaque by picking a bad name. In my test cases I prefer to abstract the assertions. This is mainly personal preference, but what I have found is that if you leave regular assertions in the test-cases at this level, dev's can't resist the call to start exposing how the system works through the assertions. So I generally add a 'confirm' step at the end of most of my tests. It's not always necessary, because I ALWAYS encode each step as a synchronous step, so if the 'bookRoom' step hadn't worked it would have reported a failure - never fail silently at this level of abstraction. So my 'confirmBooking' step *is the assertion* in this example. I'd code that to go and look up my list of bookings and check that there was one with all of the params that I supplied. Given you comment though, in hindsight, I can now see that 'confirmBooking' could easily be misinterpreted as a domain relevant idea, so sorry for the confusion.
Great video, but how would you define the HOW in this process? If the Delivery team work to define these BDD style Stories\scenarios that are independent of the solution, when\how is the actual Solution then defined? And how are the details for the solution captured?
Dave, I could not find any videos of yours where you talk about hexagonal or clean architecture specifically. It is obvious that BDD is awfully similar to clean architecture as it has use cases as one of its layers, but I wonder if you could talk about these architectures and compare them to each other a bit. Maybe Hexagonal, Onion, Clean and Microservices discussion to see how all this nicely connects with BDD and DDD.
I love these BDD videos. Although I would like a lot more practical ones. Most BDD examples cover basic test cases to get you started but what about the more complex system? Like how would one define features for automated jobs and not user interactions? Would the 'when' be 'when I run the job' or is that too specific? Also how do teardowns work? I find it fun to test changes in system states, but difficult to revert to an original state after each test. Okay one last question. Should steps be independent or can there be a context that changes as steps continue? For example, I would rather write: Given there is an employee And this employee has age 29 Than Given employee '132' exists for year '2021' And employee '132' for year '2021' has age '29' I feel some more detailed BDD practical example videos would help a lot.
Did you see this one? "A Real World Example of BDD" ruclips.net/video/9P5WG8CkPrQ/видео.html I see no problem with "Given an employee who is 29" or similar, make it readable.
We used a Gherkin framework in a previous assignment and frankly I hated it. The test framework performed regex matching on our gherkin cases in order to invoke the right code, but it was really hard to execute linters on our tests because the english prose was not translated to python until runtime. It was also not possible to apply RAII like you can do easily with pure Python. I found a bug where one test did Start service X and other Start Y they were supposed to match different rules but due to a misstake in the regex they ran the same command. In short - I want to see real code in my tests, otherwise the distance from idea to implementation is too large.
Wether you like Gherkin or not, I think that the separation of concerns between "what" the system does and "how" it does it is pretty much vital to doing automated testing well. I confess that I don't like Gherkin much either. I prefer "internal DSLs" for my tests, the examples in this video are how I write my DSLs - I write my own test infra, though may use other tech (e.g. Selenium) for Protocol Drivers.
13:15 Why not "void bookRoom(Params params)" ? Are those arguments really optional? How one would know the "driver.bookRoom()" is successful? Not throwing an Exception?
If my system consists of separate ui and Server api (e.g. Java rest-api and react Single page application) how would these tests look? Would they be end-to-end (selenium) or would I Test the two parts separately?
The missing point here is, nor BDD does not prevent client to change mind in the middle of sw development and change random requirements, causing rewrite 1/2 of BDD designed sheets. That is most common problem with clients. BDD is great method, but I would not connect that with managing clients and their behaviour. Clients often do not read long texts and specifications, they rather protests when see the feature, so to make prototype is absolutely crucial. Most of a clients are visual and emotional people, not technical.
Hello Dave, thanks for your content, little offtop question: When using TDD do you always refer to unit or integration testing? Or could there be just integration tests? I want to apply TDD to game development but since in gamedev continouous change of design and refactors happen I also have to rewrite my unit tests, thats headache. But integration tests used to artificially pass through the whole game without unit testing each single system seem less prone to refactors forced by changing design. Thats not right video to post the question under but I need this help :)
If you can't use unit tests for refactoring production code, your unit tests are probably unnecessarily coupled (e.g. one test class per production class sometimes cause this). Bob Martin Clean Coders website have some videos on TDD that may help.
Hello Sir. I am implementing a structure with the following hierarchy: Product, Functional Area, Scenarios. A product is a ship-able piece of software (such as a mobile app or web service). A functional area is a child to the product that maps to what you call a 'problem domain'. A scenario is a child of a functional area. A scenario can be tested via 'given-when-then' (gherkin) or via 'describe-it' (jest). In either case, the 'domain language' is agreed by the 3 amigos and must remain constant between the story, test, release notes, and support documentation. Does this approach match what you are discussing here or is there a difference between DDD and my current approach? If there is a difference, can we discuss via video or some zoom conference? Thanks
Not sure that I follow your description of "functional area" I am pretty sure that that is no the same as "problem domain" though. The problem domain is everything about the problem that you are trying to solve. The solution domain is the alternative, everything about how you solve the problem. You may be thinking of "bounded context" when you describe "functional area". A "bounded context" is a part of the "problem domain" where the concepts are consistent. So, for example, If my "problem domain" is selling books. The taking orders for books, maybe a "bounded context" within that, broader, problem domain. Fulfilling orders for books may be another, different, "bounded context". Both may share the idea of an "order" but each needs different things from an order and so should have a different representation of it. Lots more on this in the DDD book by Eric Evans.
"this is a free 15-minute video what do you expect" Lol, now I appreciate it more, thx for the video
I would just like to say that myself and my brother really appreciate your insightful videos. They seem to be a very clear cut crystalisation of many of the GOTO conference videos we have avidly watched over the last few months. I have been at times been quite cynical of TDD in certain forms but in one of your other videos (BDD vs TDD) as well as this one, I can see that BDD is really an effective and potent customer-relevant tool. In your BDD vs TDD video in particular I like your applied checklist for things like separation of concerned, etc - and basically everything one thinks makes good internal quality of software. That as a checklist for BDD for me makes the whole concept much more effective and very lucrative. We both liked your amoeba illustrations there mapping tests to code and how you can just be doing tests tokenly if the BDD tests not created first. As a small business owner, I am more keen on the BDD interpretation than the more technical TDD. In fact, I am thinking of having some days to dream up my own BDD requirements to try and improve current facilities. Thank you for sharing your great insights. Cheers, Tryfon
Thanks, I am pleased that you find them interesting.
I'm a simple man. I see new CD video, i click Like. :) Thank you for sharing your knowledge. :) One thing i am thinking about is... to model systems the way that they are always easy to transform. Rename things, move around etc. Like.. "The Change" should be first class citizen. You never will be able to establish ubiquitous language upfront. You never will find The Domain Expert who will tell how to name and group domains, etc. So... you should be able to go with whatever works today, but be deeply comfortable to change that thing whenever a better idea will came into your mind. I could trace that even back to monorepo/polyrepo battle/setup, build systems, issue tracking, feature toggles, etc. The infrastructure should be in place to be comfortable with refactoring. If you are not comfortable with refactoring, this will lead to really bad products.
Absolutely Wells said
Agree, architecture evolves if you can change things (specs change, technology changes, your abilities [positively] change, ...)
First thanks for that, I am pleased that you like them.
Second, 💯 yes my approach to software dev is wholly an iterative, incremental one. I believe that ib pretty much every aspect, SW dev is an exercise in learning and discovery. Certainly when it comes to building a Ubiquitous Language, and so a test DSL. You will learn new things that you want to add, and find better ways to express things that you already have and find that you got it wrong earlier on. Organising our work so that we are able to make mistakes and grow our learning seems fundamental to me. So I agree completely with your comment.
In my career it always seems like there is too little focus on the product and understanding its use cases. Developers just start to write code without proper analysis and design.The focus then is on structure and how to map what is in "User Stories" - since there are no clear mapping between code and Use Case. Understanding the product and code is largely two different things. And yes programmers like to tackle problems from a technical perspective, that is what most focus should be if you ask them and not meetings. But I argue it is rather about understanding the domain.
With an ubiquitous language we also solve the problem of using the same term for 2 different things. The current example from my experience was "a partition" which was used in terms of the group of rows in database and the Spark dataset partitioning. So when someone said a partition ID I was confused what are we talking about.
Also for me learning a domain language, when joining a new ptoject is one of priorities. I'm always looking for joining beginner courses or trainings at the start of a new project. Like the "Payments 101" course when worked for a payment processor, or the junior energy analitics training when worked on a energy bills validation system.
In my projects BDD meets the DDD at the domain service layer.
BDD creates the interface and DDD creates the implementation.
Hi Andrej, this is the level of scope that I am very much interested in. I see the value in system-level acceptance tests testing a GUI, REST API, etc. However, I want to better understand how best to apply BDD to a service layer consisting of Command handlers (i.e. hexagonal/clean). Do you use a Gherkin-based BDD framework or something more code-based like what Dave shows?
Mind-blown, life change video. Thank you so much!!!! Separation of concern from concept to implementation wow... Mind-blown
Thanks, glad you liked it.
I would like to see a video where you walk us through creating executable BDD specifications. There are some examples in this video of them, but how did you arrive there? How to go from mere specifications to executable specifications? Any tips? Steps involved? Thought process?
Well, this video is demonstrating the approach that I recommend, albeit with simple tests.
1. Write stories from the perspective of users in the Ubiquitous Language. Adopt the discipline to say NOTHING about how the system works in these stories.
2. Think of examples that would demonstrate that the need that the story captures is met. Write those down in the UL.
3. Translate these descriptions into executable specifications in your DSL.
4. Add any missing test-infrastructure or DSL concepts that didn't exist before, but that you test case relies upon. In this step concentrate on keeping the DSL 'clean' of anything about "how" the system works, isolate that understanding in your Protocol Drivers.
There are code-examples on-screen for all of these steps in this video.
If you'd like to see some different angles on this I have a series of videos on BDD and Acceptance testing on the channel, take a look here: ruclips.net/p/PLwLLcwQlnXBzwEqy9R3odTJKURxfwqDXa
For a little more detail on the plumbing to support the DSL, checkout this conference talk: ruclips.net/video/Rmz3xobXyV4/видео.html
Thank you so much for the content you create. It's helped me and our team take a different mindset. We are still not there but moving slowly there.
It's quite hard advocating for this on the gamedev industry.
Thanks, I'm pleased to hear that my videos are helping.
Hi Dave, thx for sharing your knowledge. A question regarding BDD, you described a case when it is well imiplemented, but what if it isn't well implemented, what are the pro/con to trying to refactor/reimplement BDD the correct way?
Hard too answer in general terms. It depends how badly implemented, and how useful the resulting, poor, tests are. I think, in general, it is better to improve going forward than to look back. So I'd begin by improving how you create new tests for new work. This will make it easier to learn how to do it well. It will also help you to establish the basics of your DSL.
A slight modification to that, is it may help to identify a simple, but very common representative use-case for your system and use that to begin you DSL with, even if you do have some tests that cover that already - re-implement tests for this simple scenario in your new DSL. So don't try to back-fill the tests, start with some simple cases to establish the test infrastructure and DSL. Only later decide which of the old bad tests to replace. Once you have a DSL in-place, it may be easier than you think to replace the old tests - as long as you know what it is that they test.
@14:05 the id and string arguments are swapped making the slide a bit confusing
Thank you for the video - I appreciate the simple and concise examples, and I am a huge advocate for DDD. But I do have a question regarding your examples. How is the acceptance test evaluated here? There does not seem to be any assertions in the specification's test class. Is this simply an oversight in the example?
Not an oversight, I probably made it more opaque by picking a bad name. In my test cases I prefer to abstract the assertions. This is mainly personal preference, but what I have found is that if you leave regular assertions in the test-cases at this level, dev's can't resist the call to start exposing how the system works through the assertions. So I generally add a 'confirm' step at the end of most of my tests. It's not always necessary, because I ALWAYS encode each step as a synchronous step, so if the 'bookRoom' step hadn't worked it would have reported a failure - never fail silently at this level of abstraction.
So my 'confirmBooking' step *is the assertion* in this example. I'd code that to go and look up my list of bookings and check that there was one with all of the params that I supplied. Given you comment though, in hindsight, I can now see that 'confirmBooking' could easily be misinterpreted as a domain relevant idea, so sorry for the confusion.
@@ContinuousDelivery Indeed I did read the confirmBooking as part of the normal usage of the domain. Thank you for the clarification.
Great video, but how would you define the HOW in this process?
If the Delivery team work to define these BDD style Stories\scenarios that are independent of the solution, when\how is the actual Solution then defined? And how are the details for the solution captured?
Dave, I could not find any videos of yours where you talk about hexagonal or clean architecture specifically. It is obvious that BDD is awfully similar to clean architecture as it has use cases as one of its layers, but I wonder if you could talk about these architectures and compare them to each other a bit. Maybe Hexagonal, Onion, Clean and Microservices discussion to see how all this nicely connects with BDD and DDD.
Thanks for the suggestion. I will think about it.
I love these BDD videos. Although I would like a lot more practical ones. Most BDD examples cover basic test cases to get you started but what about the more complex system?
Like how would one define features for automated jobs and not user interactions? Would the 'when' be 'when I run the job' or is that too specific?
Also how do teardowns work? I find it fun to test changes in system states, but difficult to revert to an original state after each test.
Okay one last question. Should steps be independent or can there be a context that changes as steps continue? For example, I would rather write:
Given there is an employee
And this employee has age 29
Than
Given employee '132' exists for year '2021'
And employee '132' for year '2021' has age '29'
I feel some more detailed BDD practical example videos would help a lot.
Did you see this one? "A Real World Example of BDD" ruclips.net/video/9P5WG8CkPrQ/видео.html
I see no problem with "Given an employee who is 29" or similar, make it readable.
We used a Gherkin framework in a previous assignment and frankly I hated it. The test framework performed regex matching on our gherkin cases in order to invoke the right code, but it was really hard to execute linters on our tests because the english prose was not translated to python until runtime.
It was also not possible to apply RAII like you can do easily with pure Python.
I found a bug where one test did
Start service X
and other
Start Y
they were supposed to match different rules but due to a misstake in the regex they ran the same command.
In short - I want to see real code in my tests, otherwise the distance from idea to implementation is too large.
Wether you like Gherkin or not, I think that the separation of concerns between "what" the system does and "how" it does it is pretty much vital to doing automated testing well. I confess that I don't like Gherkin much either. I prefer "internal DSLs" for my tests, the examples in this video are how I write my DSLs - I write my own test infra, though may use other tech (e.g. Selenium) for Protocol Drivers.
@@ContinuousDelivery I’ll give it another try some day :)
13:15 Why not "void bookRoom(Params params)" ? Are those arguments really optional? How one would know the "driver.bookRoom()" is successful? Not throwing an Exception?
If my system consists of separate ui and Server api (e.g. Java rest-api and react Single page application) how would these tests look? Would they be end-to-end (selenium) or would I Test the two parts separately?
I like yer shirt in this one, Dave.
The missing point here is, nor BDD does not prevent client to change mind in the middle of sw development and change random requirements, causing rewrite 1/2 of BDD designed sheets. That is most common problem with clients. BDD is great method, but I would not connect that with managing clients and their behaviour. Clients often do not read long texts and specifications, they rather protests when see the feature, so to make prototype is absolutely crucial. Most of a clients are visual and emotional people, not technical.
Hello Dave, thanks for your content, little offtop question:
When using TDD do you always refer to unit or integration testing?
Or could there be just integration tests?
I want to apply TDD to game development but since in gamedev continouous change of design and refactors happen I also have to rewrite my unit tests, thats headache.
But integration tests used to artificially pass through the whole game without unit testing each single system seem less prone to refactors forced by changing design.
Thats not right video to post the question under but I need this help :)
If you can't use unit tests for refactoring production code, your unit tests are probably unnecessarily coupled (e.g. one test class per production class sometimes cause this).
Bob Martin Clean Coders website have some videos on TDD that may help.
Bear B'n'B 😂😭 I love the little touches
😉
Hello Sir. I am implementing a structure with the following hierarchy: Product, Functional Area, Scenarios. A product is a ship-able piece of software (such as a mobile app or web service). A functional area is a child to the product that maps to what you call a 'problem domain'. A scenario is a child of a functional area. A scenario can be tested via 'given-when-then' (gherkin) or via 'describe-it' (jest). In either case, the 'domain language' is agreed by the 3 amigos and must remain constant between the story, test, release notes, and support documentation. Does this approach match what you are discussing here or is there a difference between DDD and my current approach? If there is a difference, can we discuss via video or some zoom conference? Thanks
Not sure that I follow your description of "functional area" I am pretty sure that that is no the same as "problem domain" though. The problem domain is everything about the problem that you are trying to solve. The solution domain is the alternative, everything about how you solve the problem.
You may be thinking of "bounded context" when you describe "functional area". A "bounded context" is a part of the "problem domain" where the concepts are consistent. So, for example, If my "problem domain" is selling books. The taking orders for books, maybe a "bounded context" within that, broader, problem domain. Fulfilling orders for books may be another, different, "bounded context". Both may share the idea of an "order" but each needs different things from an order and so should have a different representation of it. Lots more on this in the DDD book by Eric Evans.
Wow
Text version, please.
Sorry don't have the time.
@@ContinuousDelivery you're doing pretty much. thank you
What is a text version?
That's a pretty bold and rude ask.
@@brooksfire9580 , do not spam. Your comment also can be represented as "bold and rude", and, more important, meaningless.