Your echo "${FUNCNAME[1]}" prints to stdout, so its output belongs to the output of the debug_function, which in turn belongs to the output of the test_function.
Print the message to stderr:
by redirecting the output of echo:
echo "${FUNCNAME[1]}" >&2
or by redirecting the entire output of debug_function (if the whole function should print only to stderr) when you call debug_function:
debug_function >&2
The latter method allows commands inside the debug_function to print straightforwardly to stdout. What they print will be redirected because stdout of the debug_function is redirected.
The function itself can redirect its stdout to its stderr with exec >&2. This will affect all commands in the function. But this will also affect the calling function/script, unless the redirecting function is run in a subshell.
You can run the function in a subshell on demand with (debug_function). To always run the function in a subshell, use () instead of {} when defining the function.
So a function whose entire purpose is to print to stderr and not to stdout can be defined like:
debug_function()(
exec >&2
echo whatever
# ...
)
Now echo and other commands in the function don't need >&2. Even if you call the function simply as debug_function, the commands in it will print to stderr.
Note: stdout or stderr of one subshell or command can be different than stdout or stderr of another subshell or command or the script as a whole. Redirections are possible on many levels. Therefore even a function that does exec >&2 in its own subshell can ultimately write to stdout of the whole script, if "proper" redirections happen outside of the function body. I won't elaborate.
The most important thing to remember:
Stdout is often captured (like in your case) or piped further. The main point of stderr is not to let error/debug/diagnostic messages pollute stdout.