0

I'm working on an algorithm that's split up into multiple parts, each of which performs different tasks but is more or less separate from the others, by which I mean the only interaction between the parts is the passage of a single piece of data from one part to the next like a conveyor belt. I was doing some unit tests for the algorithm and I was wondering, is it a bad idea to use the same tests cases to test each part of the algorithm?

I thought it might be a good idea at first, since it saves me having to rewrite a whole new set of test cases for each step in the algorithm, but as I got further into it I realized some parts of the algorithm were more specific to certain tasks than others.

For example, one step in the algorithm reads a file and spits out a set of strings, which is then used by a later step in the algorithm to produce another set of completely different objects. Should separate tests be designed to specifically test the integrity of this first step?

Another thing that turned me off to the idea of using the same tests cases for multiple steps in the algorithm is that the output of one step might be complete gibberish to the step proceeding it. So a test case could pass for one step in the algorithm, but fail in the next step because despite the fact that the previous step was able to correctly parse the input data, the output is unusable to the next step.

tl;dr should the same tests be used for all the steps in an algorithm?

EDIT (In response to possible duplicate): From what I can tell, that question doesn't seem to be asking about a linear algorithm (like the conveyor belt model I described above), it seems instead to be talking about combining data from multiple individual non-contiguous components. It's also not asking about whether or not the same tests should be used for all steps.

user3002473
  • 674
  • 5
  • 16
  • possible duplicate of [How should I test the functionality of a function that uses other functions in it?](http://programmers.stackexchange.com/questions/225323/how-should-i-test-the-functionality-of-a-function-that-uses-other-functions-in-i) – gnat Jul 21 '15 at 06:34

1 Answers1

2

A good guideline is that your tests should exercise all the code that you've written.

If different inputs cause different code paths to be executed, it is a good idea to choose your test inputs so that every path is covered. More thorough testing also tries to ensure that every path is covered under different circumstances, particularly with extreme values, boundary conditions, etc.

The fact that your algorithm is in multiple parts doesn't change these principles. Since you say that you have a choice which input data to use for testing different phases of processing, I'm assuming that te steps of your algorithm can already be called in isolation. That is an excellent design, and it simplifies testing because you can achieve coverage with less effort (if three steps have four paths each, you need only 12 test cases, not 64).

If your test cases reflect real uses that your algorithm will be put to, then it's a good idea to use them for all steps - after all, that's what is actually going to happen.

It's true that if part of your algorithm fails and prevents the next stage from working, that will prevent you from catching bugs in the second stage. However, you'll have to fix the first part anyway before you publish the code, and the test suite is supposed to succeed 100% before you're done, so there is little point in choosing test cases to work around known defects. The defects shouldn't be there in the first place, so you have to work on the first stage no matter what, and it's simpler to do this first. It saves you the effort of making your tests robust against errors that can't be allowed to stay in the code anyway.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • Well, I wish it were true that each step could be called in isolation. That's not entirely the case. Let's say the input is A, and the steps are functions f, g, and h. If I wanted to test g with input A, I could send what f(A) *should* be like into g, without actually evaluating f(A), if that's what you mean? – user3002473 Jul 21 '15 at 06:51
  • @user3002473 Absolutely. The amount of work you save by making your code testable in finer increments is *combinatorial*, which in practical terms translates to "really big". If there's any way to change the code so that this is possible, do it. It's perfectly okay to change an API to facilitate testing, even if the fine-grained functions are never called in production. – Kilian Foth Jul 21 '15 at 06:53