Micro TDD, It’s Hard, But It’s Worth It!

Microservices drive us to rethink in our TDD approach, and this is why we called it “Micro TDD”.

Mohammed S. Shurrab
Digital Cloud
3 min readDec 11, 2018

--

I am in love with TDD Laravel for more than two years. During this period, I was amazed at how Laravel help makes it pretty easy to test very advanced topics.

For now-Laravel developers, this code: migrates a fresh database, fake Passport OAuth 2.0 server, authentication of a user generated by the factory, send a PUT request to update the profile, assert the response status, assert the JSON structure, and assert the sending of a notification to the user!

If you follow the top-down approach, you will start with a Feature test like this one, and you may occasionally write some Unit tests for more complicated logic. We successfully used this approach for many projects, until we decided to use the Microservices approach in one of them.

Yes! Microservices drive us to rethink in our TDD approach, and this is why we called it “Micro TDD”. The approach does not require you to use Microservices; it merely makes your code more modular, decoupled, and easier to maintain. As a side effect, the test suite will be more organized, descriptive and faster!

The Problem!

Let us review the previous Feature test again. We will refer to it as “Monolithic test” because of the following:

  1. We migrate the full database to test the profile update feature.
  2. Both “notification_settings” and “events_count” appear in the user resource while they belong to other modules.
  3. We use the database assertions to ensure that the name is changed nested of test the JSON returned data.
  4. We test if the notification is sent to the right user.

Noted why we call it “Monolithic”? The centric database, modules coupling, and dependent on a one-shot Feature test. These characteristics are quite similar to the Monolithic App. Therefore, we decided to try another approach derived from the Microservices patterns.

The Biggest Failure

The first step we take is to remove the Global migration and seeding codes, and use clear in test setup phase. The new test class will look like:

Nested of seeding the data globally in the base test class setup, we use the seed helper function to run the “MaritalStatusesSeeder” while it’s a part of the user module, and we use custom migrate helper to migrate only the tables related to the current test, in our case the user related tables.

As you can see in DATABASE_MIGRATIONS_USER, we restructure the database migrations folder and group each set of migrations as folder per module.

Almost every test case in a suite of ~1k test cases failed, just because not all tables –even from unexpected modules- exist. We try to investigate where these couplings live, and we are amazed that we have coupled Tests, Controllers, Models, Form Requests, Middleware, API Resources, Jobs, And even Migrations files!

Absolutely, it is not the Framework problem, nor a Monolithic app requirement to couple your app like this, but let us face the fact, you cannot develop a big project without end with these problems, and we need a way to force that decoupling. Remove the usage of full Database Migration is the first step in this journey.

The most confusing yet simple coupling is the migrations, how migrate a table can cause coupling between modules in the first place?

Oh, my foreign! We cannot migrate the event module unless we migrate user module first, and this is not the case in Microservices world. Therefore, we decide to disable any cross modules foreign keys. You can do that using two approaches:

  1. Remove the foreign keys entirely and think about modules tables as they deploy in different databases like a real Microservices.
  2. Keep them and use “enable/disableForeignKeyConstraints” helpers from Laravel Schema façade.

In the next articles, we will dive deep into other types of coupling, and how can Laravel help us deal with some of them. We also developed some custom solutions to solve more complicated problems, and we will share them as snippets or open source packages with each article.

Stay tuned!

--

--

Mohammed S. Shurrab
Digital Cloud

Chief Technology Officer at Digital Cloud, Lead at Facebook Developer Circle