Clojure gives you so much power so you don't need debug
developing style which is common in other less powerful languages like java, c++, etc.
- REPL. You can evaluate any function or expression anytime. You can prepare environment and reproduce the situation you need to test.
- Immutability. Clojure provides great immutable collections and pure functions library. Also there is STM that gives you full state control of your application. You can isolate mutable parts of your program from pure functional code and make those parts as small as possible so testing code responsible for state managing becomes much easier (in common cases). Testing the pure functional part is more fun and easy.
- Bottom-up programming. In clojure you can write code by small pieces. You're playing with small pure functions until you can build underlying layer (library, dsl) for the next one in which you would continue this process. The testing small (pure) functions is very easy job.
- Logging. Obviously you can log any input parameter values at any point of code.
If you keep this programming style you will reduce the chance when you really need debugging.
You can do all the job by REPL in your case. You can get input parameters of functions that generate the "debugging" dynamic code by logging . After that you would get input parameters of this dynamic code in the same way. You would have both the generated "debugging" code and input parameters at the end. So you can easily reproduce situation and test it.
Update. Regarding edited part of the question it's not correct to say that "clojure programs are hard (or impossible) to test" just because your program generates code on the fly. Keep in mind that generated code is still the data which can be manipulated as usual data collections. You don't need to build, run and freeze the whole application at the breakpoint to see what's going on there. I've already described the way you can test your dynamic code.