Sooner or later any developer faces a nasty bug, which is too hard to find. In most cases such bugs can be covered with a simple unit test, but who write tests before release?
Let’s check how it can be approached in a different way, in a world of test-driven development. How “Hello World” will look like in TDD? Code is availble on github repo.
Exampe Project
Step 0: First things first, let’s write a README
Why not sprinkle a bit of RDD on our example project.
Content of README.md
:
|
|
Step 1: Write a test first
Back to TDD, write a test before actual code. And here we are facing one of main benifits of the approach. How would one test and reuse code. In the “Hello World” example, for unit testing we should not print on the standard output, but rather return a value as string. Otherwise testing will became a bit too much envolved.
Content of hello_test.go
:
|
|
Just writing tests is not enough, let’s use them now:
|
|
Don’t worry it’s expected, we are in empty project right now.
Step 2: Make tests pass
We have a clear error message, go.mod
is missing. Create one and rerun tests:
|
|
Test fails again, but we have some progress.
Step 3: Make tests pass (again)
Error message says us that there are no implementation of Hello
function. This is time to create one.
Content of hello.go
:
|
|
Run tests:
|
|
Better now. At this point it would be a good idea to commit your changes to a repository, so we have a checkpoint.
But we are not at the point defined by our README.md
yet.
Step 4: Add a test for next piece of logic
We have covered one of possible use cases for our fancy program. But there is another one. We need to pass an argument to the function. Will start with test first (how else).
Content of hello_test.go
:
|
|
Run tests:
|
|
Step 5: Make tests pass
Again error message is concise and to the point. Update Hello
implementation to get an argument and change return value accordingly.
Content of hello.go
:
|
|
Run tests:
|
|
Nice!
Step 6: Build and Release
Reterning to our README.md
, we have covered all what was promissed. It time to build now. Wait a moment, dont we need a main
function as entrypoint? Yeap, will have one in a decicated main.go
file.
Content of main.go
:
|
|
Main is printing to standard output. We’ll test it manually for now, were are not that religious about TDD afterall.
|
|
This is a success :).
Take aways
One can notice a pattern above, and there is one:
- Write the test for specific functionality
- Do minimal changes to the code to satisfy the test
- Improve and/or refactor code
- Rinse and Repeat…
Interested in test-driven development and in Go? I would recommend to check Learn Go with Tests. This project is an example of beautiful сonvergence of tech, writing, and gophers ;)
References:
Sun Jul 30, 2023 / 827 words / Golang Programming Methodology