tags:

views:

99

answers:

6

I'm interested in the opinion, practices and reccommended best practices of using lengthy setup strings in unit tests.

Do you prefer to declare the tests in-line, close to your test, or externalize in a file somewhere?

Note, I'm talking about test assets which are specific to a single unit test, so not neccessarily suitable for living in a setup() method.

I see pros/cons of both -- I'm a fan of keeping things important to your test as close to the test as possible, however a few lines of string setup can quickly become nosiy in a test method.

Eg., I'm writing a quick parser to strip unused css declarations from files. I wanna test that given a specific input string, the correct text is stripped out. My test has become really noisy with all the string concatenation.

public void removesStyleFromText() 
{
 StyleCleaner styleCleaner = new StyleCleaner();
 String source = ".presentInFileOne {\r\n" + 
   "}\r\n" + 
   "\r\n" + 
   ".presentInFileTwo {\r\n" + 
   " bottom-corners-rounded : false;\r\n" + 
   "}\r\n" + 
   ".notUsed {\r\n" + 
   "}\r\n" + 
   "";

 String actual = styleCleaner.removeDeclaration(source , "notUsed");

 String expected = ".presentInFileOne {\r\n" + 
 "}\r\n" + 
 "\r\n" + 
 ".presentInFileTwo {\r\n" + 
 " bottom-corners-rounded : false;\r\n" + 
 "}\r\n";

 assertEquals(expected , actual);
}

Given this example, I could externalize the actual / expected into external files, but that also makes the test a little unclear as to what it's actually testing for.

Thoughts?

Regards

Marty Pitt

A: 

I would externalize the strings and write some comments on what you're testing for. Comments also have the advantage of being a lot more readable than these string constructs.

schnaader
+1  A: 

Definitely code, it is much easier to tell right away what you are testing and much easier to refactor when you want to reuse it. I like to keep it DRY, so I usually tend to move it to builders or concrete classes (depending on what I am doing), which gets me a default config that I can tweek for the specific test.

eglasius
+3  A: 

I personally prefer to keep the strings inline in cases like this. The string is important for understanding what the test is supposed to do so having to look it up externally seems counterproductive.

If you have lots of the same tests that only differ in what string goes in and what string comes the story is a little different though, you might want to look at table-based testing solutions. In .Net you have mbunit. It allows you to run the same test with different expected input/output or you could look at tools like Fitnesse that allow you to define tables of data that you want to test against.

Mendelt
A: 

I would let it this way - since it is important for that test and strictly seen if you rely in your test on something "external" it is not a strict unit-test.

Gambrinus
A: 

Your problems will vanish if you use a programming language which supports proper string literals. For example, Python supports multiline strings:

source = """
.presentInFileOne {
}

.presentInFileTwo {
       bottom-corners-rounded : false;
}
.notUsed {
}
"""

expected = """
.presentInFileOne {
}

.presentInFileTwo {
       bottom-corners-rounded : false;
}
"""

assert removeDeclaration(source, "notUsed") == expected

Such language constructs will make your tests more readable than anything else.

vog
A: 

There is a hack to make multi-line Strings literals work in Java. Performance is probably not something you'd want to see in production but good enough for tests.

My rule is: If the string is small (< 10 lines), I keep them inline but in a way that I can always cut everything between the "" out and just paste the new version (this means I'm converting the strings in my assertEquals() if necessary).

If the string literal is longer, more complex or when I have a good editor (with syntax highlighting, etc), I like to keep them in a test data folder with the name of the test as the filename. You can then use a utility function in your JUnit test which uses getName() to load the string and you will know without any magic which file belongs to which test.

If you have lots of those, I use the test class name (class.getSimpleName()) as the folder name to maintain my grip on them.

Aaron Digulla