1

Currently, I'm in a position where I'm to write unit tests for source code I have complete visibility of (which I think means it's considered white box testing?). So, this isn't test-driven development.

Reading this (What is the difference between integration and unit tests?) clarified a lot about what the purpose of all this is, but I'm confused about my current position still.

Let's say I have a method like so:

/* Some basic description on what doSomething() does */
public int doSomething(Var someVariable) {
    int someInteger = [code does a bunch of stuff to get this];
    someInteger = someOtherClassObject.doSomethingElse(someInteger);
    return someInteger;
}

Now, I don't really know what doSomething() is supposed to do. The documentation isn't enough to really tell me what int is supposed to come out based on someVariable, and I'm not familiar enough with the source code to really come up with it myself.

But I do have the implementation, so I look at the method, put in some Var as the input, and follow the code and assert against what it looks like it would return.

public void testDoSomething() {
    ClassWithDoSomething object = new ClassWithDoSomething();
    assertEquals([what it looks like it would return], object.doSomething(new Var([some input would go here]));
}

Where some way, somehow, I mock out the doSomethingElse() call and the Var constructor (and other external class dependencies if need be).

I don't know whether this is the right way to go about these unit tests. I think I'm isolating the method as I should, but I don't know how meaningful my assert is in determining whether there is a bug or not, because I know just what the method doSomething() is supposed to do in code, and how it's going to go about it, and so I've written my assertion to get that result.

The answer I've read details how unit tests are beneficial due to the method doSomething()'s isolated failure. But when would its unit test ever fail, other than when doSomething()'s implementation changes (which would mean a change in the unit test)?

Is this an issue of not knowing the source code well enough/the source code not being well documented enough to just be able to know what output I should be getting?

If [code does a bunch of stuff to get this] was really just someVariable + 3 where someVariable was an int, is it considered a meaningful assert to assert that the return value is someVariable + 3 when I know the test is going to pass based on that implementation?

Community
  • 1
  • 1
Qianpou
  • 11
  • 2
  • 1
    I suspect this question would be more suited to the [programmers](http://programmers.stackexchange.com/) site. If other people agree perhaps it can be migrated. – shuttle87 Jul 06 '15 at 18:08
  • It sounds a lot like the code you are dealing with was never designed to be testable. Look into testing the methods and functions with the fewest side effects first then move to the bigger ones after you have done that. So in this case I would start by writing unit tests for `doSomethingElse` before writing any for `doSomething` as the results of `doSomething` will depend on `doSomethingElse`. When testing `doSomething` I would then mock the results of `doSomethingElse`, you can assume `doSomethingElse` works as intended at the point in time when you are using testing `doSomething`. – shuttle87 Jul 06 '15 at 18:22
  • Do I just accept that the code isn't really designed to be testable then? Because I can test doSomethingElse() and doSomething(), like you suggest (and it's what I've been doing). It's just that my assertions would reflect whatever I see should be resulting in the source code. And ultimately I don't know how meaningful that is, because I can write it to pass, and I don't know if there's any other option. – Qianpou Jul 06 '15 at 18:45

2 Answers2

0

But when would its unit test ever fail?

You have it exactly right; the unit test will fail when doSomething's implementation changes. The point of the unit test is to catch it when a seemingly-innocuous change actually breaks the method.

Unit tests often look similar to the code snippet you posted:

public void testDoSomething() {
    ClassWithDoSomething object = new ClassWithDoSomething();
    object.someOtherClassObject = new MockOtherClass(); 
    assertEquals(4, object.doSomething(new Var("Input that maps to 4"));
}

Both SomeOtherClass and MockOtherClass implement an IOtherClass interface that specifies doSomethingElse. MockOtherClass simply returns the input when you call its doSomethingElse method.

Brian
  • 3,850
  • 3
  • 21
  • 37
0

i'd say it's pointless to write unit testing if you don't know what the code is expected to do. unit testing is checking if given some input code behaves correctly. if you don't know what does 'correctly' mean then how can you test it? you have to understand intention of the code before writing valuable tests.

the situation is a bit different if you write tests in order to rewrite the source code from scratch. in this case tests are the best safety net you can get because they document the actual behaviour and guarantee it won't change. but even in this case, without knowing what the code does, it's easy to miss some corner cases.

so i recommend to always know the intention of the code before you write tests.

piotrek
  • 13,982
  • 13
  • 79
  • 165