Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have heard that a desirable quality of unit tests is that they test for each scenario independently. I realised whilst writing tests today that when you compare a variable with another value in a statement like:

assertEquals("foo", otherObject.stringFoo);

You are really testing three things:

  1. The variable you are testing exists and is within scope.

  2. The variable you are testing is the expected type.

  3. The variable you are testing's value is what you expect it to be.

Which to me raises the question of whether you should test for each of these implicitly so that a test fail would occur on the specific line that tests for that problem:

assertTrue(stringFoo);
assertTrue(stringFoo.typeOf() == "String");
assertEquals("foo", otherObject.stringFoo);

For example if the variable was an integer instead of a string the test case failure would be on line 2 which would give you more feedback on what went wrong.

Should you test for this kind of thing explicitly or am i overthinking this?

share|improve this question
    
Is there any way that your specific tests could fail (i.e., catch a bug) that your more general test would pass? If "no", then you don't need the more specific tests. –  Dan Pichelman Jul 2 '13 at 19:56
    
The first two will never catch a situation the equality check won't, so I'd say this is over-complicating things. –  Lee Jul 2 '13 at 19:57
4  
Ehm, on items 1 and 2, only if you're working in a dynamically-typed language. In a statically-typed language, it won't compile if those two things aren't true. –  Robert Harvey Jul 2 '13 at 19:57
1  
@RobertHarvey Sorry, yes this situation did occur in a dynamically typed language. –  kris welsh Jul 2 '13 at 20:05

2 Answers 2

up vote 0 down vote accepted

The straight answer is YES, you may still have to. Also, for assertEquals you are essentially checking for two things - types and values, not if they exist. The reason is that the function will show error in an IDE (red line) if one of them is not in the scope. HMMMM.... You can still say that using text editor rather than smart IDEs will not tell you that - which is true. But why wouldn't you use it in the first place? Therefore, that test is automatically done even before you run the test. So, your first assumption about assertEqual test checking for three things is not necessarily correct - It is defenitely two, may be three. Also, when you say about scope, you need to be careful; global or local scope same? What I am trying to say is this:

package bla.bla.bla.SomeObject;

class FooTester{
//Global var "foo"
String fooStr = "foo";

@Test
testFoos_Are_They_In_Same_Scope() {
     SomeObject someObject = new someObject();  // Mock object
     String testFooStr = someObject.stringFoo();
     assertEquals(fooStr, testFooStr);
}
}

Clearly, foo and testFooStr are not in the same scope. fooStr is global and testFooStr is local.

Another good argument for having three separate test is the following:

assertEquals("foo", someObj.stringFoo());

To a person who has never done any programming, this would mean that you are testing for two strings to be equal or not. However, if you have a test where you can say:

/* Asserts if the condition is _NOT_ true
assert("THEY ARE NOT AT THE SAME MEMORY LOCATION, BUT MAY HAVE THE SAME VALUE", "foo" == someObj.stringFoo());

You have to figure out very carefully what you are trying to test and write tests with meaningful names. If you can use one test for three cases, take care when writing them and use some sensible comments declaring test purpose (if necessary).

I have done this in the past and still do it. People criticised me for writing double tests, but never told me that I didn't write enough tests. It pays dividends in long-term.

share|improve this answer
    
Uh, assertEquals("foo", someObj.strinFoo()) does check if the two strings are equal in Java/JUnit. Probably the same for dynamic languages. –  Andres F. Jul 2 '13 at 21:46
    
@AndresF. Check my edited answer. You are right about assertEquals but I was trying to make a point about testing rather than the functions themselves :) –  hagubear Jul 3 '13 at 6:54
    
So is it a best practice to check for result types in unit tests for dynamic languages? Ugh :P Remind me to stick to static typing! –  Andres F. Jul 3 '13 at 11:58

It depends. Quite probably you shouldn't use three tests for something as small as that, and rather use a debugger if it fails. However, if you have reason to believe one of the 1st two cases would be a probable bug, by all means, put them in, if just as a remainder to check for all of them.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.