This article is a part of our DevOps blog series inspired by our DevOps bootcamp live streams available to watch on our YouTube channel.
As a developer constantly working with code, it’s only natural to feel the need to test your code frequently.
Testing helps detect bugs and protect against any of the same in the future. In this article, we will understand what testing means in the concept of DevOps, and we will also see a tutorial that will give us an idea of how testing an application takes place.
Without any further ado, let's start!
Introduction to DevOps
We know that DevOps is not only a practice, but it is a culture in itself. In this culture, testing is an integral part of the process. It is essential to remember that the building phase of an application comes after planning and coding - the writing of the program itself.
During the building phase, you need to test your code to avoid any errors during the deployment phase and minimise any bugs once the application is in use. We also refer to the building phase as the Continuous Integration phase. It consists of building the code and involves unit tests, integration tests, code reviews, and packaging.
Let's look at Continuous Integration, which is often shortened to CI.
What is Continuous Integration?
In simple terms, we can define Continuous Integration as a series of events in a DevOps lifecycle that includes integrating small changes in the code, testing the code every time these changes get committed.
Continuous Integration also means building the application anew with every commit or merge of code to the main branch. This means that the application is always in a deployable state.
To have a successful integration and deployment, we need to extend the tests in such a way so that the deliverables will be compatible, secure, and work with all the bits of the application if using a microservices architecture.
This process is managed through Continuous Integration (CI) pipelines. A pipeline contains all required tasks to run automated tests and integrations, along with compilation and release of the deployed application.
Many tools and services offer this, such as Jenkins, Travis CI, Gitlab CI/CD, Circle CI, etc.
Getting started with testing
In this section, we will cover running tests on code written in Go, but you can try it out with any programming language of your choice. We will be using Github Actions for our tests. Let's begin!
Before heading on to the main part, we have to complete a few prerequisites.
To follow along with this guide, you have to install Go and Git on your local machine. You can install Go by clicking here and Git by clicking here. Next, if you don't have a Github account, create one by clicking here. Also, check out this video for an idea about Git and GitHub.
Creating the test script
Firstly, create a repository in GitHub with a name of your choice. Then, click on the Actions tab.
Next, click on the link with the name "set up a workflow yourself". After that, replace the default script of the main.yml file with the script given below
on: [push, pull_request]
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.15.x, 1.16.x, 1.17.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Test
run: go test ./...
The script shows that the test will be run for three major operating systems (Ubuntu Linux, macOS and Windows) to see if the code is compatible. Also, we can see the mentioning of the different versions of the Go language. In the end, we can see the command which we will use to run the test in a terminal as part of our pipeline.
Building and testing the functions with Go
Before moving on with creating the functions, firstly, you have to clone the repository you created on your local machine. Use the below command in your terminal to clone:
git clone <repository url>
Replace
Next, we will create a Go module file in the cloned folder. For that, use the following command:
cd <folder name>
go mod init <repository path>
Remember, the repository path is the same as your repository URL but without the "https://". After that, we will create one addition and multiplication function in the same folder. Create a file with the name "main.go" and add the following:
package main
func main() {
println(add(100,100))
}
func add(n, add int) int {
return n+add
}
func multiply(n, multiplyBy int) int {
result := n
for i := 1; i < multiplyBy; i++ {
result = add(result, n)
}
return result
}
Next, we will create the test functions for both addition and multiplication functions. You can see from the above code that both the functions are interdependent, which means if one of the tests fails, all the tests will subsequently fail.
For the test functions, create the file "main_test.go" and add the following code to it:
package main
import "testing"
func Test_add(t *testing.T) {
start, plus := 10, 10
want := start + plus
got := add(start, plus)
if want != got {
t.Fatalf("wanted %d, got %d", want, got)
}
}
func Test_multiply(t *testing.T) {
start, times:= 10, 10
want := start * times
got := multiply(start, times)
if want != got {
t.Fatalf("wanted %d, got %d", want, got)
}
}
Now that you are done with the code, it's time to test the code in the terminal. Remember the command we had described in the test script. It's time to implement that.
go test ./…
If you receive OK as the output, it will determine that your test has been successful.
Committing and running a test in GitHub
Now, it's time to commit the three files into the main GitHub repository. For that, run the following commands:
git add go.mod main.go main_test.go
git commit -s -m “Add 3 files”
git push
Now, if you go back to your GitHub repository and refresh the page, you will see that the three files have been committed to the main repository. Next, click on the Actions tab, and you will see that several tests are running. After some time, if you see all green checks beside the jobs with the overall status indicating "success", your code has passed the test.
Congratulations! You’ve just built your first continuous integration pipeline! While this example is straightforward, the main principles are the same as in any application: tests are defined by the developers to prove the code is doing what it is intended to do, which is verified by the pipeline as part of the building process. This process runs automatically as part of any commits to the repository’s main branch. If the tests do not pass successfully, a new version of the application is not built or deployed. This means that we can be more confident in any code that gets deployed.
In conclusion
Throughout the article, we have learned how we can set up a CI pipeline and run tests with the help of it. I know this is exciting stuff, and you are eager to test it out. So get your hands dirty, and I will see you in the next one.