views:

180

answers:

4

I'm using Visual Studio 2008 with Microsoft test tools. I need to access a text file from within the unit test.

I've already conf the file to 'build action=content' and 'copy to output directory=copy always' but the file is not being copied to the output dir, which according to System.Environment.CurrentDirectory is '{project_path}\TestResults\Pablo_COMPU 2009-11-26 15_01_23\Out'. This folder contains all the dll dependencies of the project, but my text file is not there.

Which is the correct way to access a text file from a unit test? thanks.

A: 

How are you running your tests?

We use (TestDriven.net -> Run Tests).

From my experience, some test runners (like Junit in Netbeans) won't automatically copy any additional text files that you might need for testing. So in your case you might have to do a full build, and then try running the tests again.

And the correct way for accessing text files from tests is the way you're trying to do it. (Setting the files to "copy always" and "content", and accessing them from the compiled directory).

Also, not sure where people are getting the idea that having tests rely on files is a bad thing. It's not.

If anything, having separate test files, will only clean up your tests and make them more readable. Consider some xml parsing method that returns a large string:

String expectedOutput = fileOperator.readStringFromFile("expectedFileContents.xml");

String result = systemUnderTest.parse(somethingtoparse);

assertEquals(expectedOutput, result);

Imagine if the output was 30 lines long, would you clutter your test code with one giant String? or just read it from a file.

vicjugador
It's a Visual Studio Test Project. Test -> Run -> All tests in solution.
Pablote
Did a rebuild solution fix the issue?
vicjugador
+3  A: 

I can't answer your question as I don't use MSTest. However, I'd consider whether accessing the file system in a unit test is the right thing to do. If you introduce a dependency on the file system, the test will become slower and less trustworthy (you now depend on something that may not be there/accessible/etc). It is for these reasons that many folk will say "it's not a unit test if it hits the file system".

Although this is not a hard rule, it's always worth considering. Any time I have to touch the file system in tests, I try to avoid it because I find tests that rely on files are harder to maintain and are generally less consistent.

I'd consider abstracting the file operations to some degree. You can do numerous things here, from changing the internal loading strategy (via Dependency Injection) to -- even better -- separating the loading/use of the file so that the consumer of the file's contents doesn't even have to care about the loading strategy.

Mark Simpson
+1 Streams or TextReader/TextWriter are usually quite sufficient abstractions.
Mark Seemann
Not sure where you are getting the idea that testing with files is bad. It's not. Reading a quick string from a text file is NOT a slow operation, and having a test file part of your test (same directory) does not make is less trustworthy.
vicjugador
I 'got the idea' from working on a project with 10k tests maintained by various people. The ones that touch files are more fickle, harder to maintain and run slower than tests that do not hit the file system. Example: we had to get someone around during a refactoring session to fix up their tests, as we were getting file not found errors despite the file being present and copied to the output directory. It turned out to be a fairly obscure bug in the test that was order dependent. That simply wouldn't happen with an in memory unit test.
Mark Simpson
Btw, I'm not saying "never" do it, I'm just saying that if it's possible to avoid it without causing too much trouble, avoid it!
Mark Simpson
+3  A: 

You have to add the DeploymentItem attribute to your test class. With this attribute you specify the files which are copied into the out directory for the test run.

For example:

[TestMethod]
[DeploymentItem(@"myfile.txt", "optionalOutFolder")]
public void MyTest()
{
...
}

See also: http://msdn.microsoft.com/en-us/library/ms182475.aspx.

alexander.egger
+1  A: 

When I need a chunk of text as part of a unit test and it's more than a line or two, I use an embedded resource. It doesn't clutter your test code, because it's a separate text file in the souce code. It gets compiled right into the assembly, so you don't have to worry about copying around a separate file after compilation. Your object under test can accept a TextReader, and you pass in the StreamReader that you get from loading the embedded resource.

Don Kirkby