My honest opinion about Unit Testing

This is my honest opinion about Unit Testing in Software Engineering

Imagine now you are in the kitchen. You are going to make an omelet. Then, you must prepare the tools first, a stove, a pan, fried spoon, a knife etc. Then, you also must have the needs, such as eggs, pepper, salt etc.

Then, let’s make a new one. When making this new one, you must follow these steps without missing for a single thing.

  • Crack 2 eggs into a mixing bowl. Make sure the eggs are in good condition
  • Whisk the egg for 10 minutes.
  • Season with salt and pepper both with a half of teaspoon. Not more and not less
  • Put the skillet over a 60° C heat and melt the butter. Wait for 3 minutes.
  • Pour the whisked eggs into the skillet. Wait for 2 minutes.
  • Make sure whisked eggs heat up. And no liquid anymore.
  • Serve the omelet.

Then, when you start to make it, you will do this

  • Before pouring the eggs into the mixing bowl, you will crack the eggs, if you find a putrid egg, then you will choose another egg. This is an expected behavior
  • When you whisk the eggs less than 1 minute, the whisked egg will be unevenly stirred.If so, you will whisk again. This is an expected behavior
  • When you pour 2 teaspoon of salt into the whisked egg, then the eggs will be salty. If it’s too salty, then you will add another egg to reduce the saltiness. This is an expected behavior
  • When you cook the whisked egg over a 100°C- temperature pan, it will get scorched. You have to reduce the heat.

All the expected behaviors, already covered. When you do all the steps above, you have done a test for each function/steps/method/unit. So, when a simple error occurred like too many salts, we already know how to deal and handle it in our steps/function/method/unit. That’s the use of unit testing.

Covered the standard (expected) behaviour

Unit testing will guide you to the expected (standard) behavior of a function. The omelete for example, we have standard (expected) behavior to cook the eggs, you need a 60°C heat of your pan.

Okay, forget the omelet. Let say we have a simple function in Go

func Login(username, password string) error{
 if len(password) < 6 {
   return NewErrNotValidPassword
 }
 user,err:= DB.getUserFromDB(username){
 if err != nil {
    return NewErrInternalServerError
  }
  if user == nil {
    return NewErrUserNotExist
  }
  if user.Password != password {
    return NewErrWrongPassword
  }
  
  // Login Successs
  return nil
}

Then we have the unit tests here for this function *(just a sample)

func TestLoginSuccess(){
 username:="lolcats"
 password:= "youknowhoiam"
 mockDB:= new(mockDB)
 mockDB.On("getUserFromDB", username).ShouldReturn(user,nil)
 err:= Login(username,password)
 assert.NoError(err)
}
func TestPasswordNotValid(){
 username:="lolcats"
 password:= "you" // Less than 6 char
 err:= Login(username,password)
 assert.Error(err)
 assert.Equal(err , NewErrNotValidPassword)
}
func TestUserNotExist(){
 username:="tamvansek"
 password:= "youknowhoiam"
 mockDB:= new(mockDB)
 mockDB.On("getUserFromDB", username).
 ShouldReturn(nil,nil) // DB return empty
 err:= Login(username,password)
 assert.Error(err)
 assert.Equal(err , NewErrUserNotExist)
}
func TestWrongPassword(){
 username:="lolcats"
 password:= "wrongPassword"
 mockDB:= new(mockDB)
 mockDB.On("getUserFromDB", username).ShouldReturn(user,nil)
 err:= Login(username,password)
 assert.NoError(err)
 assert.Equal(err,NewErrWrongPassword)
}

If you look for the unit test, we must know for the expected behavior of every single branch. If the password is less than 6 characters, then it should be error. If your test said no error found, then there must be something wrong with your period

Add extra time to develop

extra time to develop

In creating unit testing to our function, we need more extra time. Because we must create all the test for every unit function. Because instead we just creating and thinking about the logic, we also add an extra job to create the coverage of the test. It will take even longer if using TDD approachment.

But the point is, your product has less bugs when it already released into production.

Reduce The Error/Bug in production

When you write your system without creating a unit testing, of course you can release it faster. But, later your user may find too many bugs right after using it.

Without Unit Testing

Compare it if you create the unit test

Using Unit test

When your write code without a test, then your user will find 50 bugs. It will make your users get mad, uncomfortable to your application. Compare to using test, your user will only find 10 bugs.

In the term of making the omelet. Imagine you will cook for 50 omelets with a 100-egg-budget. And from the 100 eggs, there are 1 putrid eggs. Then, you cook it without checking the quality of the eggs, you don’t do the unit test for every step. You just pour them, without covering the error/putrid eggs. And when you finish it, you delivered it to production, to your client. Got the idea how your client will be, right?

Conclusions

Unit testing is a good thing, it will increase your product quality. In my current company, when coding some of the new features, it’s required to add unit tests for each function. But sometimes, it’s too boring to do that. It’s like creating the test was a new big task to do.

One day, I’m so glad because my function is done. Well, my assumption this function will work well at that time. But even it’ll work, I still need add more test, to cover every branch in there. Then, I feel like…. “WTF. What a climax killer”. I must add the test again. Damn. So, boring.

But it’s increased my confidence to my work. I will more focus on another testing like integration testing, with the real DB, the real services.


Previously posted: https://hackernoon.com/my-honest-opinion-about-unit-testing-84eee5e893ad

Share Comments
comments powered by Disqus