This, 100%. Unfortunately, private functions aren’t testable without jumping through some hoops. I found a macro on SO somewhere for defining functions that expands to def if the environment is test and defp otherwise. It’s a hack and I only use it in my own code, but I wish it were built in.
(And inb4 “private functions should be so simple they don’t require testing”. IMO it’s reasonable to have complex functions which nonetheless should not be part of the public interface.)
There are few solutions for that problem and there is still no consensus how to deal with testing private functions in Elixir, there are few possibilities though:
Do not test them at all
And when you need testing, then export them to separate, internal and undocumented, module.
Expose all functions as public in testing:
defmodule Foo do
if Mix.env == :test do
@compile :export_all
end
defp foo, do: 10
end
And then all functions are exported by default.
Define tests in line within module
This technique is sometimes used in Erlang with EUnit, but I have written simple macros that allows you to achieve similar solution in Elixir with ExUnit. Not perfect (again), but it is some kind of solution.
However in general I agree to the fact that in most cases you should not test private functions, and if you need to do so, then in most cases you probably need to extract that functionality to separate module anyway.
If I might self publicise for a moment, I’m working on a Erlang/Elixir like language with full type inference and ADTs, perhaps you might find it interesting.