Unit Testing, TDD and Test Driven Development in Golang
Reading Time: 9 Minutes
Overview
With the evolutionary growth of software development process, Test Driven Development is an approach which consolidates test first driven methodology and refactoring.
This approach is based on the principle that we should write small codes rather than writing long codes. In TDD, whenever we want to add more functionality in our codes, we first have to write a test for that. After that, we add new functionality with small code lines combined and then test it with our test. This approach helps us to reduce the risk of encountering significant problems at the production level.
Unit Testing in Software Testing
Unit testing operates on a low level and is tightly coupled with source code. In the best of worlds, one unit test always correlates to one minimal piece of functionality. These functionalities are independent of the other components of the code.
Integration Testing in Software Testing
Integration testing validates that software components work correctly when combined with each other. Only the interfaces between components are tested and it is assumed that each component has been individually unit tested.
What is Test Driven Development (TDD)?
Test Driven Development is a software development approach where developers write test cases for enhancements or new features before we write any code. The basic approach with TDD is that you begin with writing any code. The basic premise of TDD is that you begin with writing a failing test for the piece of code that we want to implement. Then you write the most straightforward possible code to pass that test, once it is done the new code is reworked or refactored as it is better known to ensure that it meets required.
TDD = Refactoring + TFD
Test Driven Development Workflow
Test Driven Development promotes the idea of each test case testing one piece of functionality. The workflow of Test Driven Development is as follows -
-
Write a concise, minimal test for a new piece of functionality. This test will fail since the functionality isn’t implemented yet (if it passes one knows that the functionality either already exists or that the test isn’t designed correctly).
-
Implement the new functionality and run all tests, both the new and pre-existing ones. Repeat until all tests pass.
-
Clean up the code and ensure that all the tests still pass, then return to step 1.
Test First Programming Concept
-
For this programming approach we write the tests before programming and during testing for functionality, all these test cases are run whenever we test the functionality.
-
For test first programming we can also say that we are going to write the automated test cases before the functionality and the developer has to write the test case to satisfy these tests cases.
You May also Love to Read Test Driven Development and Behavior Driven Development in Python
Feature Code in Test Driven Development (TDD)
The practice of first writing a (failing) test prior to writing the code for a feature. Feature code is refined until it passes tests(s).
-
Firstly when we go to design or implement a new feature we check whether an existing design is the best design which will help us to implement a new functionality.
-
If the above condition satisfies then we follow the TFD approach for the implementation of new functionality.
If the above condition is not satisfied, then it allows us to change the portion of design affected by new functionality and allows us to add new features very easily.
4 Advantages of Test Driven Development (TDD)
-
Ensures quality - It helps in ensuring the quality by focusing on requirements before writing the code.
-
Keeps code neat and tidy - It assists in keeping the code clear, simple and testable by bringing it down into small achievable steps.
-
Maintains Documentation - It provides documentation about how the system works for anyone coming onto the team later.
-
Repeatable Test and rapid change - It builds a suite of repeatable regression test and it acts as an enabler for rapid change.
Test Driven Development (TDD) Process Cycle
-
Firstly we write the test cases.
-
Then we run the test cases with functionality.
-
Next, changes are made to the functionality if the test is not satisfied.
-
The whole process written above is then repeated until the test cases are not satisfied by functionality.
Acceptance Test Driven Development (ATDD)
ATDD is short for Acceptance Test Driven Development. In this process, a user, business manager, and developer, all are involved. First, they discuss what the user wants in his product, then business manager creates sprint stories for the developer. After that, the developer writes tests before starting the projects and then starts coding for their product.
Every product/software is divided into small modules, so the developer codes for the very first module then test it and sees it getting failed. If the test passes and the code are working as per user requirements, it is moved to the next user story; otherwise, some changes are made in coding or program to make the test pass.
This process is called Acceptance Test Driven Development.
Behavior Driven Development (BDD)
Behavior Driven testing is similar to Test Driven Development, in the way that in BDD also tests are written first and tested and then more code is added to it to make the test pass. The major area where these two differ is that tests in BDD are written in plain descriptive English type grammar. Tests in BDD aim at explaining the behavior of the application and are also more user-focused. These tests use examples to clarify the user requirements in a better way.
4 Benefits of Behavior Driven Development (BDD)
-
The major change is in the thought process which is to be shifted from analyzing in tests to analyzing in behavior.
-
Ubiquitous language is used, hence it is easy to be explained.
-
BDD approach is driven by business value.
-
It can be seen as an extension to TDD, it uses natural language which is easy to understand by non-technical stakeholders also.
You May also Love to Read Test Driven Development and Behavior Driven Development in Scala
Behavior Driven Development (BDD) Approach
We believe that the role of testing and test automation TDD(Test Driven Development) is essential to the success of any BDD initiative. Testers have to write tests that validate the behavior of the product or system being generated. The test results formed are more readable by the non-technical user as well. For Behavior Driven Development to be successful, it becomes crucial to classify and verify only those behaviors that give directly to business outcomes.
Developer in the BDD environment has to identify what program to test and what not to test and to understand why the test failed. Much like Test Driven Development, BDD also recommends that tests should be written first and should describe the functionalities of the product that can be suited to the requirements.
Behavior Driven Development helps greatly when building detailed automated unit tests because it focuses on testing behavior instead of testing implementation. The developer thus has to focus on writing test cases keeping the synopsis rather than code implementation in mind. By doing this, even when the requirements change, the developer does not have to change the test, input, and output to support it. That makes unit testing automation much faster and more reliable.
Though BDD has its own sets of advantages, it can sometimes fall prey to reductions. Development teams and Tester, therefore, need to accept that while failing a test is a guarantee that the product is not ready to be delivered to the client, passing a test also does not mean that the product is ready for launch. It will be closed when development, testing, and business teams will give updates and progress report on time. Since the testing efforts are moved more towards automation and cover all business features and use cases, this framework ensures a high defect detection rate due to higher test coverage, faster changes, and timely releases.
4 Advantages of Behavior Driven Development (BDD)
It is highly suggested for teams and developers to adopt BDD because of several reasons, some of them are listed below:
-
BDD provides a very accurate guidance on how to be organizing communication between all the stakeholders of a project, may it be technical or non-technical.
-
BDD enables early testing in the development process, early testing means lesser bugs later.
-
By using a language that is understood by all, rather than a programming language, a better visibility of the project is achieved.
-
The developers feel more confident about their code and that it won’t break which ensures better predictability.
Test Driven Development (TDD) with Golang
Golang is a programming language which combines both object-oriented and functional programming paradigms. Considering functional aspects of Golang we can define functions to be of two types -
-
Functions that perform computation and no I/O operations -
-
In general, a developer must focus on writing functions which are free of side effects.
-
If the function does have side effects, those should not affect the results of subsequent tests.
-
-
Functions that perform I/O operations and no computation -
-
If a function performs less computation and more IO operations, one must consider specific testing frameworks for writing a test for such functions. For example, there is no need to use GolangTest (a popular testing framework) for such functions.
-
In Golang, test resides in project source but separated from the application code. There are many testing frameworks available with a lot of features, one can choose according to the specifications in the framework. We will consider Golang Test, a popular testing framework, in this document.
You May also Love to Read Understanding Dependency Management and Package Management in Golang
Golang Testing for Test Driven Development using Package Testing
Package Testing provides support for automated testing of Go packages. It is intended to be used in concert with the “go test” command, which automates the execution of any function of the form.
func TestXxx(*testing.T)
Setting Up Environment For Test Driven Development (TDD)
Perform the following steps -
-
Setup directory structure of your project as given below -
< GOPATH >
| --src | -- < Project Name >
| --main.go | --main_test.go | --src | -- < pkg 1 >
| | --file1.go | | --file1_test.go | …
| -- < pkg 2 >
Write test function as given below -
-
func TestXxx(*testing.T)
Implementing Test Driven Development (TDD) in Golang
-
Write a test using Golang testing package -
package main
import "testing"
func TestSum(t * testing.T) {
total: = Sum(5.5, 5)
if total != 10.5 {
t.Errorf("Sum was incorrect, got: %f, want: %f.", total, 10.5)
}
}
-
Write just enough code to fail the test.
package main
func Sum(x int, y int) int {
return x + y
}
func main() {
Sum(5.5, 5)
}
-
Execute the following command in the project structure -
-
go test
-
Output -
vikash@dm04:~/Desktop/f1$ go test
# _/home/vikash/Desktop/f1
./sum_test.go:6: constant 5.5 truncated to integer
./sum_test.go:7: constant 10.5 truncated to integer
FAIL _/home/vikash/Desktop/f1 [build failed]
-
Refactor the code
package main
func Sum(x float64, y float64) float64 {
return x + y
}
func main() {
Sum(5.5, 5)
}
-
Execute go run
Output -
vikash@dm04:~/Desktop/f1$ go test
PASS
ok _/home/vikash/Desktop/f1 0.001s
Summary
Test-driven development(TDD) is a development technique where the developer must first write a test that fails before writing a new functional code. TDD ensures a proven way for effective unit testing, however, it does not replace traditional testing. We believe that TDD is an incredible practice that all software developers should consider during the development process.
How Can Don Help You?
Don follows the Test Driven Development Approach in the development of Enterprise level Applications following Agile Scrum Methodology.
Golang For Big Data
Data is growing at an exponential rate and its getting difficult to decipher information from such large amount of data. Golang coupled with Docker helps in creating high-performance computational environment for handling large data streams. Get Real-Time Analytics on live streaming data with Don's Big Data Analytics Solutions using Golang and Apache Hadoop.
Microservices & Restful API Development
Take a cloud-native approach to building Enterprise Applications for Web and Mobile with a Microservices Architecture. Run each service inside a container and combine all those containers to form a complex Microservices Application. Restful API Development with Golang offers more flexibility and control over the applications being deployed on leading Cloud Service Providers like AWS, Microsoft Azure, Google Cloud or on Container environment - Docker and Kubenetes.