Skip to main content

2 posts tagged with "testing"

View All Tags

Integration Testing with Github Actions

· 2 min read

Integration testing is another layer of testing after unit testing. It groups multiple modules together and applies functional tests to those groups. In the scope of a backend service, it could be testing your module against a database or an external service. In this post, we'll go through setting integration testing with Go, PostgreSQL, Flyway, Github Actions.

Let's start with this sample Go app. It includes Test_LoadDataFromDB to test the function LoadDataFromDB which has interactions with a PostgreSQL database. And looking at goapp_integration_test.go, you may notice these go:build lines:

//go:build integration
// +build integration

They are added so these tests will only run with a specific build tag:

go test -tags=integration

It'll help to separate integration tests from unit tests so you'll only run them for specific occasions.

The next step is to create a PostgreSQL service in our CI via service containers by adding these lines:

services:
postgres:
image: postgres:13
env:
# Provide the password for postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

If you need to set up the database before your integration tests, you could use flyway to run the migration script. And luckily, there is a Github action for that:

- uses: joshuaavalon/flyway-action@v1
with:
url: jdbc:postgresql://postgres:5432/postgres
user: postgres
password: postgres
locations: filesystem:./migration/sql

In the above config, ./migration/sql is the path to migration SQL scripts.

Finally, you can just add the go test command to run integration tests. It will also run unit tests so no need to have a separate step for that:

- name: Run Tests
run: |
go test -v ./... -tags=integration

The work could be found in this repository. Although this is just a simplified version, you can just add more docker containers into your CI if your system is more complicated.

Some thoughts on writing tests

· 2 min read

It isn't difficult to realise that testing in general and unit tests are important. It ensures your code work as expected and it guarantees that your code won't be broken in the future. If it's so important, let's write as many tests as possible. If we're able to cover all scenarios, our software will be perfect and there'll be no bug.

Well, tests don't come free. It needs time and effort to write good tests. But why do we need good tests? When we write software, we rely on tests to make sure of the correctness. But how can we make sure of the correctness of our tests? We can't just write tests for our tests. Therefore, we need to make sure tests are easy to read and easy to understand. It should be so simple that it's hard to make mistakes.

Maintaining is another problem. Like software, we don't write tests and leave them there untouched forever. Tests should be maintainable so they always work correctly to verify your code. Maintaining tests are probably more important as they are prone to break than your software. Therefore, when writing tests, we shouldn't have it in mind that we only write the test once. Believe me, it'll backfire very soon.

Writing good tests is difficult and maintaining them isn't easy. That's why I always believe that we should have a balance of the number of tests. We should have enough tests that cover the most important logic branches. We shouldn't have too many tests that become a burden. When you find that you spend more time maintaining your tests than maintain your software, then you probably have too many tests.