What's a good way to unit test the main function that calls all the simple functions?
Question: I have this code with lots of small functions `f_small_1(), f_small_2(), ...
f_small_10()`. These are easy to unit test individually.

But in the real world, you often have a complex function
`f_put_things_together()` that needs to call the smaller ones.

What is a good way to unit test `f_put_things_together` ?

    
    
    func f_put_things_together() {
        a = f_small_1()
        if a {
            f_small_2()
        } else {
           f_small_3()
        }
        f_small_4()
        ...
        f_small_10()
    }
    

I started to write tests but I have the impression that Im doing this twice as
I have already tested the smaller functions.

I could have `f_put_things_together` take objects a1, a2, ..., a10 as
arguments and call `a1.f_small_1()`, `a2.f_small_2()`, ... so that I can mock
these objects individually but this doesn't feel right to me: if I didn't have
to write unit tests, all these functions would logically belong to the same
class, and I don't want to have unclear code for the sake of testing.

This is somehow language agnostic and somehow not, as languages like Python
enable you to replace methods of an object. So if you have an answer that is
language agnostic, that's best. Else Im currently using Go.


Answer: The general case that you've shown in your example demonstrates the need to
test both the simple functions and the aggregation of the results of those
functions. When testing the aggregating function, you really want to fake the
results of the smaller functions the aggregating function depends on. So,
you're on the right track.

However, if you're having trouble writing unit tests for your code, then
you're probably having one of these classes of problems:

  * You've somehow violated the SOLID principles ([description here](http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod)). In other words, something is deficient in the micro-architecture of your code.
  * You're trying to fake someone else's interface and you're having trouble matching the actual behavior of their implementation with your fake implementation. (This doesn't seem to be the case here).
  * The objects that you're testing with require a bunch of data setup that should be simplified, at least within the context of testing (also, doesn't appear to be the case).

**If you're tests are painful to write, they're telling you something!** With
experience, you'll be able to quickly pick up on the pain point in your
implementation that the tests are indicating.

Unfortunately, your example is a bit small and abstract. To be more precise, I
don't know what `f_small_1` ... `f_small_10` do. So, with more details, I
might make more precise recommendations for doing some small refactoring that
could have a big payoff for your testing.

I can say, however, that it appears that `f_put_things_together` looks a bit
big to me. This could be a violation of the Single Responsibility Principle
(the 'S' in SOLID). I see 10 function calls at a minimum along with some
branching logic.

You'll need to write a separate test for each branch path through your
function. The less branching you have in a particular function, the less tests
you'll need to write. For more information, take a look at [Cyclomatic
Complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity). In this
case, it seems the method has a low CC, so this likely isn't the problem.

The ten calls to smaller functions do make me wonder a bit. It looks like for
simplicity you've left out capturing the return value of these function calls
and the logic for aggregating the results. In that case, yes you really do
want to fake the results of the smaller functions then write a few tests to
check the algorithm you're using to aggregate everything.

Or, perhaps the functions are all void and you need to verify that everything
happened, and maybe that it happened in the right order. In that case, you're
looking at writing more of an interaction-based test. You'll still want to put
those smaller function calls behind an interface / class / object that you
fake. In this case, the fake should capture the calls and the call order so
that your test can make the assertions that are really important.

If some of the smaller functions are related to each other, it might make
sense to group them together in a single method a separate class. Then, your
test for `f_put_things_together` will have fewer dependencies that need to be
faked. You will have a new class that also needs tested, but it's much easier
to test two smaller methods than to test one large one that has too much
responsibility.

### Summary

This is actually a very good question with the exception of it being a bit
vague. If you can provide a more detailed example, perhaps I could make more
detailed recommendations. The bottom line is this: If your tests are difficult
to write then either you need some help / coaching on writing tests or
something about the design of your implementation is off and your tests are
trying to tell you what it is.

