There is ample discussion on the blogosphere as to why you should or shouldn't test your private methods.
In the 'NO camp'
http://www.redhillconsulting.com.au/blogs/simon/archives/000119.html, http://www.lostechies.com/blogs/chad_myers/archive/2008/11/21/do-not-test-private-methods.aspx
In the 'YES camp'
http://beust.com/weblog/archives/000303.html
I think there is some confusion as to why you should or shouldn’t.
Test-Driven Development
If you personally are practicing TDD then you are testing a whole chunk of code before and after refactoring. If your code passes the tests before refactoring, then you can be sure that any extracted methods are covered. That is to say you don’t need to test these methods (private or public) as their containing code have tests already.
Ok so you write your test, it fails. You then write your code to make the test pass. You are green. Then you refractor. After you refractor, you realize the method can be made private as nothing outside the class needs to know it is there. So now you have a private without any immediately related test (even though it is actually covered with the pre-refractored test).
Now if at some point in the future another developer comes along and adds a private method without any associated test; you now have two private methods, one with a test, one without. A quick glance at the source code of the test suite may not show that the first private method is covered. Perhaps forcing a rule that all methods should be tested should eliminate those non tested methods from creeping in. It may be a case of refactoring your tests to make sure each method has at least one associated test.
Regression testing
If you are working with legacy code and you are required to make changes to some public or even private methods, it would be wise to wrap tests around these methods, that way you can be sure they are functioning the same after the changes as they were before. This would be the same case for both public and private.
Code Coverage
Code coverage is the extent to which code has been tested; that is all code. So if you have 2 public methods and 98 private methods (just for example, this would be a ridiculously large class) and you have tests only for the public methods and not the private ones; do you have 100% code coverage? I wouldn't say so. I wouldn't be confident with a situation where I don't have any coverage of private methods.
I like the quote from Cedric Beust post.
"if it can break, test it"
A couple of weeks back I was asked by a friend of a friend why I code in c# over VB. I didn’t give him a very good answer at the time as I just couldn’t pinpoint the reason. Since then I have had a real good think about it and have come to this conclusion. It just looks bulky. Not a good reason I know. I am not what you would consider a power developer, I use .net for relatively simple tasks and there isn’t any feature I would consider using one language over the other. So for me it just comes down to aesthetics. I can and have programmed in both classic VB and VB.Net and it was only about 4 years ago that I decided to have a look at c#. Now when I look at old code I have written in VB.Net I not only shudder at the overall crapness of my code, but also the amount of non-whitespace. A simple while loop in VB looks less clean than its cousin in c#.
1: Dim counter As Integer = 0
2: While counter < 20
3: counter += 1
4: End While
1: int counter = 0;
2: while (counter < 20)
3: {
4: counter++;
5: }
For me the second code example is easier to read, I know the while construct has ended by the placement of the closing brace I don’t need 8 superfluous characters to tell me that.
I was brought up with BASIC on the Commodore 64 and then Amiga BASIC through vb2,3,4,5 (didn’t really use vb6), then VB.Net and now c#. I do feel to a certain extent a bit of a traitor.
As has been reported elsewhere, word is that inside Microsoft they are trying to align the language development teams more so a particular feature that becomes available for one language will immediately be available in others. Will this blur the choice between languages?
There is so much information out there pertaining to our jobs, a lot comes in the form of articles and books. How do you get through all this information fast without loosing comprehension?
Well this is my technique. I have used this since my university days, and although it works for me, it isn’t perfect for everyone. It is a mixture of speed reading and mind mapping. I use this for both technical articles such as research papers as well as chapters from technical books.
- Quickly skim the paper or chapter noting down only the subheadings.
- Use these subheadings as the main section of a mind map branching out from a central topic. This central topic could be paper or chapter title.
- Look at and normally read the captions for any diagrams and charts (not source code though)
- Speed read the article or chapter, don’t stop for words or phrases you don’t quite understand.
- Speed read the article again, this time writing out any key points under their relevant topics on the mind map.
- Go have a cup of coffee.
- Look over your mind map. You will naturally be drawn to topic areas that interest you the most. If needed you could re-read these sections again.
There are several ideas behind this technique.
- Getting your brain to absorb only information that interests it. Most text from books and published papers are written in such a way that allows the reader to easily flow between the related subject matter within it.
- You look at images and charts before starting to read so as to give yourself a heads up for when you reach that section of the text.
- Not stopping for difficult phrases or words helps keep the rhythm up, you will be covering these words again at the second pass. Second time around you will have more of an idea of the context of the piece.
- The detail of the mind map automatically comes out from the subject matter that interests you. We all have a tendency to remember information that is of interest to us. This information can also give extra pointers for more research down different paths.
So the speed reading gets you through the text fast and the mind map emphasizes the important bits.
The main difficulty with speed reading I find is keeping it up. Initially it is so easy to drop back into normal ‘speaking in your head’ reading. Keep practicing, it will get easier.
What about code?
The only way I find to understand the code aspect of these articles is to just type it in and step through using the debugger. I find learning easier if I can do some practical work to go along with the theory. Does anybody else have any tips?
This is one VS 2008 shortcut I use all the time. Open the folder which contains the file you are currently working on.
Simply right click the tab in the editor view and choose that option. Ok nothing new there. It would be better if there was a shortcut. Go to Tools > Options > Keyboard and select File.OpenContainingFolder and assign a key, I chose Alt+o. Really simple, never got around to assigning it until now.
I am a little late in setting out my resolutions, and although 1st January is a good time of year to set out your objectives, I’ve never liked to be restricted by a date. If I smoked (which I don’t), and I wanted to give it up, I wouldn’t wait until the 1st Jan, I would give up there and then. No time like the present. So last February I set out some objectives for the coming 6 months, how did I do?
1. Finish my MCSE Upgrade exams – done
2. Get to grips with the latest development methodologies such as Inversion of Control, Design Patterns, Mocking, Unit testing, MVC and MVP, Dependency Injection, and Continuous Integration – well I got to grips with Unit testing, Continuous Integration and MVC, I started with the other design patterns then ground to a halt.
3. Get all my code to pass FxCop analysis – done
So what for the next 6 months?
1. Getting to grips with Design Patterns.
2. Look into the Entity Framework as compared to other tools already out there.
3. Look into Ioc/ Dependency Injection frameworks.
I think I will tackle these in this order as I have already started on design patterns.
There are of course smaller ongoing objectives which I aim to have a go at, some of these are:-
1. Learn how to get more out of Resharper. I find this an invaluable tool and I know there is more to it that what I use it for, so I plan on utilizing it more.
2. Build the analysis results from FxCop, StyleCop and perhaps SourceMonitor into our CI environment
You may be asking ‘why am I blogging this?’. Well to be honest I find it difficult to remain focused on a particular objective and some times need a quick reminder.
Well the holiday season is finally upon us, and I would like to take this opportunity to post a list of applications that I personally have found useful over the past 12 months. There are some classics in there, but a few surprises. Have a look, there may be something of interest to you. So, have yourself a ‘Merry Christmas and a Happy New Year’.
Windows Server 2008 (configured as a workstation)
Visual Studio 2008
Plug-ins – Ghost Doc
Resharper 4.1
Copy Source as HTML
Firefox
Plug-ins – Foxmarks
Sage RSS
Firebug
Colorzilla
Yahoo Widgets
General Tools
Deep Burner
Foxit Reader
Magic ISO
Glary Utilities
CCleaner
Win dirstat
Notepad++
JKDefrag
Continuous Integration
CC.Net
NUnit
NAnt
Editor4NAnt
NCover
Code Analysis & restructuring
NDepend
NArrange
Win Merge
Reflector
Source Monitor
Documentation generation
Sandcastle
Sandcastle Help File Builder
XML
SketchPath
Source control
Subversion
Tortoise SVN
Ankh SVN
Graphics
Paint.Net
Blogging
Live Writer (of course :)
Plug-ins – Code Snippet plug-in
In previous posts I have covered getting cc.net up and running, combining NUnit reports with cc.net and generating documentation automatically as part of the build process. In this post I want to briefly describe how to get your unit test code coverage integrated with cc.net.
If like me you have a legacy project that you think has been tested to the ends of the Earth and back, you may be in for a shock. There will be sections of your code base that is just not touched by your unit tests. One of the best tools to see where you are missing coverage is NCover. This is a tool which although was once free, you can still get fully functional free versions prior to the project becoming commercialised. These can be downloaded from here. Version 1.5.8 is the one I have been using here. Although it states it is beta, it is fully functional and as far as I can tell, bug free.
There is another tool you may need, although it doesn’t effect our usage with cc.net. This tool is NCover explorer, and like NCover used to be a free product. It is now shipped with the full NCover. Older versions of NCover explorer can be downloaded from Grant Drakes blog here. I have been using version 1.4.0.7.
There are two methods to you using NCover. The first is to attach it to your application and run it. It will analyze all the sections of code which it touches and those it doesn’t touch at all. This is ok if you just want to see if there are any code which is being underused or parts which are overused and could be a potential bottleneck. The second method is to run it against the dll produced from your unit tests. This is the method I will describe as it shows how much coverage your tests give as opposed to how much code the application covers. Don’t be confused all we be clear in a moment.
OK, firstly you need to make sure that your unit tests are compiled to a dll, you can use a Nant script for this. Here is an example of one of my NAnt scripts.
1: <csc target="library" output="nant_build\UnitTests.dll" debug="true">
2: <sources>
3: <include name="..\UnitTests\*.cs"/>
4: </sources>
5: <references>
6: <include name="nant_build\MyApp.dll" />
7: <include name="nant_build\nunit.framework.dll" />
8: </references>
9: </csc>
Without posting the whole script, firstly MyApp is compiled into the nant_build directory, then the above section compiles just the unit tests which are in a separate project in the same solution. One important thing to note is the fact that NCover needs the debug information, so append the debug="true" attribute to the csc command for the MyApp.dll.
Next you need to call the ncover.console.exe and pass it any needed parameters like this:-
1: <exec program="C:\Program Files\NCover\1.5.8\ncover.console.exe"
2: commandline="//reg //w "nant_build" "C:\Program Files\NUnit 2.4.3\bin\nunit-console.exe" UnitTests.dll" />
reg = Registers the CoverLib.dll
w = Working directory
You pass ncover the location of the NUnit console application installed on your machine, and then pass that the location of your unit tests library file. Just remember that this script will be run on a build machine, so you must make sure that all paths are correct. On my development machine I run local nant builds using a file like nant_local.build as opposed to nant.build on the cc.net server. This way I don’t ‘accidentally’ run a script that may publish an application to one of our servers when I don’t want to. I have described how to run a NAnt script from your VS IDE here. When this script is run NCover will generate an XML file called Coverage.xml by default, you can rename it by passing the //xml parameter.
So now the Coverage.xml file is produced you need to display it using cc.net; to do this edit the ccnet.config file. Mine is located at c:\Program Files\CruiseControl.NET\server. Like merging the NUnit results you have to specify the location of Coverage.xml in the <file> element. Now the cc.net documentation states that you can specify multiple xml files in the same <file> element, but I couldn’t get this to display anything, so what I did was to specify the NUnit and NCover results in separate <file> elements like this:-
1: <publishers>
2: <merge>
3: <files>
4: <file>
5: <![CDATA[C:\Projects\MyApp\MyApp\nant_build\test_results\result.xml]]>
6: </file>
7: <file>
8: <![CDATA[C:\Projects\MyApp\MyApp\Coverage.Xml]]>
9: </file>
10: </files>
11: </merge>
12: <xmllogger />
13: </publishers>
Then when a build is run, you get the data integrated in the report like this:-
Clicking on the NCover Report link on the cc.net main menu gives you a more in depth analysis like showing which line numbers in your .cs files have not been visited by your unit tests.
Like I said earlier I was quite shocked, when I first run this a couple of weeks ago I only had 26% coverage. Now I am up to 96% and am trying to cover the edge cases.
It is funny how things work out, a disaster can lead to opportunities. Last month my main pc at home somehow got a corrupt hard drive and at first I thought I had lost all my private data (family pictures, documents etc), the drive wasn’t backed up as it was a mirrored drive, which I had thought would be an alright disaster recovery mechanism. It happened while I was upgrading to Server 2008. I broke the mirror and disconnected them. So the drives themselves weren’t connected at the time of upgrade, it was when I reconnected them after the upgrade was successful, the OS just couldn’t see them, maybe a corrupt partition table. I even rolled back to Server 2003, but nothing. The most important thing was that I had to recover that data somehow. This lead me to a piece of software called Active File Recovery which is just so simple to use. To cut a long story short I managed to recover all my missing data. But one thing that really made me think was the fact that this software could see my data and all previous owners data (it was a 2nd hand drive bought from a computer fair).
I have learnt several things from this experience, these being:-
- I need to use a more reliable medium. Using new hard drives instead of 2nd hand ones may have prevented this issue, but at the time (2002) I made the purchase there wasn’t a lot of data and it was the only viable option.
- I need a disaster recovery plan. Yes even for your home pc. I chose not to use a backup tool for my data for the simple fact that as there was around 13000 files, it would have took too long to run a back up on a machine which wasn’t permanently powered up.
- Be aware of old data. If upgrading an old hard drive, keep in mind that the data may still be recoverable. Dispose with care.
Now I have my data back I needed to find a mechanism which would protect my data with the least amount of administration work. That is I don’t want to have to remember to run a back up every time I add a file to my important documents drive. This is what has lead me to the Synchronization Framework. Using an expanded on version of the file synchronization example I now have a mechanism which will synchronize my important docs with my NAS, running in the background as a service. I can sleep better at night now, but what if we have a flood or worse? All my data is still in the same location. My next personal project is to also get it to synchronize with the cloud; hello Live Mesh.
This morning I read a post by Davy Brion who was explaining a technique to test private methods. Although the post was interesting, it was a comment by Rafferty Uy that got me thinking. He suggests that you make your method protected instead of private and have the testing class inherit from this class. There is much debate as to whether you should be testing private methods at all, and as I am fairly new to unit testing, I have only ever tested my public methods.
From Microsoft:-
protected
The type or member can only be accessed by code in the same class or struct, or in a derived class.
(http://msdn.microsoft.com/en-us/library/ms173121.aspx) So that is fine if your tests live in the same project as the code being tested. You just inherit from the class. If however you have all your tests in a separate project, then you simply need to have a reference to the .dll or .exe of your main project with the methods that need testing. Add the namespace to your using list and inherit the class in your test class.
1: using NUnit.Framework;
2: using Spike.PrivateMethodTest;
3:
4: namespace Spike.UnitTests
5: {
6: [TestFixture()]
7: public class Class1 : Spike.PrivateMethodTest.Program
8: {
9: [Test()]
10: public void TestPublicMethod()
11: {
12: string expectedValue = "this is public";
13: string actualValue = Program.MyPublicMethod();
14: Assert.AreEqual(expectedValue, actualValue);
15: }
16:
17: [Test()]
18: public void TestPrivateMethod()
19: {
20: string expectedValue = "this is private";
21: string actualValue = Program.MyPrivateMethod();
22: Assert.AreEqual(expectedValue, actualValue);
23: }
24: }
25: }
This technique seems by far the simplest I have come across to allow you to test private methods.
If you don't already know, the Synchronization Framework team has just released the CTP for v2.0
There are 3 core areas of the framework:-
- Sync Services for ADO.NET: Synchronization for ADO.NET enabled data sources
- Sync Services for File Systems: Synchronization for files and folders
- Sync Services for FeedSync: Synchronization for RSS and ATOM feeds
The framework home page contains links to lots of decent resources. The introduction to the framework, discusses file synchronization between two directories. This for me was a great place to start. As the document was written in November 2007, there was bound to be a few changes as to how you call various methods. I will cover here some of those changes for anybody who is interested.
1: // Set options for the sync operation
2: FileSyncOptions options = FileSyncOptions.ExplicitDetectChanges | FileSyncOptions.RecycleDeletes | FileSyncOptions.RecycleOverwrites;
Becomes
1: // Set options for the sync operation
2: FileSyncOptions options = FileSyncOptions.ExplicitDetectChanges | FileSyncOptions.RecycleDeletedFiles | FileSyncOptions.RecycleConflictLoserFiles;
1: SyncAgent agent = new SyncAgent();
2: agent.LocalProvider = sourceProvider;
3: agent.RemoteProvider = destinationProvider;
4: agent.Direction = SyncDirection.Upload; // Sync source to destination
5: Console .WriteLine( "Synchronizing changes to replica: " + destinationProvider.RootDirectoryPath);
6: agent.Synchronize();
Becomes
1: SyncOrchestrator agent = new SyncOrchestrator();
2: agent.LocalProvider = sourceProvider;
3: agent.RemoteProvider = destinationProvider;
4: agent.Direction = SyncDirectionOrder.Upload; // Sync source to destination
5: Console.WriteLine("Synchronizing changes to replica: " + destinationProvider.RootDirectoryPath);
6: agent.Synchronize();
1: switch (args.ChangeType)
2: {
3: case ChangeType.Create:
4: Console .WriteLine( "-- Applied CREATE for file " + args.NewFilePath);
5: break ;
6: case ChangeType.Delete:
7: Console .WriteLine( "-- Applied DELETE for file " + args.OldFilePath);
8: break ;
9: case ChangeType.Overwrite:
10: Console .WriteLine( "-- Applied OVERWRITE for file " + args.OldFilePath);
11: break ;
12: case ChangeType.Rename:
13: Console .WriteLine( "-- Applied RENAME for file " + args.OldFilePath +
14: " as " + args.NewFilePath);
15: break ;
16: }
Becomes
1: switch (args.ChangeType)
2: {
3: case ChangeType.Create:
4: Console.WriteLine("-- Applied CREATE for file " + args.NewFilePath);
5: break;
6: case ChangeType.Delete:
7: Console.WriteLine("-- Applied DELETE for file " + args.OldFilePath);
8: break;
9: case ChangeType.Update:
10: Console.WriteLine("-- Applied OVERWRITE for file " + args.OldFilePath);
11: break;
12: case ChangeType.Rename:
13: Console.WriteLine("-- Applied RENAME for file " + args.OldFilePath +
14: " as " + args.NewFilePath);
15: break;
16: }
However the biggest change I have come across with this example is that the FileSyncProvider takes in a GUID as a parameter, not a Synchronization.SyncId
The SyncId does have a public method which returns a guid like so:-
Guid guidSourceReplicaId = sourceReplicaId.GetGuidId();
So just use this instead, what is the difference you may ask? Well a guid comprises of 5 blocks of hex separated with hyphens, and the SyncId is just the hex without any hyphen.
The whole Synchronization Framework seems such a fantastic technology I hope to delve in a bit deeper in the coming months.
More Posts
Next page »