I just graduated with a degree in CS and I currently have a job as a Junior .NET Developer (C#, ASP.NET, and web forms). Back when I was still in university, the subject of unit testing did get covered but I never really saw the benefits of it. I understand what it's supposed to do, namely, determine whether or not a block of code is fit for use. However, i've never actually had to write a unit test before, nor did I ever feel the need to.

As I already mentioned, I'm usually developing with ASP.NET web forms, and recently I've been thinking of writing some unit tests. But I've got a few questions about this.

I've read that unit testing often happens through writing "mocks". While I understand this concept, I can't seem to figure out how I'm supposed to write mocks for websites that are completely dynamic, and where almost everything depends on data that comes from a database. For example: I use lot's of repeaters who have ItemDataBound events etc. (again depending on data that is "unknown"). 

So question number 1: Is writing unit tests for ASP.NET web forms something that is done often, and if it is: how do I resolve the "dynamic environment" issue?

When I'm developing I go through a lot of trial-and-error. That doesn't mean I don't know what I'm doing, but I mean that I usually write some code, hit Ctrl F5 and see what happens. While this approach does the job most of the time, sometimes I get the feeling that I'm being a little clueless (because of my little experience). I sometimes waste a lot of time like this as well.

So, question number 2: Would you guys advise me to start writing unit tests? I think it might help me in the actual implementation, but then again I feel like it might slow me down.

No.

The concept behind unit tests is based on a premise that has been known to be false since before unit testing was ever invented: the idea that tests can prove that your code is correct.

Having lots of tests that all pass proves one thing and one thing only: that you have lots of tests which all pass.  It does not prove that what the tests are testing matches the spec.  It does not prove that your code is free from errors that you never considered when you wrote the tests.  (And the things that you thought to test were the possible issues you were focusing on, so you're likely to have gotten them right anyway!)  And last but not least, it does not prove that the tests, which are code themselves, are free from bugs.  (Follow that last one to its logical conclusion and you end up with turtles all the way down.)

Djikstra trashed the concept of tests-as-proof-of-correctness way back in 1988, and what he wrote remains just as valid today:


  It is now two decades since it was pointed out that program testing
  may convincingly demonstrate the presence of bugs, but can never
  demonstrate their absence. After quoting this well-publicized remark
  devoutly, the software engineer returns to the order of the day and
  continues to refine his testing strategies, just like the alchemist of
  yore, who continued to refine his chrysocosmic purifications.


The other problem with unit testing is that it creates tight coupling between your code and the test suite.  When you change code, you'd expect some bugs to show up that would break some tests.  But if you're changing code because the requirements themselves have changed, you'll get a lot of failing tests, and you'll have to manually go over each one and decide whether or not the test is still valid.  (And it's also possible, though less common, that an existing test that should be invalid will still pass because you forgot to change something that needed to be changed.)

Unit testing is just the latest in a long line of development fads that promise to make it easier to write working code without actually being a good programmer.  None of them have ever managed to deliver on their promise, and neither does this one.  There is simply no shortcut for actually knowing how to write working code.

There are some reports of automated testing being genuinely useful in cases where stability and reliability are of paramount importance.  For example, the SQLite database project.  But what it takes to achieve their level of reliability is highly uneconomical for most projects: a test-to-actual-SQLite-code ratio of almost 1200:1.  Most projects can't afford that, and don't need it anyway.
