Friday, November 8, 2013

To learn TDD takes time.  It takes time to learn how to do it, but also to do it in the way that is efficient as possible.  So that shouldn't stop you from doing TDD.  That includes using and learning tools like ReSharper and keyboard shortcuts to make generation of production code fast.  VERY fast.

Again when I talk "production code" in the context of TDD, that is code you create AFTER you code the lines in your Unit Test of things that don't exist yet.  "Things that don't exist" could be anything from the core class you need, new methods in that core class, or properties that you want to populate as part of your TDD Unit Test.

So I wanted to find the fastest way to generate the classes, methods, whatever from my Unit Test...that is generate the stubs that do not yet exist as fast as possible.

After researching a bit, I found that there are 2 ReSharper keyboard shortcuts that you'll need and that's literally it!  Those are the following:
  • Alt + Enter
  • F6

At first I found the Efficient Navigation when doing TDD/BDD with ReSharper video from JetBrains but it's very old.  It talks about TDD with R# but that's ReSharper 5!  Apparently they have not updated their videos in 10 years or so.  While most of this is still valid, I found a better option, F6 for the moving of the cla

Anyway, I found it, was just what I was looking for.

Later, after applying Alt + Enter and Ctrl + Shift + R (refactor menu), I found yet a quicker way which was just F6 for the refactor menu.


So lets take a look at how you would apply this in Test Driven Development because that will also show and explain how ReSharper will help you in this process once you get the keyboard shortcuts down by habit just from routine practice.

Using the Red, then make Green, then Refactoring principals of TDD, here's what that looks like and how I used the shortcuts to perform a typical creation of a unit test against a use case and necessary classes related to one particular unit test:

1) Always Start with a Use Case (Story) to drive what tests you need

Eventually this will just come naturally through time as habit, but intil then, be sure to keep reminding yourself and try not to forget that TDD tests themselves are a form of living documentation.  When a team looks at TDD tests they should feel confident that those who created those tests did it with Use Cases driving them...and that they are not some abritrary guesses.  

So you should feel good that with TDD you have guidance.  You don't just blindly start off guessing what you may need for "possible" requirements in the future like many devs have done without TDD and who create much more code than is needed in a lot of cases (wasted time).  Instead, you don't need to guess where to start.  TDD tests are and should be driven by Use Cases (Stories)

Your test classes should therefore act as documentation itself.  Meaning anyone should be able to go into a test class and it can be viewed as a footprint for business requirements.  Tests in your class were written for business requirements so the intent and reasons why those tests are there should read like documentation.  Meaning your test names should be clear on what they are testing.  And each unit test has a direct relation to one or more Use Cases that drove the creation of these tests.  So these tests are the business requirements literally from use cases.

Also all your tests serve as a form of documentation to other devs.  If you want to know how to call something, look at the tests!  They show you exactly how one could call a certain method in many ways as if you're coding via TDD you'll have a lot of tests per method usually.

And as a result, you are driving your team to create LEAN code.  Since Unit Tests are driven by Stories and you are to make sure unit tests are as small as possible each, some seemingly ridiculous to newbies, they are not too small.  Because by creating small tests, you are thinking about the parts you need to satisfy those business requirements.  And a unit test by definition means you test ONE very small thing.  That could literally be testing to make sure a method does not return a null instance or doesn't return an empty string.  All these kinds of little tests are things that could go wrong while you code methods and classes for the use case.

And remember you aren't going to know what tests you need instantly even if you have a use case right in front of you.  One of the good things about TDD is that it forces you to think about what you need for a use case.  So you're only creating the code you need, at its leanest.  Just enough code to pass the tests that make sense to support the business use case.


So lets start with a hypothetical Use Case:



    Figure 1 - a user story in Jira

