Test Driven Development and Continuous Integration

25 Oct 2019 |

Software Development Story

Sprint is a finite timeframe where developers need to do some works and get it done in the end of time frame. Normally, sprint lasts for two weeks. Sprint ends with a deployment of feature that has been worked out by developer and verified it is worked as intended by quality assurance engineer.

In a startup environment, we usually need to pump out new feature fast. There are customer demands that needs to fulfilled or competitor feature that we didn’t have. Two weeks sprint is used to tackle this problem. Companies with satisfied customer wins and stafisfied customer needs many feature that they didn’t even know that hey needs it.

So basically, we have two weeks (10 work days) to pump out new feature that works – and won’t break – to stay in competition. How we make sure everything worked smoothly when our system change quickly?

Developer develop something called unit test. It is a piece of program that verify another program works as intended. Let’s say we want to create cart feature. In this feature, customer could mark which item they want to buy.
We can create a program that verifies if a person click/tap buy this button, item will be stored in a table called carts. After automatic click buy this button, the program will query database and check whether the item exist in cart or not. We create such program for every feature we create, ideally. Unfortunately, we deal with not-so-ideal condition which we will discuss later.

Why Test Driven Development

There are many software development practice. We think there is no such silver bullet practice that will solve all sofware developing problem. We need to search one that fit company situation and manpower we have. For this artice, we will focused on Test Driven Development (TDD).

TDD can summed up with three sentence. Create test unit for feature that we want to create which will fail because we haven’t developed it yet. We create our feature that should pass the test. We test our new feature with test we create before we create feature; unless it pass, it shouldm’t be deployed.

There are many interpretation of TDD but can be summarised with sentence above

TDD make sure every feature we create have a test unit. Therefore we have pre-condition and post-condition of feature. Test unit also act as a documentation for the feature for future software engineer (or future you that already forget what have you done) as long as they could read the code.

The downside of TDD is the test is as good as software engineer ability to understand the product story. Low ability to understand the product story or specification will lead to poor test unit. For example, test unit does not check certain things that crucial for product. Other downside is the one who create test unit is the one who make program to pass the test. Developer could make a test unit that test trivial things so it could pass test unit. Workaround for this problem is to make sure that every feature and test unit have a code review by another developer. Lastly, create test unit takes time. Remember that developer only have 10 work days to complete a feature(s)? Those time is also slashed by time that needed to QA check (which also need time).

Is TDD benefit outweigh its downside, in our opinion is it depends. TDD relies on good product managers who could describe what product they want to roll out. A good developer that could transform product story to a technical implementation, able to estimate their workload, and create a good test unit.

TDD also need a good code reviewer that could spot an unrepresentative test unit and bad codes (in my experience it is included in a developer task). Last but not least, TDD needs a QA engineer that test not only what written in test, but also many possibilites of features usage when s/he found one, reports it to developer.

Test Driven Development and Feature Documentation

Many developers said that a good code should document itself. We agree with this statement in some extent. While it is a good aim, it is kind of hard to achieve. First, every developer have different level of understandings and different rate of learning.

A code written by smart developer might become unreadable or need more time to understand by their less smart peers. One developer maybe understand the whole business logic and code properties just by looking at code where as his/her peer need to write down or sketch the program flow based on what s/he reads.

That’s why code need some standardization and documentation which i wrote a post about it. So where TDD involvement in documentation? In the test unit.

When codebase grow larger, we need to know a function works properly. Measurement of proper can be done by unit testing. What are the input, whant kind of error that the function/feature will emit, what are the consequences of running the function. Junior dev who never read the feature only need to read the test unit to grasp features capability and requirements. A good test cover common – ideally all possibilities – that could happen to the feature.

Combine continuous Integration and TDD

Back to the topic of two weeks deployment process, we need to deploy new feature without breaking whole system. That’s where TDD comes in. In such a short time, we need to verify that none of our system breaks when new features implemented. We need to create such TDD integration system that we can sure when all test passed, the system won’t break. This rely heavily on how good the test is. It is also one of the measurement whether a test is representative or not.

Test Failure and Confidence

As we state in previous paragraph, TDD makes us confident that we are ready to deploy and it won’t break in front of our user. Before QA process, we need to make sure all feature is created using TDD process. We create the test first, make sure it will break. Then we create features that will pass the test we just created and all previous test. So it is okay if the test failed, unless it failed before feature deployment.

Deployment confidence comes at a price of many passed test unit. This not only we have more confidence but also able to pin point the problem in case there are some breaks in production enviroment. If we does not have test unit, we need to create pre-condition of feature and post-condition and replicate the failure in non-production enviroment. This takes time and feature knowledge whereas in a test unit, we already provide the pre-condition and post-condition and a failure is caused by possibility that we didn’t consider it before. We just add more pre-condition that we don’t consider before – not create it from scracth. This will save time and make sure same mistake won’t be repeated – unless we let the test didn’t pass.

Type of Test

There are three types of software development test, test unit, integration test, and end-to-end test. All of them important but in different ways. Test unit only guarantee that a feature will work but only for that feature only – such as send password to an email. Integration testing guarantee that multiple feature could work together to achieve a goal – such as forgot password. Lastly, end-to-end testing guarantee that series of an action – such as registration – works properly.

Naural question that comes to mind is can we just write end-to-end testing and ignore the rest? The answer is, yes you could, but remember you only have less than one weeks to write such test. Sometimes integration or even unit test is sufficient to ensure out system won’t break when new features deployed. End-to-end testing only needed in crucial part of our service. For example, if we run a eCommerce site, we need to make sure our buying mechanism won’t break. Starts from picking item, checking out cart, and payment. End-to-end testing make sure that every of this crucial parts works properly.

Closing Statement; Scaling Argument for TDD

Startup loves scaling so much. Several companies called it growth. TDD and CI have an important role in companies quest for growth. In short, TDD and CI ensure that companies will pump out new features with confidence. It also let developer focus on creatin tests and features instead of fixing bugs in production environment. Every new features can integrate flawlessly with system is every developer, QA engineer, and project manager dream.

That’s all for now. Hope you learn something new!