Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 3, 2021 08:09 pm GMT

how to use build tags to control GO testing with a GitLab CI use case

abstract

The importance of testing code in programming is undoubtedly a fact. There cannot be good quality development without proper testing coverage. Sometimes, however, it is necessary to distinguish the tests or even launch them grouped together rather than all at once. This is the purpose of these few lines: present a valid solution for GO developers who wants to run their tests separately.

The use case I prepared involves a dummy GO project with test files. It has been pushed on a GitLab repository to run the Continuous Integration, while diversifying tests. This is the link to inspect the solution directly on GitLab.

prerequisites

  • basic knowledge of GO programming and testing
  • basic knowledge of the GitLab-CI

the GO project

Let's start our tour presenting the pilot GO project used to evaluate the usefulness of build tags. It is a simple Web Server with the sole purpose of handling http requests based on this URL query string /?value=10. Assuming the value is numeric, the web server returns a JSON payload with a success status and the value increased by one unit.

{"status":"success","result":"11"}

In case of invalid request it returns JSON payload with a fail status and the error.

{"status":"fail","error":"strconv.Atoi: parsing \"10a\": invalid syntax"}

the project layout

In this scenario, the GO project has two packages besides the main: handler and helper.

  • handler: decodes the http request and returns the answer after processing the data received
  • helper: exposes the functions to manipulate the data

the test files

The layout presented allows me to separate the context for the testing stage.
The handler can be tested using the net/http/httptest GO std library package. The handler_internal_test contains the httptest functions NewRequest and NewRecorder to prepare the http.Request and evaluate the http.Response. This could be identified as a sort of integration test.

func TestHandler(t *testing.T) {    var response Response    req := httptest.NewRequest("GET", "/?value=10", nil)    w := httptest.NewRecorder()    Handler(w, req)    res := w.Result()    defer res.Body.Close()    assert.Equal(t, http.StatusOK, res.StatusCode)    data, err := ioutil.ReadAll(res.Body)    assert.NoError(t, err)    err = json.Unmarshal(data, &response)    assert.NoError(t, err)    assert.Equal(t, "11", response.Result)}

The helper package contains the functions used to process the data. Those functions can be tested as a pure unit tests. This is the helper_internal_test created.

func TestConvert(t *testing.T) {    tables := []struct {        in  string        out int    }{        {"1", 1},        {"100", 100},    }    for _, table := range tables {        converted, err := Convert(table.in)        assert.NoError(t, err)        assert.Equal(t, table.out, converted)    }}func TestIncrement(t *testing.T) {    tables := []struct {        in  int        out int    }{        {1, 2},        {100, 101},    }    for _, table := range tables {        converted := Increment(table.in)        assert.Equal(t, table.out, converted)    }}func TestToString(t *testing.T) {    tables := []struct {        in  int        out string    }{        {1, "1"},        {100, "100"},    }    for _, table := range tables {        str := ToString(table.in)        assert.Equal(t, table.out, str)    }}

the build tags ( or build constraints )

What we produced so far is the Web Server and its test files. As a GO developer I just have to run the command go test ./... and my whole list of tests is executed.
The point is that I cannot distinguish between integration test and unit test or even have a separate report in a GitLab pipeline.
Here is where the build tags become useful. On top of that, they are easy to integrate into the code.
The syntax is a comment on top of the test file, with the special word +build followed by the keyword that identifies the tag. The constrains are injected into GO using -tags flag in the test command.
Let's see what happens in practical terms:

  • integration test: the chosen keyword is integration, so I need to add the comment // +build integration on top of the handler_internal_test file and run the command go test ./... -tags=integration to execute it.
// +build integrationpackage handlerimport (    "encoding/json"    "io/ioutil"    "net/http"    "net/http/httptest"    "testing"    "github.com/stretchr/testify/assert")func TestHandler(t *testing.T) {........
  • unit test: the keyword in this case is unit, I need to add the comment // +build unit on top of the helper_internal_test file and run the command go test ./... -tags=unit
// +build unitpackage helperimport (    "testing"    "github.com/stretchr/testify/assert")func TestConvert(t *testing.T) {
  • unit and integration test: tags syntax allows to use AND and OR, as well as negative expressions. To run both at the same time, the command to use is go test ./... -tags=integration,unit

the GitLab CI pipeline

Last but not least, the integration of the build tags into the GitLab CI pipeline. In this case the purpose could be to see the result of the tests grouped by tags. The case presented here contains only two tags: integration and unit. The gitlab-ci.yml file will have two stages, each with the proper script.

stages:  - unit_test  - integration_testunit:  stage: unit_test  script:    - go test -v ./... -tags=unitintegration:  stage: integration_test  script:    - go test -v ./... -tags=integration

Which brings this result:

Alt Text

Thanks to the build tags in the GitLab pipeline presented above I'm able to distinguish tests by context, run them separately and inspect the result individually.


Original Link: https://dev.to/enbis/how-to-use-build-tags-to-control-go-testing-with-a-gitlab-ci-use-case-584b

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To