{Code, Architecture}

Category: Clean Code

Integration Tests VS Unit Tests

Many people ask me about this comparison and even about the proportion of each type of tests.

I faced several situations when I needed to evaluation the best approach and of course is not like black and white situation, but I personally defend that should always favor the Unit Tests.

I compiled a comparison table about the two types of tests to help us to brainstorming about it.

Integration Tests VS Unit Tests

Integration TestUnit Test
Difficult to maintainEasy to maintain
Usually don´t test every possible pathUsually test every method parameters combinations and paths
Difficult troubleshooting (many objects, many layers, many external resources are involved)Straightforward to identity the problem and to fix (test of single unit of code)
Can take long time to executeIs fast to execute
Parallel execution could causes problemsAre executed in parallel with no problems (if well done)
Can be executed against any kind of implementationForce us to improve the code to make it testable.
Complex to setupEasy to setup
Can give false-positive result (since it’s a black box test we can get correct result without knowing exactly how this result was generated – could be fixed or manipulated data i.e)We are testing a small piece of code and we can perform multiple types of validation not only against the result but how it’s generated

So why/when we need Integration Tests

Have more and good unit tests will ensure more product quality

So why we need and why we have Integration Tests

The integration test provide us a test of integration parts like:

  • contracts
  • connections (databases, caching system, message queue…)
  • application bootstrap
  • infrastructure aspects (protocols, access control, authentication…)

How many integration tests we need to test this “integrations”?

Just a few tests. Not for all functionalities or use cases.

That’s why we should have much more unit tests (good tests with high code coverage)

Code Smells: Primitive Obsession

What is, why is bad and how to prevent

The Code Smells, a symptom of our weakness. Seems to be faster than do the good option, but as always, the bad code slow down the team and makes we going slower.

How to know if you are creating a Primitive Obsession Code Smell?

  • A primitive should never travel “naked” around the code.

When I say “naked” I mean: alone, opened, outside a class

Even for the most simple code or method we may think that would not be a problem to have this “data” traveling. But “the problem we don’t see today probably we will face tomorrow”

On this code, for instance, I decide to receive a Phone Number through a primitive variable as a parameter:

void AddPhone(string phoneNumber)
{
     //adding phone
}

We can predict a many of problems from this code as:

  • How we can insure that the phone number is valid?
  • What if our system works with multiple countries with different phone numbers formats?
  • What if we need to add more related information like zone code, country code and so on?
  • What if our system need to validate that phone number is mandatory?
  • What if we need to control phone types?

Primitive constants to control information is another case:

const int PHONE_TYPE_CELLPHONE = 1;
const int PHONE_TYPE_HOME = 1;

void AddPhone(string phoneNumber, int phoneType)
{
     //validating by phone type
     //adding phone
}

What is the problem?

The most important issues are about Consistency and Scalability. Why?

  • If we use primitives and need consistency, we’ll need to add validations all over the place to guarantee that the data is correct all the time
  • If we have more than one related data (like phoneNumber and phoneType) the consistency will be much more difficult to achieve (see Data Clumps code smell)
  • Using primitives we can’t scale, won’t be easy to add new features, validations or data.
  • Probably use primitives will drive us to add more and more

Reasoning

There is no problem at all by creating a small class, even with just one attribute, property or field. This will allow you to scale, reuse and keep your software good inside.

If we model the system using objects from beginning the cost will be minimal and we’ll have a scalable, consistent and healthy software.