Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep your Source Close and your Unit Tests Closer

When I first started using unit tests I encountered two problems. First was being able to test private methods and fields and second falling behind on keeping unit tests up to date when rapid development was taking place. Consequently I adopted the approach below for my unit tests.

#if UNITTEST
using NUnit.Framework;
#endif

public class MyBlackMagic
{
   private int DoMagic()
   {
      return 1;
   }

   #if UNITTEST

   [TestFixture]
   public class MyBlackMagicUnitTest
   {
        [TestFixtureSetUp]
        public void Init()
        {
             log4net.Config.BasicConfigurator.Configure();
        }

        [Test]
        public void DoMagicTest()
        {
             Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
             Assert.IsTrue(DoMagic() == 1, "You are not a real magician!");
         }
     }

     #endif
 }

I find that approach overcomes my two problems and it's a flick of a pre-compiler switch to make sure all the unit tests compile.

My problem now is that I am moving to a new project where the talk is of using seperate assemblies to hold the unit tests. Before I dive in and start expounding on the virtues of the internal class approach as shown above I'd like to know if anyone thinks it has any shortcomings?

Edit:

Just to add a couple of points around some of the mentioned weaknesses:

  • The unit testing code will never impact the production code since the UNITTEST pre-compiler flag gets switched off,
  • The unit test code doesn't make the main code any less readable since it's placed at the bottom of each class and wrapped in a Visual Studio region directive,
  • I find the internal unit test class means the main class is actually simpler as there are no extra methods or properties that have to be exposed just for testing. There will always be cases where you want to test some internal state of a class as part of a unit test sooner or later...
like image 583
sipsorcery Avatar asked Nov 27 '22 02:11

sipsorcery


2 Answers

I find this approach very ugly, since it clutters your real logic with testing methods, making your source harder to read.

Next to that, you also have a dependency (reference) to the NUnit assemblies in your project itself. Although the dependency is not necessary when you compile without the unit_test conditional define, this is plain ugly and unneccessary.

If you want to keep up with your unit-tests, I advise you to write tests first, and then implement the real code.

Writing unit-tests is more then just about testing; it is also about designing code.

By writing the test first, you'll get to think of the API / the interface of your class, or how you want to use those classes.

like image 122
Frederik Gheysels Avatar answered Nov 29 '22 16:11

Frederik Gheysels


You shouldn't test private methods separately, because they are (should be!) used from public methods or possibly constructors - so the public methods depends on the private ones to succeed with their assignments.

These public methods/constructors will (should!) fail if the private methods don't do their work. So your approach is actually a bad approach for writing unit tests.

And to iterate the previous answers - write your unit tests before you write your methods.

like image 28
Björn Avatar answered Nov 29 '22 17:11

Björn