views:

115

answers:

2

I know that it's strongly recommended to run unit-tests in separation from file system, because if you do touch file system in your test, you also test file system itself. OK, that's reasonable.
My question is, if I want to test file saving to the disk, what do I do? As with database, I separate an interface that is responsible for database access, and then create another implementation of this for my tests? Or may be there's some other way?

+2  A: 

You could instead of passing a filename to your save function, pass a Stream, TextWriter or similar. Then when testing you can pass a memory-based implementation and verify the correct bytes are written without actually writing anything to disk.

To test problems and exceptions you could take a look at a mocking framework. This can help you to artifically generate a specific exception at the certain point in the save process and test that your code handles it appropriately.

Mark Byers
I wonder if @chester89 also wants tests to handle `invalid path`, `file collision`, `locked file`, `invalid filename`, `save interruption` etc. I suppose all of these could be mimicked as well.
scunliffe
@scunliffe, yes, I'd like to test these things too. how can I mimick these behaviour?
chester89
@chester: You could take a look at a mocking framework. This can help you to generate these exceptions at the appropriate times. Be careful to think before going down the path of testing every single possible error condition and having 100% code coverage from tests. This is often more expensive than it is worth.
Mark Byers
@Mark Byers "before going down the path of testing every single possible error condition and having 100% code coverage from tests. This is often more expensive than it is worth"Can you please explain why? I don't agree with you. Especially, in this case it is worth going for 100% coverage. chester89 may not necessarily use a mocking framework, he can also create a mock manually.
P.K
@tugga: You have to weigh up the benefit of testing every case versus the development cost. If you use existing file-selector dialogs then most of the problems with invalid paths will already be correctly handled by the component. If you are paranoid you can imagine situations where the file selector will return you an invalid file name, but these situations are very rare and are generally bugs in the framework. If you spend 90% of your development time testing for things that will rarely happen then you only have 10% of time to spend on developing features that people will pay for.
Mark Byers
+6  A: 

As of today, my approach towards this (is heavily biased on the GOOS book that I just read, but it's the best that I know of today):

  • Create an interface to abstract away the file system from your code. Mock it where this class is needed as a collaborator/dependency. This keeps your unit-tests quick and feedback fast.
  • Create integration tests that test the actual implementation of the interface. i.e. verify that calling Save() actually persists a file to disk and has the write contents (use a reference file or parse it for a few things that it should contain)
  • Create an acceptance test that tests the whole system - end to end. Here you may just verify that a file is created - the intent of this test is to confirm if the real implementation is wired / plugged in correctly.

HTH

Gishu
Just curious, what is the GOOS book? Couldn't figure it out.
Mathias
@Mathias - http://www.growing-object-oriented-software.com/
Gishu