<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="265237" data-post-id="265237">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ityonemo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ityonemo/120/11341_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ityonemo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Eh, testing has more than one function.  I use this strategy the <em>most</em> when I’m doing TDD (I’m not religious about it) and for example it appears when I’m testing intermediate compile-time artifacts with NimbleParsec.  In this case, the primary function of the test is clarity during the code writing phase and assistance in reading and understanding the code later.  I personally would really hate to test complex parsers strictly in situations that are “the code you see in prod”.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265237" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-265237" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265237"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="265242" data-post-id="265242">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tcoopman" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tcoopman/120/8112_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tcoopman
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The boundary library might also help you to keep things public but still define who is allowed to use it and who isn’t</p>
<aside class="onebox allowlistedgeneric" data-onebox-src="https://boundary.hexdocs.pm/Boundary.html">
  <header class="source">

      <a href="https://boundary.hexdocs.pm/Boundary.html" target="_blank" rel="noopener nofollow ugc">boundary.hexdocs.pm</a>
  </header>

  <article class="onebox-body">
    

<h3><a href="https://boundary.hexdocs.pm/Boundary.html" target="_blank" rel="noopener nofollow ugc">Boundary — boundary v0.10.4</a></h3>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>Personally I don’t think there’s anything wrong with testing private functions. So I wouldn’t worry too much about it if the library does what you need.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265242" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-265242" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265242"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="265531" data-post-id="265531">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pragdave" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/120/1042_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pragdave
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Programming Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>FWIW, my personal belief is that no one knows enough about software development to be able to make rules: it’s just too young a discipline.</p>
<p>But, I also believe that:</p>
<ul>
<li>
<p>defining helper functions as <em>private</em> sets a demarcation  layer in my code: if the code is to be used by a third party, then making a function private means that I’m free to change it without worrying about unintended consequences.</p>
</li>
<li>
<p>tests can be helpful for some functions. Which ones? The ones where there’s doubt; the ones which are pivotal to the rest of the code; the ones where the tests help you explore the problem.</p>
</li>
</ul>
<p>These two things do not necessarily correlate. I often find myself writing internal (private) functions which need tests.</p>
<p>“But, Dave” say those in the <em>never-test-a-private-function</em> camp. “Why not just test them indirectly via the public functions that use them?”</p>
<p>Because, I say (outside of quotes), that is often a lot of work. The higher level the function, the more state it assumes, and the harder the test is to write. And, typically, when you invoke these higher level functions, you’re calling a number of lower-level ones. The test loses focus.</p>
<p>Let’s look at this a different way. Let’s think about the demarcation of code in GenServers.</p>
<p>When I write GenServers, I typically split them into two files. One file contains the server stuff: <code>start_link</code>, <code>init</code>, and all the <code>handle_xxx</code> calls, the other contains the implementation.</p>
<p>Here’s part of a typical server:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule ExMdns.Server.ReceiveDNSPackets do

  alias ExMdns.Impl.PubSub
  alias ExMdns.Impl.ReceiveDNSPackets, as: Impl 

  use GenServer
  require Logger
  
  @me __MODULE__

  def start_link(_) do
    GenServer.start_link(__MODULE__, [], name: @me)
  end

  def init(_) do
    PubSub.join()
    { :ok, Impl.initial_state }
  end

  def handle_info({ :pubsub, msg=%PubSub.PacketReceived{}}, state) do
    state = Impl.handle_incoming_packet(state, msg.data)
    { :noreply, state }
  end

  def handle_info({ :pubsub, _ }, state), do: { :noreply, state }

