Unit Testing (RSS)

Possible nunit bug. Tests in separate assemblies and culture

Embarking on a new project I decided that it would be a much better idea this time to separate the nunit test cases into separate projects from the production assemblies. I had read the recent article in VSJ magazine and was ready put into practice those things that I wasn't routinely doing (I.e. separating my test cases from my production class libraries.

So, the first thing that I wanted to do was write some quick scratch code in order to make sure that everything would work. My scratch code doesn't always tend to be quick as I want to make sure that it works under as many scenarios as possible. Firstly, I made a class library called CompanyName.ExampleProject.dll, wrote a class in the class library, and of course a couple of methods in the class to be able to test. Let's say then we had:

CompanyName.ExampleProject.MyClass that contained:

public string SayHello() method.

All fine so far. Then, being that I like to make sure that everything is set up in the normal fashion, i altered the AssemblyInfo file, adding in all the usual bits like AssemblyTitle, AssemblyCopyright and AssemblyCulture.

Great, I'm all set-up. Now to try and write another project to test it.

So, I set-up another project called CompanyName.TestExampleProject.dll. In a class in this library, I added an nunit test to test the CompanyName.ExampleProject.MyClass class. All looked fine, very little code to test. Run the test.

CompanyName.TestExampleProject.Tests.TestMyClass : System.IO.FileNotFoundException : File or assembly name CompanyName.ExampleProject, or one of its dependencies, was not found.

How odd. Everything compiled correctly and i could even instantiate the SayHello() method from a separate web project, so there was certainly nothing missing.

I verified that everything was in the proper place and that the code was as simple as possible. However, the only thing that I needed to do to make the test pass was to remove any reference to MyClass.

Even if I simply made a fake test and added a line: MyClass c1 = new MyClass then nunit would return the same error message.

Ok, so what would happen if I added the test into the same assembly as the MyClass class? Yep, just as in other projects, now everything would pass. So i could now make my test pass or fail,simply by moving it into another assembly. This shouldn't happen.

Looked at the more specific error message generated by nunit.

at System.Reflection.RuntimeConstructorInfo.InternalInvoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean isBinderDefault)

at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

at NUnit.Core.Reflect.Construct(Type type) at NUnit.Core.TestFixture.DoSetUp(TestResult suiteResult)

After more testing, i found the answer. i had added an AssemblyCulture to the main project assembly. Yes, this is a good thing to do. The culture I had added was perfectly legal (en-GB). With the test in the test project (CompanyName.TestExampleProject.dll), if I changed the AssemblyCulture in the other assembly (CompanyName.ExampleProject.dll) to something illegal (E.g. hello) then nunit would tell me straight away that the culture info is not valid. That's good. However, if I changed it to a legal culture, then nunit would not complain until I tried to run the tests.

conclusion
It's my conclusion that this is a bug in nunit. In order to separate my nunit tests into a separate project I need to remove the AssemblyCulture information from the assembly that is being tested. Hardly ideal, but worth it to be able to separate the tests from the production code.

Cheers

R
with 4 Comments

To unit test private methods, or just the publics

Hmm, I see that there is often debate about what should and shouldn't be tested with regard to unit tests.Many beleive that it is enough to test all the public methods of a system while others are sure that every method should be fully unit tested. This, for me at least is a tough one. There are, I think many factors to consider.

So, what are the factors involved? - Here are just three.

  1. Pressure from the business to write production ready code. Yesterday
  2. The difficulty in testing private methods
  3. Public methods are exposed interfaces, therefore if these are fully tested, why test what they call. 

It doesn't quite sit right with me that each part of the system isn't tested. After all, there is no more reason why the private methods shouldn't break than the public ones. Why should private methods suffer the loneliness of a test-free life. On the other hand, these are hidden chaps that are never exposed to our clients. All those proud public method chaps are sitting on the front line and happily calling the privates for help when needed.

Also, to test the private methods seems like it's going to add some overhead, certainly in time and resource. If our public methods are properly, no really properly tested then we would also be duplicating some of the testing, surely.

In my experience, there is always a balance to strike between doing the best possible to ensure that we write robust, maintainable and bug free software and resigning ourselves to the fact that it's the busness that pay our wages and if we can test what we expose well enough then we are saving ourselves time and overhead while still delivering on-time and within budget.

By now you should know which side ofthe fence I sit on. Test all your public interfaces, but do it well.

For those interested, here is a link to a good article on testing private methods in C# http://www.codeproject.com/csharp/TestNonPublicMembers.asp

Cheers

R

with 3 Comments