DEV Community

Arthur Lee Ying Kiu
Arthur Lee Ying Kiu

Posted on

Introduction to stubbing and test driven development

Introduction

Suppose you are new to software engineering and wish to dip your toes into software testing. You've implemented the backend lofic of the feature, which also ties to external services and want to test it by writing your test code. You realise after writing a bunch of test code that your feature's core logic does not work and you're not sure whether it's from the logic you wrote or whether the external services that were called failed instead. You scratch your head and realise it's going to be a tough road ahead.

What can be done differently? What if you wrote your tests before writing your core logic? What if you can abstract the calls to external apis and just focus on checking the core logic you wrote? Well, this can be solved with test driven development as well as stubs. Let me explain what both of these concepts are in detail.

What is test driven development?

Test Driven Development (TDD) is a software development approach in which test cases are developed to specify and validate what the code will do. This means that test cases for the functionality is written first before the functionality itself is written to pass the tests. It's key methodology is called "Red, Green, Refactor", which are the 3 phases in TDD.

Overview of the 3 phases
Overview of the 3 phases

Red

The first phase is writing a test before the functionality. Normally this means writing a test for the happy flow of the functionality. However, as the core logic was not written yet, this test is supposed to fail. This is symbolised by the color red.

Green

Now that you have a failing test case, you can focus on getting it to pass. This means implementing your core logic with the singular of focus of passing the test, so disregarding code cleaniness is okay at this juncture. After implementing the code, run the previously written test. If it still fails, determine whether it's the code or the test that is wrong. Subsequently edit your core logic or test code until it passes. This allows you to validate early on in the development process whether the code written works. This phase is symbolised by the color green.

Refactor

You have a passing test now, congratulations! Now before you create a pull request, make sure to refactor the code such that it is clean and neat, removing any additional console logs and unnecessary comments.

This process can be repeated until all the edge cases for a feature is accounted for and ensures that your feature is well implemented and tested.

What is stubbing

Now that you undestand the philosophy of TDD, a new question the arises is what if the feature being implemented utilises external APIs? Calling the external API in the test environment, would introduce additional factors that make the test fail such as whether there is a network connectivity issue when calling the external API. This makes it harder to find out which part, ie your code or the external API call, is causing the test to fail.

Therefore Stubs come into the picture. It is a function or object that replaces the actual behaviour of a module, in the previous call your external API call, with a fixed response. The stub returns the fixed response that you programmed. Therefore stubs are useful in integration tests where it can mock behaviour with other modules or components, as well as mocking the result when calling external APIs. This reduces additional dependencies that make the test fail and allows you to focus on the core logic being written instead

Real life applications of stubbing in NodeJS environments.

During a previous software engineering internship, I was working on a NodeJS backend and had to write integration tests. We used mocha and chai as our Javascript test framework. However, there were times where we used external systems such as firebase or other external APIs in our backend logic. To mock that we used SinonJS and essentially verify whether specific functions are called, whether errors are thrown as well as what they resolve to.

Conclusion

We have gone through a quick introduction on what TDD and stubbing is. I hope this article helps to demystify the 2 concepts and helps you progress in your software engineering journey.

References

Here are some articles I read and referred to while writing this post, feel free to read more and further expand your knowledge!

Top comments (2)

Collapse
 
rogerlys profile image
Roger Lim Yong Siang

I have always believed that testing code is very important as it allows us to catch bugs from production code. This would give developers the confidence needed in production and deployment. I felt that your article introduced test driven development and stubs in a succinct yet insightful manner. I feel that stubs are a very relevant topic when discussing test driven development as it there is a focus on unit tests.

Test driven development (TDD) is just one of the methods that we can use to develop. TDD is inspired by the agile manifesto and extreme programming where the iterative approach to software development is favoured. This would imply that the 3 phases highlighted in this post would be repeated many times until the product is finished. TDD would fit nicely into agile development as it constantly requires and benefits from feedback about the software being developed. Some benefits of TDD would include early bug catching. TDD would also give developer the confidence to change code when needed. This is because the test code that is written in the red phase can be used to ensure that the component can still meet the requirement even after the change. This is known as regression testing where testing is done to ensure that change in software does not impact previously implemented functionalities.

To add on to your point on the green phase of TDD, it should be noted that minimal amount of code should be written to try pass the newly added test cases. This would link back to the YAGNI (You Aren’t Gonna Need It) principle where it is advised to only develop what is required at that moment.

Despite all the benefits to TDD, it does have it shortcoming as it often would slow down production of code. This is due to the overhead associated with constantly writing test code. In software development, requirements can change over time making certain prior test cases irrelevant. This may cause slowdown in production as developers would have to divert time and attention to fixing and maintaining prior test cases.

To add on to your point on stubs, I believe that stubs would be used the most in unit testing as it allows the developer to eliminate dependencies among components. This would allow members to develop and test code in parallel. Stub would be especially important for testing when performing TDD as test code would have to be written before the other component are fully developed. Like you mention, stub would allow the user to focus on the individual component that is being tested as dependencies are removed. Some tools that can be used for unit testing would be Junit for Java, typeMock for C++ and as mentioned in the article mocha for Javascript. Personally, I feel that stubs would be more applicable in unit testing rather than integration testing. Because the purpose of integration testing is to ensure that different component work together as expected. Hence using stubs in integration testing would not be as beneficial as we should be using the actual component rather than stubs.

Overall, I would say that the article can give beginners a quick summary of the benefits of TDD and stubs. Personally, I feel that it would be very beneficial if some concrete examples were given to give readers something to follow. For example, it would be beneficial if we were given some example test cases that utilise stubs. This can provide beginners with an example to follow when writing test code.

Collapse
 
galvinleow profile image
Galvin Leow Wen Yuan

I have enjoyed the article that you have written as the title was fitting of the content and the content was presented in a simple to understand manner.
I felt that the overview of test-driven development was well written. The diagram together with the explanation of red, green, and blue arrows gave me a better view of how test-driven development is done. The red arrow indicates the starts which is the development of test codes, followed by the green arrow that indicated the development of the feature with the successful factor being passing of the test created for it and lastly the blue arrow is refactoring which is the clean up of code to maintain code quality.
I also liked that the article touches on testing when using an external API, this situation is common in the development of code in the real world. From the article, I learned that we could use stubs to mock the result of calling an external API. I also learned that SinonJS can be used to create fakes (Fakes are alternatives to the Stubs and Spies, and they can fully replace all such use cases).
Companies like IBM also have teams that use test-driven development, and the results were surprising. They found that the team that used test-driven development had more solid code than others in some cases.
I have some suggestions that you could add to your article since it is an introduction to test-driven development. People that are new to test-driven development will not only be interested in the benefits of this method but also some potential pitfalls. You could mention some of the critical pitfalls of this method like writing tests that are too large or coarse-grained which would lead to poor maintenance of test code in the future or even writing overly trivial tests that not only did not test the feature code properly but also taking time away from developers to develop more impactful codes.
There are some of the reasons why companies are not taking TDD as the standard of development. The main reason I assume would be the cost. The cost of functionality will increase as resources would be poured to develop test code, the cost of code maintenance will increase, and test code increase linearly with production code and TDD might cause the code to be more complicated than it needs to be making developers spending more time to understand the code. These reasons could be added to the articles as well.
Overall, I felt the article is a good start to knowing what is test-driven development all about.