Test Driven Development in PPL

Muhamad Yoga Mahendra
7 min readMar 23, 2021
www.whizlabs.com

What is Test Driven Development?

Test Driven Development is a Software Development Approach with the purpose of reducing overall errors, bugs and mistakes when developing applications/softwares. TDD Starts with designing, developing, and refactoring tests for all aspects of the software, from the smallest functionality. After the test is created, we then create implementations such that it will pass all created tests before. This forces the code to be simple, where “as long as the test passed”, the code is good enough.

Benefits of Test Driven Development

Using TDD gives out many benefits for the developers team, present and future. Some major benefits are:

  1. Less Bug
    TDD ensures that the overall bug/errors will be lower than with using other approach since the implementation is tested with many different kinds of test. It also helps with detecting and fixing bugs.
  2. Clean & Simple
    TDD implementation code is clean and simple, since it’s developed with passing the tests made in mind.
  3. Better User Acceptance
    Developers can better know what the user will do, and need so they can focus on developing tests that matches the user’s needs.
  4. Better Implementation
    In addition to point 2, TDD codes are usually more effective since after the test is passed, it’s usually got refactored to perform more effectively.

Phases in TDD

After initializing the whole project, creating branches, setting up dependency, etc. Now we’re ready to enter the TDD Cycle.

There are 3 major phase in TDD, each having their unique color to identify which phase is which. They are:

  1. Writing Testcase(Red Phase). In this phase, the tests are designed, developed, and maintained. In PPL, the commit message for this phase is [RED] message, meaning that the CI pipeline should fail since the test implementation code isn’t yet made. In the picture this step resembles the orange and red steps.
Example of [RED] Phase in PPL

2. Writing and passing Implementation(Green Phase). In this phase, the implementation code is made such that all tests in the Red phase should be passed. In PPL, the commit message for this phase is [GREEN] message, meaning that the CI pipeline should be green(success). In the picture this step resembles the bright and dark green steps.

Example of [GREEN] Phase in PPL

3. Refactoring(Refactor, Improvement and Optimization Phase). In this phase, the implementation code is further improved(increase redundancy, add documentation, optimize algorithms, etc.) without making the pipeline fail. In PPL, the commit message for this phase is [REFACTOR] message, meaning that the CI pipeline should also pass since it’s just refactoring without adding more implementation. In the picture this step resembles the blue steps.

Example of [REFACTOR] Phase in PPL

Then the cycle continues, until the software is finished. Here’s what one cycle of TDD looks like:

Note that in each Phase, there can be more than commit, but no less than 1 commit. So in a TDD Cycle, there can be a minimum of 1 Red Phase, 1 Green Phase, and 0 Refactoring Phase (Assuming the developer is good enough, such that when committing the Green Phase it’s already refactored and optimized, thus the Refactor phase is not needed and can be skipped).

Types of Tests and What’s it’s good at?

In a software, there can be more than 1 layer of programs running. Usually there’s Backend Layer and Frontend Layer. But with the current technology, where everything’s modularized and microservices becomes the new meta, new types of tests are developed to match the needs. The test types are split into Functional Testing and Non-Functional Testing.

Functional Testing

  • Unit Testing
    It’s focused on testing the smallest unit of the software, usually an individual part of a function, feature, or testing a specific part of the software. Usually a programmer will do this test both manually(when debugging, for instance) or using Unit Test automation.
  • Integration Testing
    The goal is to test a structure/components designed as a whole. The components are grouped, then tested all at once according to the software flow design. It has 2 types: Black box(for output validation), White box(verify the steps).
  • System Testing
    The test makes sure the software works on different Operating System as intended. It’s a part of black box integration tests, but focused on running on specific OS. It covers security, recovery, stress and performance testing.
  • Sanity Testing
    The goal is to determine whether the software would perform well if it’s tested with further major testing event or not. If it crash/bugs in this test, then the system/software is not stable enough for further testing.
  • Smoke Testing
    The goal is to make sure that the current software being tested is ready/stable for further testing(stress/performance testing, for example). It’s used to check whether the software can pass the initial tests(more like warmup. If it’s “catching fire/smoking” then the test fails)
  • Interface Testing
    The goal is to test whether the GUI: Works fine; Works as intended; Looks as intended; Fulfills other goal values.
  • Regression Testing
    It focuses on testing whether the software is working as intended, even if it’s modified(a module is added, for example).
  • Alpha Testing
    A type of validation testing, where the software is tested before the product is released. It’s usually done by QA.
  • Beta Testing
    Another type of validation testing, where the software is tested by limited amount of people, but it is tested in a real-time environment (or production environment).

Non-Functional Testing

  • Performance/Load Testing
    Tests the runtime performance of a software within an integrated system. It’s used to test the performance, effectiveness, memory usage, etc.
  • Stress Testing
    The goal is to check how the software will perform under stress(maximum resource reached, slow processing speed, too many requests, etc.).
  • Volume Testing
    A part of performance/load testing, but focused on the memory/data usage of the software and it’s effects on software performance.
  • Security Testing
    It’s used to test whether the software is vulnerable to hacking/exploitation or not. Threats can come from external/internal sources, and thus the software’s security system must be robust and able to secure the whole software.
  • Compatibility Testing
    Divides into Browser compatibility testing(tests the software in different browsers/web applications), Backward compatibility testing(tests the software whether it will perform better on older system/environment, and able to use resource from older software version), and Environment compatibility testing(tests the software with different dependencies, servers, hardware, and other environments)
  • Install Testing
    Tests whether the software can successfully install and run, on a default or custom installation process in different OS(also a part of System Testing).
  • Recovery Testing
    It’s goal is to check whether a software is capable of recovering from crashes/other disasters (malfunction, memory ran out, etc.).
  • Reliability Testing
    Tests whether a software is reliable, even in unfavorable environment(a part of performance/load test, stress test, and system test).
  • Usability Testing
    UI Friendliness is tested here(UI/UX test). Also checks for error reporting, and general usage of the software.

TDD Cycle in PPL

Now that we know what kind of tests out there, we can start planning our TDD Cycle.

Testing in PPL

In PPL Backend part, we mostly use Unit Test and Integration Test(No Integration test yet since the backend itself is still on progress). We didn’t use System Testing etc. because we run our software inside Docker Instances.

Some example of Unit Test:

The above function is tested by 2 UnitTest method below

Each method can have many different tests, usually testing for success and failed operations (This is called A/B Testing, or Black and White Testing, names can be different but it means the same). This is done such that we can assure that the tested method will only function as intended, and the fail testcases show that the method will fail as intended.

--

--