I was under the impression that checking the workings of a method was
unit testing. Am I mistaken in this? Is there a better way to test
this?
A unit test only tests the code in a particular method. As soon as you
confirm outside the unit, you are entering some type of functional
testing. The same is true when you hit a database, the file system, or
other external bits. Sometimes this is a clear indication of a need for
refactoring.
If you are actually hitting the file system in your test, then you are
no longer unit testing. At this point, you are more functional in
nature, perhaps even into some integration testing. There is nothing
wrong with these types of tests, per se, and I often code these types of
tests using the testing framework, but I put them into other assemblies,
as they are not unit tests.
In fact, you will see my assemblies like this:
{company}.{product}.Business
{company}.{product}.Business.Tests.Unit.VS
{company}.{product}.Business.Tests.Unit.MBUnit
{company}.{product}.Business.Tests.Unit.NUnit
{company}.{product}.Business.Tests.Integration.VS
etc.
I want to ensure the longer running tests (non-unit) do not slow down
unit testing.
To get around areas you cannot unit test, you can often use mocks with
IoC or Dependency Injection. I would have to think through the object
inherited from a file system object, however. It may only be tested
through integration tests, but this is not a huge deal as you are
dealing with a utility class. You can, however, refactor the class so
there are testable methods. A method that tests DotDot, for example, is
one you can refactor out and test with a unit testing framework. Whether
refactoring out this method is wise or not will depend on your
application and perhaps if there is an acceptable interface you can code
against for a mock.
Please note that I am not saying you should not test using VS tests
against hte file system. Just don't mix these tests with your other unit
tests.
NOTE: Any time you set up a test against outside bits, you should create
and destroy the outside bits. To do this, create the directory you want
to test in creation method of your test class and then destroy it when
you are spinning it down. If you do not do this, a test can fail if your
system setup changes. Not a problem today, as you will see "oh, the
directory is gone", but it could cause problems later. This won't make
the test a unit test, but it will make it predictable. If you want to be
really safe, you can code in an exception when the directory already
exists:
if(Directory.Exists(dirName))
{
throw new DirExistsException(string.Format("the directory {0}
exists", dirName));
}
else
{
//Create directory
}
This ensures that you do not delete the directory later on if it already
exists.
If you create directories like:
AppName.TestDirectory
And then create a pointer (dotdot) with a similar name, pointing to the
same.
You can then be fairly sure the directory and pointer don't exist. But
it is still safer to test and fail the test(s) than to delete something
that already exists. Even if it turns out to be an error that someone
manually created, you can manually delete and then rerun to confirm the
test.
I hope all of this makes sense. TDD, unit testing, etc. are a paradigm
shift in thinking and take some time, so don't get overly concerned if
it takes a bit of time to get your head around it completely.
Peace and Grace,
--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA
Twitter: @gbworld
Blog:
http://gregorybeamer.spaces.live.com
*******************************************
| Think outside the box! |
*******************************************