end
</code></pre>
<p>None of these functions contain any logic (apart from pattern matching on their parameters. Instead, they delegate to a second module that contains the actual logic.</p>
<p>The functions in this second module contain the implementation of the logic behind the server. The server module calls an implementation function with the server state as a parameter, along with any additional parameters from the <code>handle_xxx</code>. The implementation function returns an updated state.</p>
<p>Here’s the implementation corresponding to that server:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule ExMdns.Impl.ReceiveDNSPackets do

  alias ExMdns.Impl.PubSub
  require Logger

  def initial_state() do
    []
  end

  def handle_incoming_packet(state, raw_packet) do 
    try do
      DnsPackets.decode(raw_packet.data)
      |&gt; publish_replies()
    rescue
      e -&gt;
        Logger.error("Ignoring invalid DNS packet: #{inspect raw_packet}")
        Logger.error(inspect e)
    end
    state
  end

  defp publish_replies(packet) when packet.header.qr == :reply do
    for answer &lt;- packet.answers do
      PubSub.publish(%PubSub.AnswerReceived{ answer: answer })
    end
  end

  defp publish_replies(packet) do
    Logger.info("ignoring query\n#{inspect packet, pretty: true}")
  end
end
</code></pre>
<p>Why is this relevant to testing? Because I can test the implementation functions standalone, without firing up a GenServer. And it’s easy to do, because my tests just create the state to pass in, and then verify the state that comes back. In fact, I rarely run any genservers in test: My application.ex looks like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def start(_type, _args) do
    children = case Mix.env do 
      :test -&gt; 
        [ ]
      _ -&gt; 
        [
          Server.Cache,
          Server.ReceiveDNSPackets,
          Server.UdpInterface,
          # Registration,
        ]
    end

    opts = [strategy: :one_for_one, name: ExMdns.Supervisor]
    Supervisor.start_link(children, opts)
  end
</code></pre>
<p>What has this to do with private functions?</p>
<p>It’s an illustration of how I believe that testing convenience trumps following rules.</p>
<p>Typically, Elixir developers would put the implementation functions in the same module as the server stuff. They’d then struggle with whether they should be private. Purity insists that they should: they are accessed via the GenServer.call interface, and so shouldn’t be exposed externally. Make 'em private, and then test via GenServer calls. Or, make 'em public, test them directly, and feel guilty.</p>
<p>Instead, this two-module approach sidesteps the dogma. In my apps, <em>nothing</em> in a subdirectory of <code>lib/</code> should be accessed externally. Instead, I have a top-level <code>api.ex</code> that delegates each API function, calling <code>.Server</code> files if the implementation of the function uses a GenServer, and calling the implementation files directly for stateless functions.</p>
<p>It then becomes immediately obvious to any external user of the code what they’re allowed to use: anything with more than one module name in the path is internal to my application. It may be public, but that’s for my convenience and not for your use.</p>
<p>Do I do this consistently? No: to be honest I’m experimenting with each app I write. This is where I am now.</p>
<p>TLDR; forget what people tell you is right. Do what you feel makes your code easier to work with.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265531" data-batch-url="/posts/batch_likers">
                        25
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-265531" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265531"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-solved cat-solved" title="Marked as solution"></div>
  </section>
</div>
    <div class="postbit" id="265536" data-post-id="265536">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sezaru" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sezaru/120/36113_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sezaru
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I do the same thing for gen servers (I’m pretty sure I got the idea from some article from you, haha).</p>
<p>But I tend to be, let’s say, a little bit more hardcore with the separation, I usually separate it into 4 files:</p>
<ul>
<li>The server public API file:</li>
</ul>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyGenServer do
  @moduledoc false

  alias MyGenServer.Server

  @spec child_spec(keyword) :: Supervisor.child_spec()
  defdelegate child_spec(opts), to: Server

  @spec do_something(any) :: :ok
  def do_something(some_data),
    do: GenServer.call(Server, {:do_something, some_data})

  ...
end
</code></pre>
<ul>
<li>The server gen_server implementation file:</li>
</ul>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyGenServer.Server do
  @moduledoc false

  alias MyGenServer.Impl

  use GenServer

  def start_link(args),
    do: GenServer.start_link(__MODULE__, args, name: __MODULE__)

  @impl GenServer
  def init(some_args), do: {:ok, Impl.init(some_args)}
  
  @impl GenServer
  def handle_call({:do_something, some_data}, from, state) do
    {reply, state} = Impl.do_something(some_data)
    
    {:reply, reply, state}
  end
end
</code></pre>
<ul>
<li>The server business logic file:</li>
</ul>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyGenServer.Impl do
  @moduledoc false

  alias MyGenServer.State
  
  @spec init(any) :: State.t()
  def init(args), do: State.new(args)

  @spec do_something(any, State.t()) :: State.t()
  def do_something(some_data, state) do
    ...

    {:ok, State.update_something(2)}
  end
end
</code></pre>
<ul>
<li>And finally the state file:</li>
</ul>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyGenServer.State do
  @moduledoc false
  
  @type t :: %__MODULE__{something: integer}

  defstruct something: 0

  @spec new(any) :: t
  def new(args), do: struct!(__MODULE__, args)

  @spec update_something(t, integer) :: t
  def update_something(state, something), 
    do: %{state | something: something}
end
</code></pre>
<p>It is a little bit more work to separate the server into these files, but IMO it makes the whole thing way easier to read, very easy to test and gives a very clear API for others to use.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265536" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-265536" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265536"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="265540" data-post-id="265540">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pragdave" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/120/1042_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pragdave
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Programming Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yeah, I went through a phase of having the GenServer API file, but stopped doing it in favor of having a top-level file for the actual external API.</p>
<p>I also use a module if my state is more complex than a list, but I keep it as an internal <code>defmodule State</code> in the Impl file.</p>
<p>But those are just details: whatever works is good.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265540" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-265540" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265540"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="265585" data-post-id="265585">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="trisolaran" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/trisolaran/120/23748_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  trisolaran
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The need to test private functions is in my opinion and experience, a serious design smell.</p>
<p>Testing should be focused on the external behavior of the system, defined by its API. Why? Because this is the only thing that matters to anyone who will be using it. As long as the system behaves as expected, it doesn’t matter what its internal implementation is.</p>
<p>If you have a component and you realize that you can’t properly test it with its API, chances are the component is too complex and tries to do too many things. Try to break it down into smaller components, each one with its own API that you can test. Then add integration tests for the whole system.</p>
<p>Sure, it’s more work in the short term, but your future self and your team members who will be looking at your code later will be thankful.<br>
The resulting system will be easier to understand, extend, and refactor. Less work in the long term.</p>
<p>TDD can help you guide your design towards components with clear, testable interfaces.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265585" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-265585" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265585"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="265603" data-post-id="265603">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tcoopman" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tcoopman/120/8112_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tcoopman
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>First you say focus on external behavior.<br>
A bit later you say, break a component down into smaller components with its own API.</p>
<p>What do you mean with external behavior? In the case of a REST API, is the REST API the only external behavior? Or does every module that we implement have external behavior for some other module using it?</p>
<p>What’s the difference between moving a private function into a separate module and testing that vs keeping the private function in the module and test it like that?</p>
<p>To be clear, I don’t think there is anything wrong to move a complex private function into a separate module because that makes it easier to test, but I also don’t think it’s wrong to keep it private and test it in an other way.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265603" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-265603" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265603"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="265605" data-post-id="265605">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dorgan" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dorgan/120/22107_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dorgan
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Also, code doesn’t need to be complex to be hard to test.</p>
<p>The behaviour of a genserver with no public api that all it does is periodically call itself to perform some side effect is built on entirely private behavior that should not be used by any other module. I’ve had to deal with a bunch of them and they are always nasty to test.</p>
<p>Whatever approach you take, you’re ripping the module open and testing its internals, not any “observed behavior through public api”. Theres no public api.</p>
<p>The process calling itself every X time is not something you can test via public api, so giving up on idealistic notions of how code should be tested in favor of pragmatism is best. This point is also raised in the Testing Elixir book by Andrea Leopardi, in the Testing OTP chapter.</p>
<p>You can decide to move some functions to a different module and test that because now it’s no longer “private” and you can test it “normally”, but imho that’s just lying to yourself and if theres no other reason for that module to exist(to split complex logic into smaller files, to name an example), it’s just an indirection that brings very little value.</p>
<p>At that point, just test the behaviour callbacks directly by providing some state. This may sound controversial, but if theres no client api then no solution will appeal to everyone’s taste. FWIW this would be just like <a href="https://github.com/elixir-ecto/ecto/blob/master/test/ecto/uuid_test.exs" rel="noopener nofollow ugc">testing a custom Ecto type by calling the callbacks directly instead of creating a schema and persisting it to indirectly test dump and cast</a>.</p>
<aside class="quote no-group" data-username="pragdave" data-post="14" data-topic="51118">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/48/1042_2.png" class="avatar"> pragdave:</div>
<blockquote>
<p>TLDR; forget what people tell you is right. Do what you feel makes your code easier to work with.</p>
</blockquote>
</aside>
<p>1000 times this</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265605" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-265605" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265605"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="265611" data-post-id="265611">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="trisolaran" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/trisolaran/120/23748_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  trisolaran
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tcoopman" data-post="18" data-topic="51118">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tcoopman/48/8112_2.png" class="avatar"> tcoopman:</div>
<blockquote>
<p>What do you mean with external behavior? In the case of a REST API, is the REST API the only external behavior? Or does every module that we implement have external behavior for some other module using it?</p>
</blockquote>
</aside>
<p>The latter. That’s what I mean by external behavior. The interfaces between modules or services.</p>
<aside class="quote no-group" data-username="tcoopman" data-post="18" data-topic="51118">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tcoopman/48/8112_2.png" class="avatar"> tcoopman:</div>
<blockquote>
<p>What’s the difference between moving a private function into a separate module and testing that vs keeping the private function in the module and test it like that?</p>
</blockquote>
</aside>
<p>Breaking down the logic among separate services is likely to make your code easier to read, understand, and reuse.</p>
<p>Let’s say you have a REST controller that needs: to a) access the database to fetch some data b) process the data in some way and c) call some external API to publish the data somewhere else.</p>
<p><em>Option 1:</em> You build everything in the REST controller, which will do a, b and c. The public API is the REST API, you call it in a test and check it. All the nitty gritty of the logic from a, b and c live in private functions, and you test them too as part of the test suite for the REST controller.</p>
<p><em>Option 2:</em> You spread a, b and c across their own modules or services with clear interfaces. You test the REST API in the rest controller, and the nitty gritty details of all things that can go wrong in a, b and c in their own tests suites. Since you’re working at a lower level, you can have more low-level, focused and precise tests.</p>
<p>Both options work. Both could lead to a perfectly tested and functioning system. But which option do you think is more likely to lead to a codebase (and test suite) which is easier to understand, refactor, and with components that can be reused in other parts of the codebase if needed? For me, the answer is clear.</p>
<aside class="quote no-group" data-username="tcoopman" data-post="18" data-topic="51118">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tcoopman/48/8112_2.png" class="avatar"> tcoopman:</div>
<blockquote>
<p>but I also don’t think it’s wrong to keep it private and test it in an other way.</p>
</blockquote>
</aside>
<p>I also don’t think it’s “wrong”. I didn’t want to give the impression that these are absolute rules you have to follow. But I think you have generally accepted good design principles, even in software engineering. There are surely exceptions, but there are always exceptions. I don’t think I ever added a test for a private function or method in my career - everytime I was tempted to do it because it was “easy”, I took a step (sometimes 2) back and realized that I had uncovered something not very good about my design. That’s what I meant by design smell.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265611" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-265611" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265611"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="265616" data-post-id="265616">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tcoopman" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tcoopman/120/8112_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tcoopman
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="trisolaran" data-post="20" data-topic="51118">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/trisolaran/48/23748_2.png" class="avatar"> trisolaran:</div>
<blockquote>
<p>Both options work. Both could lead to a perfectly tested and functioning system. But which option do you think is more likely to lead to a codebase (and test suite) which is easier to understand, refactor, and with components that can be reused in other parts of the codebase if needed? For me, the answer is clear.</p>
</blockquote>
</aside>
<p>I definitely agree with splitting into modules in your example, but there are also examples where I wouldn’t do it.<br>
I’m talking a situation where there is complex behavior + something that’s really tightly coupled to something else. I don’t have a good example right away because it’s not something that comes up that often.<br>
But every now and then, I want to test some private functions. But because a lot of languages don’t really have decent support for that (some do), I mostly don’t bother and either make it public or extract it. Even though it’s an implementation detail - that I’d rather not expose to everyone.</p>
<p>I also think we have these kind of discussions because most languages only have private or public functions. That’s what I like about the idea of boundary. You don’t need to make things public for everyone, you can say who is allowed to call what. So, by making something public for testability reasons, you don’t need to expose it to the whole world.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="265616" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/private-a-lib-to-test-private-functions-in-2022/51118/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-265616" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="265616"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/51118/load_more?page=3">Load more posts (14 remaining)</a>
</div></template></turbo-stream>