lamtrhieu

lamtrhieu

How to write tests for public functions with many complex private functions

Hi everyone,
I have a module with several public api and the implementation for these public require call to several private functions. Something like this

def foo do
  bar 
  baa 
  baz
end

defp baa do
...
end
defp baz do 
...
end
defp bar do
.....
end

And baa have 2 cases to test, baz have 3 cases, and bar have 5 cases. So if I just keep them as private functions inside 1 module, I need to write 2x3x5=30 unit tests.
So I refactor them to separate module and make them public so I just need to write 2+3+5=10 unit tests and some smoke tests for foo which don’t cover all the scenarios.

Is that approach ok and how I prevent users from misused my private module ? I just want the user to use my public module only.

Hope to hear your thoughts on this matter. Thanks

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

It can already solve it today :slight_smile: Add use Boundary to the top-level module (e.g. context), and the cross-boundary calls to the internal ones will be reported. It’s still not fully usable, b/c the support for nested boundaries is lacking, but that’s definitely on the roadmap.

Boundary doesn’t do any mangling. It uses compilation tracer to collect all function/macro invocations, and then reports non-permitted cross-boundary calls.

It’s definitely not bulletproof. Breaking it is currently as easy as using apply to dynamically invoke the function. This can be detected though, and I plan to address it, but even then you can work around by constructing the module name dynamically.

All that said, boundary will make you work harder to introduce unwanted dependencies into your codebase.

chrismcg

chrismcg

It would certainly help stop “accidental” usage where someone who doesn’t understand the @moduledoc false idiom calls a function directly instead of through private api.

NobbZ

NobbZ

The convention is that internal modules are @moduledoc false, similar how internal functions are @doc false, though you have no way to enforce that no one will use them.

There is some prototype library defmodulep which hides modules by name doing some name mangling, but still, once someone figured out the mangled name, they can use the module anyway.

Where Next?

Popular in Questions Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement