Does Creating a unit test for Private Functions worth it ?
Tags: dart, programming, testing
Published: 2024-02-23 19:02:24

Unit tests are quite mandatory nowadays despite of how every engineers thought about it. It could improve the confidence level of a company about their software/feature quality even though sometimes quite painful for engineers to create a good unit tests.

After working on so many projects that included unit tests inside, I literally created unit tests for any function I had created. Starting from public functions and also private functions. But not all programming language allow us to create unit test for private functions. One that I've found that we can create private function unit test is Golang, and most of other OOP language don't allow us to create unit test for private function. Recently, I questioned, why is that ? and how should we test that private function ?

## Visible For Testing
I just found out that some programming language enables us to give an annotation that tells "theres a function that exists only for testing". Which we can use to test private function in OOP language. Example : 

```
#### Dart

class GeneralUtilities {
  int res = 0;

  void foo() {
    _add(1);
  }

  void _add(int value) {
    res += value;
  }

  @visibleForTesting
  int getPreviousNumber() {
    return _getPreviousNumber();
  }

  int _getPreviousNumber() {
    return res - 1;
  }
}
```

This example above enables us to call `getPreviousNumber()` outside, but we will get a warning which said `The member 'getPreviousNumber' can only be used within '<package name>' or a test.`

Therefore, we can use this as our way to create a unit test for private function.

```
void main() {
  test('GeneralUtilities.getPreviousNumber() tests', () {
    final GeneralUtilities gu = GeneralUtilities();
    gu.foo();
    final int res = gu.getPreviousNumber();

    ## returns 0
    expect(res, 0);
  });
}
```

## But is that worth it ?
After some comparison, I would say that this is not worth it. Why ? 

1. Being in a big-scale software codebase is pretty though, we should really focus on what matters. So what really matters about all of this functions ? The most important thing is, does this utility function works as it needed or not ? Does the client who would use this function can get the right answer/data or not ? So instead of focusing ourselves on testing private functions, we should focus on testing our public function that will use our private function also. By focusing on public function unit tests, we can focus on what matters and still creating a good quality software.

2. Using @visibleForTesting would make our class dirty. Because there are some functions that exists only for testing, and that really doesn't make sense. Functions inside class should do something about that class, not fulfilling the needs for unit testing. Unit testing should be done based on the contract of that class.

3. Sometimes I feel that creating a unit test for private functions are needed when the size of a public function is very big. Lets say we had 3-5 if conditions inside a public function and each condition will call another private function. It really sucks right to create a super big unit tests for that public function ? But in my opinion, a good public function is a function that only does one thing, not many things together. So instead of thinking how we should create the unit test for that function, we should think first, does this function accept Single Responsibility Principle or not ? Does this function built in the right way ?

## Conclusion
Unit tests are needed. We should focus on what matters, instead of trying to create a unit test for private function, try to create a simple public function that calls private function which not more than 1 responsibility.