So this user story has a couple tasks (we'll only talk about the first two):
  • create an initial Web Service class stub
  • create some method stubs we think we'll need to support facilitating calls to various payment processors
  • Create some utility methods for parsing proprietary XML, sending API requests, creating request tokens, etc.
  • ....
So this is a business requirement.   Tests we create should make sure our code is satisfying that business requirement.

The first two tasks are dependent on each other so our tests will naturally involve the two anyway (you need a service and you need methods after that)
  1. We'll create a new PaymentServiceTests.cs class to hold our unit tests for this service
  2. We'll start thinking about what this service should do/provide, if it needs a constructor and some initially wiring up on a constructor for any reason, and how it might start out. This is the part of TDD that forces you to think about what you need now and at its leanest.  This is the best way to discover what you need based on the Use Case
  3. As we go, we'll naturally start thinking about and as a result discover how we'll implement the production code in these methods and class to make our tests go green


Now Lets start on the Tests to Support these requirements

First lets create the service Interface.  Note we could also be creating a class but we'll do it by an interface for now since that's normally where I start when I create a web service because I start thinking about what methods we'll need for the service and there are several reasons I'm using an interface here that I won't go into in this post

To go about this, lets start creating tests in our PaymentServiceTests.cs class:

Usually most TDD tests start out with checking the absolute very basics.  We're talking about stuff like making sure you even have an instance of the service object itself.  When you do TDD again nothing is too small to test.  It may seem absurd to test something like a valid object but you'd be surprised that these things can fail at any time in the future if people start changing the implementation of the class, initialize it wrong, or whatever...

So the first test simply checks that we have a valid instance (object) of the service we want to use, in this case our PaymentService.

    Figure 2 - our first TDD based unit test for our new PaymentService and using 
    Roy Osherove's convention of method naming as well as comment guiding parts of the test     code inside (Arrange, Act, Assert)

Because I want to base my service off an interface, we know we'll need an Interface AND a service class that implements that interface.  We also know we'll need methods in both places right?  A method stub in the interface and method implementation in the Service class. 

(Some may argue we don't need an interface here but I can argue some reasons that we benefit from having one here.  I'm not going to debate that now, so just follow along...the point is to get a test of how to start TDD which again I'm learning as well but figuring out more and more every day at work.  We do not have a certified TDD guru on board so we're all in the same boat, learning and trying to do TDD right.)

The Service Interface will house those methods that we want to expose publicly to the client/consumer of this Web Service.  In TDD you want to only unit test public members for several reasons that I will not get into in this particular blog post.

The Service Interface is also where we will house and define the WCF or other specific attributes that the methods will rely on.  We are adding attributes in this case because we are creating a RESTful WCF service.

So if you look at the test above, I thought to myself ok, at the very least, we need a valid service instance before all else.  This is typical in the TDD world.

One interesting thing to note.  For now, I like the approach of creating the assertion first.  By doing so it makes me think about what the test expects as an outcome to support the use case  

Then after creating the assert, going backwards to create the non-existing class or methods and code as if they are available but we know they are not that the assert is using.  This is called Failing First (going Red first).  Meaning you code as if those interfaces and classes already exist but we know they don't.  That's ok and what you want to be doing, it will feel awkward at first but you will see the beauty of this later as you get more practice with TDD and start seeing the light as to why this is the first thing you do if you are coding via TDD principals.  

Again, don't be tempted to go create theses files (class and interface).  When you do TDD, You want to generate the actual class and interface files from your test.  And this is where ReSharper will really automate that and help you do it quickly.

So first I create the assert:

    Figure 3 - initial assert to support this Unit Test.  This unit test will be one of many to                               come as we create more tests support our Use Case
    
   This asserts says I expect that I always have service object instance to work with at the very     least.  We need that do do anything period if anyone wants to start using our service.

Next, lets start creating production code (implementing the actual method, class, interface, etc)  to support the assert:

    We needed to create the variable called  serviceInstance.  To do so, that means we'll 
    need both a ServiceInterface and related Service class that implements that interface.  
    Again the interface just abstracts out WCF specific stuff and also defines the public 
    contract which is very common when creating WCF services.  We could define a public 
    contract for WCF with just a plain class, but I have my reasons for 
    doing it this way, there are many benefits in this particular case.

    So I just started right in creating the variable as if everything exists.

    And what you end up with is red invalid service and interface references.


Next step is to create the production code.  Meaning we need to start making this test green.  Putting another way, we need to make this test REAL.

Now here's where ReSharper is very handy.  There are a couple things we want to do to accomplish creating our interface and test class here:


  • We need an IPaymentService.cs interface and a PaymentService.svc.cs class
  • We need to be able to create new files for these
  • We need to be able to decide where we want to create those files as we don't want them located in our Test itself
  • We want to be able to reference the namespeces for those new classes in our test project so it knows about them (in other words we'll need using statements for these at the top to recognize they exist)
Now the nice thing about ReSharper is it helps us do this very easily and quickly which othewise would take minutes.  

Here's what ReSharper can do for us in response to the steps we'll need to take in the list above:
  • We'll need only 2 ReSharper based keyboard shortcuts already built into ReSharper to assist us
  • ReSharper will automatically inject the using statment in our Test class after all is said and done (you don't even need to think about it, nice right?)
  • Optional benefit:  I like using the ReSharper test runner, which to me is more powerful and easy to use rather than MSTest runner or NUnit's crappy test runner

Now here's how we'll finish the rest efficiently with ReSharper:

First lets create the Interface class stub and file:

Place your cursor at the beginning or end of IPaymentService and press Alt + Enter.  Nice right?!!!  you immediatley get an option instantly to create a new interface:


This will create the interface stub in your test class:


    That was Jimmy Johns-like freaky fast right?  Huge time savings right there, no excuse to 
    say TDD is slow (well after you practice and get this down pat that is)

Ok and now lets create the PaymentService class stub, same deal, Alt+Enter:





Nice right?!?!  but wait, look again.  ReSharper also helped us out by the fact that it knew the context.  It knew not only to create that class but to automatically implement
IPaymentService based the context of the line of code where you told it to generate that 
class from.  Awesome right?  You should be saying damn straight...because this is the kind 
of stuff Visual Studio doesn't do for you...stuff like this that saves you so much time.  This 
goes beyond basic generation, this is smart generation at the same time saving you a few 
more steps.  ReSharper is smart people.

Finally you say to yourself, well that's stupid, we don't want this here, these should reside in our WCF Service project.  How can I move these and also create a new file at the same time?

Again ReSharper to the rescue.  All you need is F6 on your keyboard.

All you need to do is place your cursor at the beginning or end of what you want to move, this being the PaymentService class and choose "Move to Folder":



   Then this brings up a quick dialog to allow you to finish that move and also specify what 
   project and where in that project you want to move this and also create a file for this:



    Ok great.  However it defaulted to the location being our current test class.  Lets change         that.  Backspace a little and ReSharper automatically adjusts the list to show you more and     more up the tree of projects and folders in your solution:


    Ok cool, but I want to go all the way back to the root of my solution and choose a different 
    project.  So instead replace it and type in the name of your project and you'll get a broader     list up the stack to choose from.  Then just arrow down to which one you want:



   Once you select the right project, then add a slash "\"  at the end and it'll start showing 
   you the folders within that project to choose from:

    OPTIONAL: Also notice you could use this icon at the top right for another way to visualize     the solution stack as well:
    
Anyway, I've told it where to generate the class and now it just did.  It created the .cs files and placed them where I told it.  

I repeated the same set of steps we just did to move the Interface as well.

Now our Test class is clean again and just contain tests:



And look!  And since I use the ReSharper Test runner, it automatically detected what Unit Test Framework is on, so it added a nice little icon to the right that we can click on to run the test:



And results shown in the ReSharper Test Runner shows our test now runs green!  We've just created just enough production code to make this particular test past.  So we've just created what we need and only what we needed for that test.  We're creating LEAN code and that's just one of the benefits of doing TDD and following its principals in order.

Actually I had to change it up in the end to make it go green, just an example of how TDD makes you think about stuff and make it work



Disclaimer:  no I have not added a mocking framework in this example.  This was just to illustrate basic TDD motions.  Yes, you should be mocking the service.

Tools used in this example:
  • VS 2012
  • ReSharper 8.0.2
  • My Brain and thinking based on the Use Case


Till next time, work hard and learn TDD ok?  Stop Making Excuses. It's worth the work now, you'll benefit beyond your wildest dreams later once you get this stuff down and it becomes habit / no brainer later on.

0 comments:

Post a Comment