JeremyBytes - TDD Basics with C#
HTML-код
- Опубликовано: 8 фев 2025
- Test-Driven Development (TDD) lets our code develop out of our tests. We do this by following the Red-Green-Refactor cycle. In this video, we look at the basics of TDD by implementing FizzBuzz in C#. We'll be using NUnit as our testing framework, but these principles work with whatever environment we choose.
Thank you for this video. I was doing a lot of research and reading to try and understand this methodology but everything I found either wasn't specific enough or didn't provide concrete examples.
I now feel like I understand TDD a lot better especially after seeing your example. I'm encouraged to try it in my own code.
Thanks again
You saved my day in 24min. Thank you so much.
Thanks for posting! NUnit's ability to run parameterized tests is a huge selling point over MsTest. Plus since you posted this there is now a test adapter for version 3.x.
There is MSTest V2 now that can do this
Excellent demo, ideal for those just starting out with TDD. Many thanks!
Excellent explanation by author!
Thank you sir for your lessons!
Excellent video Jeremy! I wanted to point out that Clean + Build is equivalent to Rebuild.
Wow, I had no idea. Thanks!
Thank you very much! really helped to grasp the concept quickly
This is an amazing explanation of TDD! Can't wait tot start with the latest plugins. Tomorrow, ofcourse.
Never found such a simple but great TDD sample
Thank you. about to start a job and they told me they do unit testing... great video!
Thank you! All of your videos and blog posts have been incredibly helpful!
you have given me a basic idea of TDD. Thank you very much.
Excellent video. Clear and complete, thanks!
Great Video. Well explained and at the right pace.
Fantastic explanation!!!
A great video even 6 years after posting.
thank you very much, very helpful and easy for understanding video. i got a project to make, using this technology. and you really helped me.
Very helpful video. Thank you
Overall not a bad introductory video.
It is very important to note that the Refactor step is not just for the code; it is also for the tests.
You started with a working program. This may be the case but if it is, then tests need to be added for the Main function in order to ensure that it is not affected by the new code.
Why click "Run All" when you could keep your hands on the keyboard? Ctrl+R, A (Live Unit Testing is also now an option in VS 2017.)
Using the variable names of "expected" (in arrange) and "actual" (in act) can make the tests more readable.
Being more explicit about the process, especially when refactoring tests, would be beneficial.
The "_When5_" test should have been renamed during the test refactoring.
Explicitly adding the additional values is unnecessary since you understand the logic and is counterproductive when it comes to Continuous Integration (CI) automated builds due to increased execution time.
Regarding live unit testing, this is only currently available in VS2017 Enterprise, but I've been using NCrunch for years and it does the same thing with a nicer interface and more functionality. It's not free, but if you don't already have Enterprise it's cheaper than Enterprise and even if you do it's worth a look. I've always found the Test Explorer built in to VS to be a real pain to use.
The Main function is usually not worth testing in a unit test, and if you did it would not be a _unit_ test because it can't be isolated. This should usually be covered by other kinds of integration tests that actually execute the assembly and verify its behaviour at a higher level. The important thing is usually that any code like this which is not covered by a unit test should be very simple e.g. create one class (or an object graph) and execute it. This also tends to be the case when a class has external dependencies like a REST client library that has no abstractions ( _cough_ microsoft _cough_ ) - it's often better to wrap the parts of that library which are being used, then use an abstraction of the wrapper to test that library is being used correctly by its caller. Again, in this case actual external requests should still be tested, but not in a unit test. This should only ever happen at the boundaries of the service.
One can also use dotnet watch with Core: docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-2.1
Really Great video to introduce to TDD, thank you
Very nice and simple explanation.
Jeremy, this is a FANTASTIC video and I truly appreciate it. I was reading The Art of Unit Testing but honestly, this is something better practiced than read about.
That said, I have a question for you... Test Driven Development is sort of a way of thinking.. You have to first think about the tests needed and then shape the code into the product as you did here... My question is, how do you get into that mindset? What are some great ways to reframe how you think about program design so that you are thinking test-first rather than "What does my function/program need to do?"
Or do you actually start by thinking that and then thinking about what tests need to come from that? Thats my biggest challenge. Thank you again!
I found Kent Beck's book "Test Driven Development by Example" to be very helpful in understanding how to approach TDD, including breaking down problems, determining the best place to start, and how to keep going.
Quite honestly, I'm not an avid TTDer. I mostly do what I call "Test Along Side" where I write code and tests at the same time (the code usually comes first). I tend to take Roy Osherove's approach: I don't care if you write tests first or not; I care that you have good tests.
TDD is very useful. I encourage people to try it out because it has some great features that help out a lot of people/teams. I tend do to a bit more design up front, but as Uncle Bob wrote earlier this year, you don't give up on design when you do TDD: blog.cleancoder.com/uncle-bob/2016/03/19/GivingUpOnTDD.html
Great, thank you! I must say that following along with your examples, I'm actually finding that I enjoy TDD and the benefits that come with it, such as security when refactoring or making changes to the code.
I think that's what a lot of developers and companies think tdd is :)
Perhaps my hasty video can help address the thinking aspect. ruclips.net/video/9Z7eyQHZMek/видео.html
Excellent Video.
Anyone following this and getting a problem where the tests are not being run, adding Microsoft.NET.Test.Sdk fixed it for me.
Very instructive video, thank you very much
great video. clear and concise. thanks so much.
Great one. We don't do TDD but simply do code as per requirement and then do test.
But this video explains how to create test as per requirement and do code later... correct if I am wrong.
Thinking to start implementing at earliest. Any book on TDD you like to suggest?
Yes, that is exactly correct. One of the advantages of using TDD is that you only build code that you need since the tests come from the specification.
The Art of Unit Testing by Roy Osherove.
There is a this thing invented by God named Gooogle.
great video! thank you :) love your explanations
Really great video, well explained and easy to follow. Nice job :)
Thank you Jeremy , very simple and to the point!
Perfect explanation!
Excellent video
Pretty good explanation!!
Thanks
As always, excellent tuition. Even if I could not having NUNIT working in my VS2017: my SampleTest at time 5:20 stayed blue instead of red :-(
I ran into a problem this week with NUnit and VS2017. The NUnit framework was v3.11.0 and the NUnit3TestAdapter was v3.12.0. The tests did not run in the test explorer. I downgraded the test adapter to v3.11.2, and it started working. I've had a couple issues like this with NUnit, and I might switch to a different framework if they keep happening.
Thanks very much for your answer. "Bonne continuation !" as we say in french...
Great video! Thanks in advanced!
TDD made easy, great example...
this video is a masterpiece of teaching. Thank you very much, Sir
Amazing tutorial! Great explanation. Your voice is very pleasant to listen to! May I ask why you prefer NUnit over the built in visual studio testing framework? Looking forward for more videos =)
+hl2mukkel I've used MSTest (the built-in testing framework) extensively. One big reason I liked it was that it was "always there" -- this was the days before NuGet. That's not much of an advantage any more.
The primary features I like from NUnit are parameterization (which is possible (but difficult) in MSTest) and exception testing. If you want details on these, take a look at the articles under "Why NUnit?" here: www.jeremybytes.com/Demos.aspx#UTMMF
Thanks, great pace, appreciate it
Thanks a lot Jeremy. It helped me a lot :)
Thanks for this video. I like how you go along in a very slow speed to explain the basics. I like to follow how you go about it and why, because I believe looking at other people's screens is the best way to improve ones own style. By the way, I would go about the refactoring in the end much slower. You kinda loose your "basics speed" there and do a lot at a time (I know, there's no real danger here, but ... ;) )
I've create a very similar type of videos in the past (see my channel). Would you be interested to join forces and do something on, say, Pair Programming?
Excellent video ! thx sir !
Over the years I have tried to come up with so many "reasons","arguments" against using TDD. But I have not been able to come up with any so far!
How woud you test the Program.cs in this case? More specifically how would you test the for loop?
Liked the video!
Thanks! Great video!
Great video! how would I go about testing non void return values? Keep up the good work!
The video shows testing non-void return values (FizzBuzzer.GetValue returns a string), so I'm assuming you're asking about testing methods with void return. In object-oriented programming, it is common to have methods that return void but change a property value on the object itself. In this case, the test would call the method, and then do the assertion against the expected property that is changed. If the method does not change a property on the object but instead does some type of work (such as saving a file), then things get more complex, and we often have to break things down for easier testing. For a more complex scenario, you can check out a conversation that I had with Steve Bishop (ruclips.net/video/Urh97eeG53g/видео.html) -- skip ahead 20 minutes to get to the coding bits :)
Thanks! Helped me a lot!!
Thank you so much.
Great video! +1 subscriber
Great video about TDD! Have you ever tried Typemock? the company i work for started using it and id like to hear what you think about it?
Great tutorial... but what tests the test... e.g. maybe you put the wrong values in the parameters on your tests and didn't notice.
Hi, very cool video! Do you know how to run this with Specflow? The Feature file doesn't support TDD??
Excellent!
great stuff!
Latest version of VS2017 also needs you to install Microsoft.NET.Test.Sdk - Just spent a looooong time working that out. Great video though!
You can also explicitly create a Unit Test project type.
Great tutorial! I am very new to unit testing, so I was wondering if you can help. I've got a website project, a class library and unit test project (nUnit). Everytime I run a very simple test, it takes ages, because I guess, it is building all the project. Is there any way of preventing this? Thanks.
This will depend on the test runner that you're using. Running tests will usually cause a "build" of the solution. In Visual Studio, this means that projects with changed files will be rebuilt (not the entire project). If you aren't changing the code, but only changing tests, the normal result is that the test project will be rebuilt, but any unchanged code will just use the existing dlls. If the tests themselves are running slowly, then you will want to check that you have good isolation, and you can usually run tests one at a time to find a problematic one.
Thanks you rock !!!!
Bro, you pc seems to be a rock.
What was your pc specs at the time?
thank you ;)
Does everyone use NUnit instead of the Microsoft testing framework?
I used MS Test successfully for many years. There are a few features in NUnit that makes me like it better. I've written a few articles about it: "Why NUnit?" www.jeremybytes.com/Demos.aspx#UTMMF
I use MSTest since it requires no additional dependencies and is integrated with Visual Studio and the MSBuild process. Data-Driven Tests provide the same ability as NUnit's Parameterized syntax.
Clever bastard! born to teach!!
Hi Jeremy, could you tell me which test framework is better, betweene MSTests and NUnit?
There are a number of features I like in NUnit that are not available in MSTest. Look at the "Why NUnit?" section of articles here: www.jeremybytes.com/Demos.aspx#UTMMF
Thank you very much Jeremy, and keep going with this good work.
The "Why NUnit" section does not highlight a reason to choose it over MSTest. Parameterized and More Parameterization is similar to Data-Driven Tests. MSTest is inherently integrated with Visual Studio. MSTest includes assertions for exceptions.
Of the four points there only one has value: parameterized tests. More parameterization options is covered with Data-Driven MSTest. MSTest is de facto integrated into Visual Studio. Testing for exceptions is inherent in MSTest.
Now with the latest version of MSTest and .NET Core, one can use [DataTestMethod] and multiple [DataRow(...)] attributes just as with NUnit and xUnit.
Test -> Windows -> Test Explorer
THANK YOUUUUUU
Don't understand why you are doing tests on 1 -20 when you only need to test 4 different scenarios. 1, 3, 5, 15 and also maybe throw a 4 in just in case ;)
How many items we test will vary based on the needs of the code. For most scenarios, I will make sure to test inflection points. For example, if 0 is an inflection point in the code, then I would want to test -1, 0, and 1. For FizzBuzz, I would say just testing "3" is insufficient for "Fizz" because our initial implementation code returned "Fizz" when equal to 3 (rather than divisible by 3). So I would want to test at least 3 and 6 to make sure the divisible by 3 is working properly. Granted, this example takes very small steps to show one way we can use TDD. Since FizzBuzz is a trivial task, I would normally take bigger steps such as going straight to "% 3 == 0" and skipping the step "== 3".
This is what I did:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FizzBuzz
{
class Program
{
static void Main(string[] args)
{
for (int i = 1; i
+Steve Kiley Hey Steve. There's nothing wrong with your code, and I would not call someone who gave that to me a "crap programmer". The point of this video is not the resulting FizzBuzz implementation -- FizzBuzz is designed to be extremely simple, after all. The point is to go through the process of TDD to see the steps involved. Then we can take the steps we learned with this simple problem and apply them to more complex problems.
-Jeremy
+Jeremy Clark Sorry, no implied criticism.
I have watched many of your videos, and they have always taught me something, and I like your presentation.
As regards TDD, I am just trying to learn the basics, as I am no longer in employment, and just looking out of interest really.
Anyway, thanks for responding.
Tedious Driven Development
You apparently missed the point of this video. Good job.
I worked on a massive product for a company that didn't like the idea of TDD because "it's extra work". They had major issues with old functions constantly breaking, and gremlins appearing seemingly out of nowhere when new features were added. Most of my 3 years there was spent debugging and fixing functions that "used to work". TDD would have prevented most of these issues, as the developer who added new features could of run all tests and realised they just broke 3 functions.
*[Personal opinions incoming!]*
I never used unit tests. Recently, I'm really convinced by a senior architect, hence I watch this video. I'm really convinced to try it later on. What I realize is my repeated
1. build
2. open browser
3. insert random input
4. click on execute
5. observe output
, these steps can be automated, and it's cool.
Most of my past projects are small, experimental thus the requirement is *unstable*, my boss will tell me this is not what I want anytime, so the extra work on writing tests, probably gets deleted or major architecture changes that will break all test structure. Boss will not care your effort on TDD, they want to see results. This is in-synchronization between SE and business existed for long time and mentioned in many books.
I watch Douglas Crockford's conferences recently and he thinks TDD is overrated. There are few things TDD can't capture and require manual testing. True, depending on the context, some stuffs are hard to capture with TDD, but most business rules and validations can be captured.
I personally believe TDD is not a silver bullet. Most peoples work in big companies, their requirement is *stable*, and they tend to do it for long run, then TDD is a proven methodology for testable and loosely coupled architecture. You can't just 'lets to it tomorrow since the code works' because you are forced to write tests first.
In general, we spend most of our time in debugging, not writing, thus more writes trade for lesser debugging will mostly worth it. Still, consider the scenarios I mentioned above, in SE we find the sweet point to consider which should, which shouldn't. Eg. even DRY principle is good, you shouldnt spend 5 hours to refactor a complex code that duplicate twice.
TDD is a ridiculous way of convincing yourself you are doing the right thing by typing mind blowingly obvious, superfluos , redundant and low utility value code enough time until you feel like doing something.
It may seem like that but to me that tells me you are missing the point. I don't have a ton of experience but to me it seems like its in the long term that this pays off. If you have ever worked with Legacy code and needed to do enhancements or refactoring you may understand or be able to empathize with why this is a good thing.