2

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?

4
  • 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. Commented Jul 2, 2013 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
    Commented Jul 2, 2013 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. Commented Jul 2, 2013 at 19:57
  • 1
    @RobertHarvey Sorry, yes this situation did occur in a dynamically typed language.
    – Kris Welsh
    Commented Jul 2, 2013 at 20:05

2 Answers 2

0

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.

3
  • Uh, assertEquals("foo", someObj.strinFoo()) does check if the two strings are equal in Java/JUnit. Probably the same for dynamic languages.
    – Andres F.
    Commented Jul 2, 2013 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 :)
    – ha9u63a7
    Commented Jul 3, 2013 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.
    Commented Jul 3, 2013 at 11:58
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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