Posted on 6/30/2009 10:25:21 PM by Justin Etheredge
The title of this post actually isn’t a question that I get asked very often. I think the reason that I don’t get asked this very often is because of two different reasons. The first reason is that people (and programmers especially) are embarrassed to admit when they don’t know something that they feel like they should know. Secondly, many developers out there think they know exactly what you are talking about when someone says “unit testing”.
Of those developers who think they know what unit testing actually means, I would be willing to bet that only about 10% really do. You see, the problem is that when most developers are asked to define unit testing they will say something like “tests that are run against a project using a unit testing framework”. That is kinda right… well… not really. It isn’t really right at all. In fact, calling frameworks like NUnit, xUnit, MbUnit, MSTest, etc… “unit testing frameworks” is inaccurate. They are instead “automated testing frameworks” which can be used to execute any number of kinds of tests. One of these kinds of tests just happens to be unit tests. There are also integration tests, performance tests, load tests, etc…
Okay, so what exactly is a unit test? It is a test which verifies a “unit”, or the smallest piece of an application which is able to be tested. Ideally, when writing a unit test in C#, you’d want to isolate an individual class and write tests against only its functionality. The developers doesn’t want to pull in external dependencies and doesn’t want to access external processes or services. Unit testing is all about testing small pieces in isolation.
So why would we want to write tests like this? Many reasons…
They are fast. Have you ever worked in a system that mixes unit tests and integration tests? How long did they take to run? I have worked in a handful of systems that weren’t very large and still had suites of tests that took 10+ minutes to run. How often do you think that developers are going to run these? Not very often at all, and being able to run your unit tests quickly and easily is very important to having quick feedback while developing. Forcing developers to sit through minutes of tests will guarantee that your tests will rarely get run. A broken test found after a developer has moved on to another task will take them substantially longer to fix than one they find right away.
They are reliable. If all of your tests only operate in memory and don’t touch the disk, go across the network, query from a database, etc… then we can be assured that these tests will, for the most part, run smoothly. You won’t have to deal with numerous different settings, connection strings, external processes, etc… Tests which don’t run reliably, or can break frequently will merely frustrate developers and keep them from running them. Remember, tests are useless if they aren’t run.
They are accurate. By this I mean that since they only test very small pieces of functionality it is often quite easy to tell what has broken when the test fails. In a test that crosses a wide swatch of the application, it can often be much harder to figure out where the breakage actually occurred. Having pinpoint tests makes sure that you can find your regressions quickly.
They are flexible. Applications are full of unexpected events. But if they are unexpected, then how can we make them happen in a reliable manner? How can we force a database to throw an exception during a query? Well, in many cases we probably can’t. These are the cases where unit tests allow us to fake dependencies in order to raise exceptions or to cause situations that would otherwise not likely come up during normal execution. Sometimes we don’t care about these events, but sometimes we do, and when we do we need to have some way to force them so that we know how our application is going to respond.
Does this mean that if we are writing unit tests then we don’t need to write integration tests? Of course not! What it does mean is that integration tests need to be separated out from your unit tests so that they can be run in a single environment away from the developer’s desktop. Ideally this would occur on the build server. This way the developer doesn’t have to worry about long running or brittle tests. If all of the unit tests passed, but the integration tests didn’t, then the developers can take the time to figure out why these tests are executing correctly.
This is all great, why isn’t everyone writing unit tests? Well, unfortunately unit tests aren’t a cure-all. Many people complain that writing unit tests is a burden that they just don’t have time for. In fact, I came across a post today that said just that. I think that this is a myth that is generally driven by poorly designed software. Now I know that this is a generalization that is made quite frequently, and one that is even harder to back up, but I really think that this is the truth.
In an ideal system you would be writing unit tests as you are writing your classes, and then you would writing your integration tests as you integrate them in with the rest of the system. In some larger systems, units tests can be unavoidable. Often different pieces of the system are being written before their dependencies have even been created. Or they are created by separate teams that are simply developing against an interface. In these cases the unit tests would be written long before integration tests are even possible.
Another complaint that I often see is people complaining about brittle unit tests because they are using facilities such as MSTest’s accessors which allow developers to directly tests private methods (which I personally think is very bad practice, but that is another rant). Either that or they haven’t factored out methods in classes enough and they are trying to test way too much. Getting used to testing public interfaces of classes and not relying on internal implementations will go a long way toward having less brittle tests.
Automated testing is an indispensible tool, and unit testing is just one of the tasks that you should be performing with it. Testing your application from top to bottom is very important, but making sure that the individual pieces of your application work in isolation is often the only way to reliably and quickly exercise a lot of the code in your application.
Next time you are writing an application, give it a shot. Split out your unit tests and integration tests so that they can be easily run separately. You may not notice any advantage at first, but once your suite of tests grows large you’ll find that you are able to write new code much faster because you have almost instant feedback on regressions in your tests.
Posted on 6/29/2009 12:09:30 AM by Justin Etheredge
On Twitter the other day I had a short conversation (well, it wasn’t really a conversation since it was only about 4 tweets) with Jeff Cohen who is the author of Rails for .NET Developers. Which is, by the way, an excellent book and highly recommended. The conversation that we had was about the dynamic keyword for C# and its implications for C# developers.
Jeff expressed some concern for the keyword and its potential abuse among C# developers. His point was that if C# developers want to write dynamic code, then you need to use a language like IronRuby or IronPython, not try to inject dynamic code inside of C#. Thankfully, for the most part, I agree with him! However, I do think the dynamic keyword is a great thing because, most importantly, it allows interop between static and dynamic languages to be super easy. Without dynamic, we would have to use all kinds of nasty APIs to use an IronRuby object inside of C#. With dynamic I’ll be able to write code that looks like this:
dynamic irObject = GetIronRubyClass();
string resultValue = irObject.CallSomeMethod();
Which is pretty awesome, but how would that possibly work in a statically typed language? The short answer is that it wouldn’t. In order to accomplish this magic, whenever C# sees the dynamic keyword it generates IL that performs late bound calls against the object. Which means that in order to interact with a dynamic language, C# essentially becomes a dynamic language itself. So does that mean that C# is a dynamic language now?
But I think a more interesting question is, do we need to draw a line in the sand between static and dynamic? It seems that as time passes the lines between static/dynamic, OO/functional are being blurred more and more every day. When C# 4.0 comes out we will have an object oriented, statically typed language that has enough functional features in it to almost be considered a functional language, and now a bit of dynamicness thrown in to give us a leg up on a few special cases where making dynamic calls could really make our code more simple.
Now before people get out there pitchforks, yes I know that C# is still missing several fundamental aspects of a functional programming language such as pattern matching, easy immutability, partial application (not at the language level), etc… but that really isn’t my point. My point is that C# is starting to pull in many paradigms in order to make developers lives easier without going full steam in an entirely different direction.
Another great example of a language like this is Scala. Scala, just like C#, is a statically typed, object oriented language. The main difference is that Scala has gone much further in the functional programming direction than C# has. Scala does have support for easy immutability and even encourages the developer to program in this way. It also has language support for partial application and it has robust pattern matching. However, Scala has not yet gone in the dynamic direction that C# 4.0 has. In Scala, the only support for dynamic typing is structural types, which allow you to specify a type by its shape. Sort of like specifying an anonymous interface.
So, are we pulling what we need into our languages so that we can right software easier and faster? Or are we creating kitchen sink languages that are so bloated it has become difficult for people to learn and use them effectively?
Personally, I think that general purpose languages can only benefit from learning a few tricks from other programming paradigms. But I also don’t think that we will ever get to the point where we have one programming language to accomplish everything. Nor do I think that is even desirable. I love the fact that I can write in a language on a day to day basis that allows me to pull in a bit of lazy evaluation, or some other functional goodness, but then I also see that it would be very difficult to take the dynamicness or the functionalness much further in C# without sacrificing the core of what the language is. It is a very narrow line to to walk.
I for one look forward to a future where languages borrow from each other, but keep enough of their individuality in order to make them useful. Always keep in mind that a jack of all trades is an ace of none.
Posted on 6/18/2009 10:25:47 PM by Justin Etheredge
I gave a presentation tonight at the Charlottesville .NET user group on building testable applications. The presentation was focused around the Single Responsibility Principle and the Dependency Inversion Principle. We started off with a very simple app that we slowly factored out dependencies into their own class, and then implemented a dependency injection framework (Ninject) in order to resolve our dependencies. Then we implemented a mocking framework (Moq) in order to mock our dependencies to use in testing. The application was built in a series of steps, and by popular demand I have attached to this post the final result of the application refactoring! (Popular demand, ha!)
Anyways, unlike my previous experience, this talk went really really well and I got quite a bit of good feedback from the talk. I can’t wait to give the talk again, I really wish that I had submitted it to DevLink instead of one of the other talks that I am giving.
I wanted to thank everyone who came out to see the talk, I really enjoyed giving it! I can’t wait to give it at the Richmond .NET User Group in October!
Oh, and the presentation was only a few slides with just pictures. I didn’t attach it because it really makes no sense out of context.
Source for the test project updated with start and finish project
Posted on 6/15/2009 9:43:09 PM by Justin Etheredge
For loops have been our friend for so many years. I have fond memories of looping through huge lists of items imperatively bobbing and weaving to construct my final masterpiece!
for (int i = 0; i < items.Length; i++)
{
if (items[i].SomeValue == "Value I'm Looking For!")
{
result.Add(items[i]);
}
}
Look at that beauty. I am looping through a list of items, filtering them on some value, and then BAM! I get a result list with the values in it. Magic I tell you, magic. And then foreach loops came along and I realized how ridiculously ugly it was. Just check this out:
foreach (SomeDummyClass item in items)
{
if (item.SomeValue == "Value I'm Looking For!")
{
result.Add(item);
}
}
Mmmmm. Beauty, simplicity, less room for error. But I still have to do a lot of declaring and looping and things. Ugh. So then they gave me the magical yield statement, and when used with a method, I could do this:
private static IEnumerable<SomeDummyClass> GetItems(SomeDummyClass[] items)
{
foreach (SomeDummyClass item in items)
{
if (item.SomeValue == "Value I'm Looking For!")
{
yield return item;
}
}
}
Nice. Still a lot of looping, but now I don't have to declare that stupid result list. And, if the result is never used, nothing even runs! Lazy evaluation rocks your face people! This still just feels gross though. Why am I holding the compilers hand so much? I just need to say "hello computer, give me crap in this list where SomeValue = some crap I'm looking for". Lo and behold Anders Hejlsberg and his team came down from on high and delivered Linq to us. Now I say:
var result = items.Where(i => i.SomeValue == "Value I'm Looking For!");
And the compiler figures it all out for me. Better yet I still get lazy evaluation and I get my list filtered. Best of both worlds! And since I am not telling the compiler exactly what to do, then in the future (with .NET 4.0) when my list grows really really large, all I have to do is say:
var result = items.AsParallel().Where(i => i.SomeValue == "Value I'm Looking For!");
And suddenly my list is being filtered by all of the processors on the box! This is possible because at each iteration we began to tell the computer less and less how to perform the individual operations needed in order to get our result, and instead we are now more closely telling the computer the action to take, not the specifics of how to perform the action. This lets the computer best decide how to execute our action, and in the case of Parallel Linq, we are now able to tell the framework that we want our task executed in parallel. (In case you are wondering, there are a few reasons why it can't just run it as parallel by default)
As you can see, we really are moving more and more down the road of declarative development. Over time we will see more "what" and less "how" in our day to day programming adventures. And that, my friends, is life after loops.
Posted on 6/11/2009 11:01:20 PM by Justin Etheredge
In my last post about the most powerful developer tool ever made I had a person leave a comment that said this:
I could not agree with you more. Google is your friend! I actually landed my current job because of Google. In my interview I was asked the question, "How would you rate your skills in C#, 1-5?" I replied "4", even though I had never seen a line of C# code. He asked me why I rated myself a 4 and I told him, "Programming is a skill, once you know how, everything else is just syntax and I can just Google the rest."
This comment had me thinking for a few minutes. Sure, knowledge of your programming language and environment are very important, but overall, is programming a generic skill that easily translates between platforms, languages, and toolsets? My first response was “kinda”, object oriented programming is a generic skill. If you know how to write good object oriented software, then you are likely to be able to easily translate that skill into another, demonstrably similar, language.
A Rose By Any Other Name
For example, if I were to be an awesome Java developer (which I am not) who can write great OO code, then I would very likely be able to turn around and write great C# code. I’d have to do quite a bit of searching, and trial and error to find out the particular way to connect to a database, search a string, write to a file, etc… but over the course of a few weeks I could become extremely productive in the alternative platform. As Thoreau said:
Every artizan learns positively something by his trade. Each craft is familiar with a few simple well-known well established facts-not requiring any genius to discover but mere use and familiarity. You may go by the man at his work in the street every day of your life.- And though he is there before you carrying into practice certain essential information-you shall never be the wiser.
There are simple well-known facts at play here, but these are both incredibly similar platforms. They practically share the same syntax, both are object oriented, they are both garbage collected, etc… The similarities go on and on. But if you came from a language which wasn’t so similar, then would we be in the same situation? Is it just syntax at that point? Absolutely not.
There are really two different ways that languages differ. First is in syntax, second is in paradigm. In terms of syntax and paradigm C# and Java are basically the same. Even C# and C++ would be considered very similar in terms of syntax and paradigm, but if a C++ programmer came into C# they could probably get around but would likely perform tasks in sub-optimal ways until they learned the ropes. Obviously the reverse is also true, but to a more extreme degree.
If you were to drop a C# developer into the world of Scala they would feel comfortable with the syntax but the shift to a more functionally oriented language would probably give them trouble for quite a while until they learned the ropes. Going further and putting the developer into a functional language like F# would push them even further, and without proper training and exploration they would probably be solving problems in entirely backwards ways because they are still thinking in their old paradigm. In F# though we still have the object oriented tools available to us, and therefore the C# developer would likely be able to at least fumble their way through a problem. However, if you took a C# developer and dropped them into the world of Haskell they would be a fish out of water. The software would be as foreign to them as a brain would be to a cardiac surgeon.
Making The Switch
Does this mean that the comment on my previous blog post wasn’t true? Absolutely not. In fact, he is almost certainly correct in the vast majority of cases. Object oriented programming dominates the development industry right now and moving between C++, C#, Java, PHP, Delphi, VB.NET, etc… are all extremely similar. Once you’ve learned how to develop in one, you can be fairly comfortable in the others in a matter of days or weeks. It isn’t even that far of a jump to go into object oriented dynamic languages like Ruby, Python, or Grooby. You just have to forget everything you were taught about the importance of type safety! If you are looking for a tutorial, look no further!
The bigger jump is when you look at the next generation of languages coming down the pipe and you start to think about the paradigm shift that would accompany languages like F#, Scala, Erlang, Clojure, etc… These languages, should any of them become mainstream will represent a shift in the fundamental way in which many programmers develop. In fact, many of us are already starting to make this shift if you are working in a OO language such as C# that is slowly starting to push more and more functional concepts into it.
Don’t Forget About the Libraries
Libraries can’t be discounted completely though. I wrote it off as earlier in this post as simply googling for a snippet of code to write to a file or parse a string, but the reality is that libraries that come with languages drarwf the languages themselves by many times. Over time a developer becomes familiar with his/her platform of choice and their productivity can rise substantially. The real question is how long does it take to get to this point? I for one subscribe to the idea that libraries are like spoken languages. The English language may have tens of thousands of words, but any individual usually only uses a few hundred in every day conversation. Those few hundred can take a different amount of time to learn, depending upon the person and the environment.
One thing is for sure though is that a developer writing C# in one shop and a developer writing C# in another shop can be exposed to two entirely different parts of the framework. A good example of this is that I went in for an interview once where the interviewer asked me to tell him how to connect to a database, fire off a query, and then read the results out. Well, I had just come off a two year project where we used a heavy abstraction on top of the data layer that mapped all of it into classes for us. I honestly couldn’t remember what the classes were called, and so I told him that. I explained that I hadn’t needed to use those classes in quite a while, and I made a few guesses about their names. Right now I am using them on a daily basis, and I wish I wasn’t, but I could name all of them off to you and probably even enumerate all of their methods! The point is that library experience is important, and learning tools is important, but they will only take you so far. The rest is up to you and your search engine.
Summary
So does out programming experience translate across languages and platforms? We better hope so, at least to some degree. Otherwise all of those pointy haired guys out there who are looking for the 20 year old guy with a year of experience in the tool du jour would be right! Ugh, that would be the most depressing thing ever. But I don’t think that is the case, I think that good developers span languages and platforms and they are the ones that are always searching for a better way to do something. They are always trying to be more efficient, more productive, and do more with less. They are always looking for a sharper tool. Are your tools getting dull?