Fl4m3Ph03n1x

Fl4m3Ph03n1x

Classicist VS Mockist TDD in Elixir

Background

For those of you wondering what classical TDD is and Mockist TDD is:

Mainly, classical TDD is focused on testing system boundaries and treats your projects like a black box. It provides for flexible tests that don’t break upon implementation changes.
Mockist TDD, tests the interactions between each component of your app, so it is more coupled to implementation details, but it offers stronger/more precise tests.

TDD in Exlir

I am now trying a new approach to testing apps in Elixir. I have read for the 100th time Mocks and explicit contracts in Elixir and I get the idea of creating interfaces and then having implementations for those. This right here is a classical approach to TDD, if I have ever seen one.

Jose Valim even mentions project boundaries and the need to define those, so I take it that in his mind, all we need to test are the boundaries, which is why we make our applications depend on interfaces (at the boundaries).

This is all fine but…

But I have an issue with this. I know some people love REPL development. I also find it fun - for toy projects. In a real enterprise system, you need a strong suite of tests that can be automatically run. REPL doesn’t cut it.

So, this leaves me with a severe deficiency - how do I test that my system is working internally as expected?
If I only test the boundaries, I have no guarantees.

A very simple example of this is using a cache. If I only test the boundaries, like Jose states, then I will never know if the answer to my query is coming from a cache or from a computation, since to the outside world, both are the same.

It also makes it impossible to test if your processes are being registered correctly, or if your GenServers are doing well instead of just dying, being restarted, and re-running the request with a clean state.

An obvious solution?

Perhaps the obvious solution here would be to just add more boundaries. Boundaries everywhere !
But this is non-sense at best. If we follow this approach we will end up with a contract for every component, because we need to test their interactions. This is crazy.

Questions

  1. So why is Elixir so focused on classical testing?
  2. How do you test the interactions within your system?
  3. If you see yourself as a mockist, which tools to you use? Do you use Mox?

First Post!

lpil

lpil

Creator of Gleam

The only thing I mock in my application is HTTP calls to external services, and that’s just so I don’t blow the quota or create lots of junk data when running unit tests. Typically I’ll also have tests that hit them for-real that are infrequently run.

I don’t really understand the purpose of mocks in dynamic languages. I think if you care about the code and you don’t have a good type system then you should run the code.

Most Liked

lpil

lpil

Creator of Gleam

I’m not a fan of either :slight_smile:

LostKobrakai

LostKobrakai

I’ve taken a bit of time and created an example repo, which includes how I would use Mox in an ideal fashion. There’s nothing used beside plain ExUnit and Mox and it has “unittest” using mocks as well as implementation tests using a global process.
https://github.com/LostKobrakai/mox_example

Last Post!

peerreynders

peerreynders

Ultimately that is an organizational issue.

Technical debt or in this case testing debt isn’t evil in itself but it has to be skillfully and effectively managed in order to maximize the benefit and minimize the risk.

In many places technical debt just happens and is ignored until it’s too late.

Where Next?

Popular in Questions Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
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
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
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
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

Other popular topics Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40165 209
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New

We're in Beta

About us Mission Statement