I've been using this approach for a couple of years, and the thing I love the most is the predictability of where to find the respective tests for the code I'm changing.
Hi! I've been looking around some videos on clean architecture and good software engineering and your channel is one of the best! Great content, perfect speed and you go straight to what's important with good explanations on why you do things in a certain way. Keep it up and thanks for taking the time to do these videos.
Nice video. This is the sort of pattern I use especially when it comes to naming and creating common fixture data that doesn't clutter the test. However, when it comes to creating the Sections and the items I would use a delegate that returns a list rather than an instance of a list. So for example where in the final test there were a set of sections that each referenced the same list of items, we can provide a different list of items to each section.
Thanks Amichai, for all your vidéos, You were going to make another video showing how to handle invariants and domain errors. I'm really looking forward to that one. Thanks.
Great video, extremely well explained and showcased! I'm quite surprised I've been working almost exactly the same way with my testing infrastructure (although your example is a bit more graceful than my actual projects). The one thing that gave me a lightbulb moment was splitting the constants into partial classes in separate files, genius. I wish I had partial classes in my current Java project...
We have arrived at a similar state with our tests. I tend however to move the constants to inside a static object/model if it's common or variable inside the test method. If I need to assert on one of the properties of the model that's when I tend to have that defined as a method level constant (defined at the top of the method...screaming at me, in CAPITALS).
How can you debug the unittest inside of vscode? I assume, you use the "debug test" from Dotnet Test Explorer Extension. But it did not work for me. Would be great, if you can elaborate more on that. :) Great video, by the way.
Awesome video brother! Really learning so many methodologies from you. And one thing, the sound seems a bit lower. Please try to increase in next videos. Wish you best of luck!
Great video! Thank you! Maybe not exactly on the topic of the video, but I have a problem that I don't know how to solve yet using the existing architecture. Namely: I add a function to the repository to search for an entity by identifier, I pass an identifier object to the function as a parameter (HostId hostId hostId as an example), inside the function I use FindAsync(hostId). When executed, the exception "System.ArgumentException: The key value at position 0 of the call to 'DbSet.Find' was of type 'HostId', which does not match the property type of 'AggregateRootId'" occurs. Considering that AggregateRootId is an abstract class, how to solve this problem? I would be grateful for a hint.
Thank you for the great and informative series. I followed all parts and have a question regarding UOW. In a scenario where changes are made to two different aggregates/entities and want to apply it in the database, how would you handle it as one transaction?
I don't like your test naming convention for a few reasons. Like you said once SUT is renamed you need to rename tests. Sooner or later, you will forget to do it. Reviewers of your PR will see change only in SUT source file and will need to check if there are any tests to remind you to rename them. They will most likely not want to spend time searching for tests so they will not do it and it will slip in in every PR. Some of your tests will have wrong names after some time. I don't understand why the name of class containing those tests is not enough? When you see the test failing you see that this test is in SUTTests class so you know exactly what failed. Should - this is so common and I don't like it. What does it mean "Should"? Should, but doesn't have to? No, it must do what it says. When you have test with "Should" in it and it fails is it good or bad? Why bad? The test says it only "should". Plus, it adds to test name length so often they don't fit on screen especially if you split screen to see both SUT and its tests. I use XUnit which uses [Fact] attribute instead of NUnit's [Test]. I like the name "Fact". My tests, when passing state facts about the system. If they fail, this means that Fact is not true. When Test with Should fails it doesn't mean anything to me. So, if I said I state facts about system your test which verifies Handling create menu command would be - ValidRequest_CreatesAndReturnsMenu. Others could be: InvalidRequest_IsRejected. Short and to the point. When you see list of tests passed you can even export them and show business people what has been implemented, they will understand it.
Thanks for the very detailed and informative video. Appreciate it a lot. How about using AutoFixture to generate the models for us because in most cases we do not care about the contents of the objects generated using the Utility Classes?
Good overview. I'd personally use fluent interface if possible instead of default params for creating custom test objects. Like: CreateCommand().WithSections(sections).
@Amichai Mantinband, I guess you also would hurt discoverability (using builder pattern). I have seen test methods with A LOT of default params or params that are unclear. I guess it's the matter of composition and code review. You have to hold your test code to the same code quality standards as regular code.
Same. That’s why I think it’s important to limit the parameters to constructing the top level object, otherwise it’s a slippery slope. Regarding code review, I have yet to see big projects where tests are reviewed thoroughly. At some point, the threshold becomes lower than production code
A function named CreateCommandWithSections(sections) is just as descriptive as the builder class function but without the effort. In addition i can easily change the name (i mean the first part) without affecting other functions.
@@peterfranzmayr3962 Yeah, but naming is one of the hardest parts of programming (imho), especially when you have a lot of different params. Personally, I have troubles with overly descriptive names (and names that expose implementation details). I would probably use data generators in case of complex objects to improve maintainability and readability. But than again having a standard naming convention for your tests and tests helpers improves the situation quite a bit.
my lazy brain goes to wonder if there is a way to make a source generator or chat gpt to write all this test code lol anyway this video is very useful, i was sort of ending up going a similar direction recently even tho less rigorous and more messy. I might not know to write this stuff correctly, but i truly feel bothered when i write messy tests or code in general to just make it "work". 20:46 why did you make the constants class partial?
Hey Ghevi. Partial allows splitting a class’s implementation across files. This way we can have two files that have the constants static class (Constants.Menu and Constants.Host in our case)
@@amantinband have one more question, when trying the convention for naming tests...i understand i should consider my context but in ur opinion... If i have a class called MyService that have many methods instead of mediatr handlers for each operations, should i name a test like "MyService_WhenCreatingProductWithNewId_ShouldReturnSomething" or "CreateProduct_WhenNewId_ShouldReturnSomething"? It seems like in the first case the middle part gets very long.
Hey Amichai. What is your presentation tool called? The one you use to draw on the screen. I have found ZoomIt, which looks like it can do much of the same, but the styling is different, so you are using something different :)
Thanks! I think AutoFixture is a great way for creating mock objects for testing, but I don’t have experience working with it in large projects to confidently suggest it as a go to solution
Hello Amichai! Hope you're doing well. This isn't related to unit testing, but can you please share your key binding of vs code. That'll very much appreciated.
This is the holy grail of unit testing in C#. I have been looking for months for such a detailed and real world oriented video. Thanks a lot!
I've been using this approach for a couple of years, and the thing I love the most is the predictability of where to find the respective tests for the code I'm changing.
This is the best video about unit testing I've ever seen, Thank you for that!
I am using similar approach. The only difference is that i'm keeping my tests as close to the tested project as possible (without the "tests" folder).
Finally, the long waited episode. LOVE it!
This is literally the best series ever for .NET beginners. Thank you!
Hi! I've been looking around some videos on clean architecture and good software engineering and your channel is one of the best! Great content, perfect speed and you go straight to what's important with good explanations on why you do things in a certain way. Keep it up and thanks for taking the time to do these videos.
Thank you sir very much ppreciated. Just asked this in the last video. Thank you sir.
Can you show us how to write integration tests efficently?
Thank you brother, all this content for free is amazing
This is best video ever on unit testing. thank you so much Amichai 👏
Nice video. This is the sort of pattern I use especially when it comes to naming and creating common fixture data that doesn't clutter the test. However, when it comes to creating the Sections and the items I would use a delegate that returns a list rather than an instance of a list. So for example where in the final test there were a set of sections that each referenced the same list of items, we can provide a different list of items to each section.
Great video! Would love to see a tutorial of this in action doing TDD!
Thank you, Amichai. Looks comprehensive and great!💪
Thanks Amichai, for all your vidéos, You were going to make another video showing how to handle invariants and domain errors. I'm really looking forward to that one. Thanks.
I have been dreaming this so long. Thanks!
thanks Amichai, great
Great video, extremely well explained and showcased!
I'm quite surprised I've been working almost exactly the same way with my testing infrastructure (although your example is a bit more graceful than my actual projects).
The one thing that gave me a lightbulb moment was splitting the constants into partial classes in separate files, genius.
I wish I had partial classes in my current Java project...
Good job! Waiting for Integration test
We have arrived at a similar state with our tests. I tend however to move the constants to inside a static object/model if it's common or variable inside the test method.
If I need to assert on one of the properties of the model that's when I tend to have that defined as a method level constant (defined at the top of the method...screaming at me, in CAPITALS).
Great video
Indeed testing is alot of effort
yeah, I was waiting for this!
Amazing content, it seems like lots of ceremony though
How did you manage to debug the Unit-test project. I am not able to see how you attached the projects to the debugger.
How can you debug the unittest inside of vscode? I assume, you use the "debug test" from Dotnet Test Explorer Extension. But it did not work for me. Would be great, if you can elaborate more on that. :) Great video, by the way.
Awesome video brother! Really learning so many methodologies from you.
And one thing, the sound seems a bit lower. Please try to increase in next videos. Wish you best of luck!
I'll double-check next time, thanks!
Why not use fixture or other to generate data instead of creating static classes by hand?
Hey Amichai, will you continue this series?
Great video! Thank you! Maybe not exactly on the topic of the video, but I have a problem that I don't know how to solve yet using the existing architecture. Namely: I add a function to the repository to search for an entity by identifier, I pass an identifier object to the function as a parameter (HostId hostId hostId as an example), inside the function I use FindAsync(hostId). When executed, the exception "System.ArgumentException: The key value at position 0 of the call to 'DbSet.Find' was of type 'HostId', which does not match the property type of 'AggregateRootId'" occurs. Considering that AggregateRootId is an abstract class, how to solve this problem? I would be grateful for a hint.
Thank you for the great and informative series. I followed all parts and have a question regarding UOW. In a scenario where changes are made to two different aggregates/entities and want to apply it in the database, how would you handle it as one transaction?
I don't like your test naming convention for a few reasons.
Like you said once SUT is renamed you need to rename tests. Sooner or later, you will forget to do it. Reviewers of your PR will see change only in SUT source file and will need to check if there are any tests to remind you to rename them. They will most likely not want to spend time searching for tests so they will not do it and it will slip in in every PR. Some of your tests will have wrong names after some time. I don't understand why the name of class containing those tests is not enough? When you see the test failing you see that this test is in SUTTests class so you know exactly what failed.
Should - this is so common and I don't like it. What does it mean "Should"? Should, but doesn't have to? No, it must do what it says. When you have test with "Should" in it and it fails is it good or bad? Why bad? The test says it only "should". Plus, it adds to test name length so often they don't fit on screen especially if you split screen to see both SUT and its tests. I use XUnit which uses [Fact] attribute instead of NUnit's [Test]. I like the name "Fact". My tests, when passing state facts about the system. If they fail, this means that Fact is not true. When Test with Should fails it doesn't mean anything to me. So, if I said I state facts about system your test which verifies Handling create menu command would be - ValidRequest_CreatesAndReturnsMenu. Others could be: InvalidRequest_IsRejected. Short and to the point. When you see list of tests passed you can even export them and show business people what has been implemented, they will understand it.
what is the name of this to you use to make arrows during the record?
Thanks for the very detailed and informative video. Appreciate it a lot. How about using AutoFixture to generate the models for us because in most cases we do not care about the contents of the objects generated using the Utility Classes?
THANK YOU SIR
Great video, thank you. Question: what tool do you use to annotate the screen in "real time"?
Thanks! I use presentify on MacOS (this video), and ZoomIt on Windows
Thank you for letting me know. ZoomIt seems to be free, but I guess pressentify isn't, right?
Right
Good overview. I'd personally use fluent interface if possible instead of default params for creating custom test objects. Like: CreateCommand().WithSections(sections).
I used to love the builder pattern, but nowadays, I almost always default to optional parameters instead - same behavior, less code
@Amichai Mantinband, I guess you also would hurt discoverability (using builder pattern). I have seen test methods with A LOT of default params or params that are unclear. I guess it's the matter of composition and code review. You have to hold your test code to the same code quality standards as regular code.
Same. That’s why I think it’s important to limit the parameters to constructing the top level object, otherwise it’s a slippery slope. Regarding code review, I have yet to see big projects where tests are reviewed thoroughly. At some point, the threshold becomes lower than production code
A function named CreateCommandWithSections(sections) is just as descriptive as the builder class function but without the effort. In addition i can easily change the name (i mean the first part) without affecting other functions.
@@peterfranzmayr3962 Yeah, but naming is one of the hardest parts of programming (imho), especially when you have a lot of different params. Personally, I have troubles with overly descriptive names (and names that expose implementation details). I would probably use data generators in case of complex objects to improve maintainability and readability. But than again having a standard naming convention for your tests and tests helpers improves the situation quite a bit.
my lazy brain goes to wonder if there is a way to make a source generator or chat gpt to write all this test code lol
anyway this video is very useful, i was sort of ending up going a similar direction recently even tho less rigorous and more messy.
I might not know to write this stuff correctly, but i truly feel bothered when i write messy tests or code in general to just make it "work".
20:46 why did you make the constants class partial?
Hey Ghevi. Partial allows splitting a class’s implementation across files. This way we can have two files that have the constants static class (Constants.Menu and Constants.Host in our case)
@@amantinband have one more question, when trying the convention for naming tests...i understand i should consider my context but in ur opinion...
If i have a class called MyService that have many methods instead of mediatr handlers for each operations, should i name a test like "MyService_WhenCreatingProductWithNewId_ShouldReturnSomething" or "CreateProduct_WhenNewId_ShouldReturnSomething"?
It seems like in the first case the middle part gets very long.
Do u have any video on cache implementation?
Hey Amichai. What is your presentation tool called? The one you use to draw on the screen. I have found ZoomIt, which looks like it can do much of the same, but the styling is different, so you are using something different :)
Looks like he is using ScreenBrush, it is macos only I believe
Great video, did you consider AutoFixture to generate random data in each test?
Thanks! I think AutoFixture is a great way for creating mock objects for testing, but I don’t have experience working with it in large projects to confidently suggest it as a go to solution
Autofixture and bogus together ftw.
Hello Amichai! Hope you're doing well. This isn't related to unit testing, but can you please share your key binding of vs code. That'll very much appreciated.
Looks like he is using the VsVim extension to get Vim mode in VsCode
Very helpful template!
Can you continue the project by adding code coverage and github actions ?
You mean how to set up a GitHub action that checks code coverage?
@@amantinband yes please.
Finally, thank you the effort you put in for this amazing content