Code Coverage for Golang Integration Tests with Build Tags

I’ve been writing a lot of Golang code lately. For the most part, I always write unit and integration tests for whatever program that I am building. I’ve been using VSCode as my IDE and really like it. The one thing that I was having trouble with was getting the code coverage to show in the IDE for my integration tests.

I have a different build tag in my unit test code and my integration test code so that I can run the two separately in my CI/CD pipeline. The following build tag is in all of the integration code

// +build integration

I have the following build tag in all of my unit tests

// +build unit

VSCode has the hooks to enable configuration to run and show the coverage of the unit test code in the UI, but not for the integration tests.

I was able to get a visual representation of my code coverage based on my integration tests by running the native go tools. As of Golang 1.2 you can now display test coverage results. It does require a separate cover program that can be installed. Run the following in your project

 go get golang.org/x/tools/cmd/cover

Once that is installed you can run the following to generate a coverage profile file

go test -cover -coverpkg github.com/rchapin/mypackage -tags=integration ./... -coverprofile=/var/tmp/c.out

-cover enables the coverage analysis. -coverpkg will apply coverage analysis to in the tests to the packages that match the CSV of patterns provided. -coverprofile will write out a coverage profile to the path given.

After that has finished, run the following to generate an HTML representation of the coverage profile

go tool cover -html=/var/tmp/c.out

Running Multiple VSCode Windows from the Same Workspace

In order to have two separate VSCode windows open that point to the same workspace, press CTRL+Shift+P and then search for Duplicate As Workspace in New Window. This will open a new window that is associated with the current workspace.

The thing to keep in mind is that it just DUPLICATED the existing workspace in a new window. Notice that at the top of the EXPLORER it will say UNTITLED (WORKSPACE). You can now work with two windows editing your code, but when you quit out of VSCode close the duplicate workspace first. It will ask you to save the workspace. You can tell it to close without saving.

Configuring a Bitbucket Pipeline for a Golang Project with Privately Hosted Dependencies

Go’s dependency management is based solely on git repos. Most of the libraries have publicly available repos from which you can clone the source and then build your project.

In my case, most of the Go that I’m writing ends up in private repos in Bitbucket. Currently, I’ve got a program that I am writing that is dependent on a library that I have written that is hosted as a private repo in Bitbucket. I wanted to setup a Bitbucket Pipeline to build and then run the unit and integration tests when a PR was submitted.

Initially, I had a bit of a hard time figuring out how to set up the pipeline to work correctly and posted this Stack Overflow question. Not being one to give up, I kept at it and stumbled upon some Atlassian documentation that gave me what I needed to get it sorted out.

The key (no pun intended) ended up being the distribution of SSH keys between the repos and some additional go specific environment variables in the pipeline code.

bitbucket-pipelines.yml

image: golang:1.16

pipelines:
  pull-requests:
    '**':
      - step:
          name: Build and test
          script:
            - /bin/bash build/bitbucket-pipelines.sh

The pipeline yaml is straightforward. I’m using a golang builder image, defining a pull-request trigger for any branch, and specifying a shell script that contains the details for buiding and running my tests. The script is in the build directory which is in the base of my repository.

bitbucket-pipelines.sh

# Export the following go specific env vars to configure the tool chain so that I can clone
# repos from my private Bitbucket project.
export GONOPROXY="bitbucket.org/my-project"
export GONOSUMDB="bitbucket.org/my-project"
export GOPRIVATE="bitbucket.org/my-project"

# Configure git to force using ssh instead of https to clone the repos hosted in
# my Bitbucket project
git config --global url."git@bitbucket.org:my-project".insteadof "https://bitbucket.org/my-project"

CGO_ENABLED=0 go build
CGO_ENABLED=0 go test -count=1 -tags=unit ./...
CGO_ENABLED=0 go test -count=1 -tags=integration ./integration_tests/

SSH Key Configuration

With this basic pipeline code you then need to create a distribute ssh keys between the projects

Create the Pipeline SSH key pair in the Repo where you are running the pipeline

  1. In the repo where you are running the build, and composing the library, go to Repository settings. Then under PIPELINES, click on SSH keys
  2. Click Generate keys to create a new key pair.
  3. Copy the Public key to your clipboard. This public key will be added to all of dependent repos to enable us to clone and build with their source code.

For each of the dependency repos do the following:

  1. Go to Repository Settings and under GENERAL click on Access keys
  2. Click Add key and enter a Label and then paste the public key in the Key field.
  3. Then click Add SSH key

Once the public keys have been distributed to the dependent repositories your pipeline will have the permissions required to clone during the build.

Configuring VSCode to Use Build Tags in GoLang to Separate Integration and Unit Test Code

One of the ways to separate unit and integration test code in golang is to use build tags.

A TLDR; on build tags is that it is a way to tell the compiler which source code to include or ignore when doing a build.

For example: if we have the following golang code:

// +build integration

package integration

import "testing"

func TestSomething(t *testing.T) {
	// Some test code
}

Then this code will only be compiled if we run the following command that includes the integration build tag.

go build -tags=integration

In order to separate out our unit test and integration test code we include the integration build tag in each file that is part of the integration tests, and the unit build tag in each file that is part of the unit tests. This is all well and good when we are writing code in a text editor and compiling and running our tests on the command line, but if we are going to use VSCode there are a few things that you need to do to configure the project so that the code is compiled correctly in the IDE while you are working on it and debugging your code.

  1. Click on the folder for your project in the Explorer
  2. Type CTRL+, to open up the Settings Editor
  3. Click on Folder below the search bar in the Settings Editor and select the folder for the project that you are configuring
  4. Click on Extensions > Go in the left-hand navigation of the Settings Editor and scroll down to Build Flags
  5. Click the Add Item button and enter the following: -tags=unit,integration
  6. Scroll down to the Test Tags section and click on Edit in settings.json then add the following to your json file so that it looks like the following
{
    "go.buildFlags": [
        "-tags=unit,integration"
    ],
    "go.testTags": "unit,integration",
}

You can also, just create a settings.json file in the .vscode directory in your project and add the aforementioned items to it. VSCode is really nice because it gives you a number of ways to manage your configs.

With these configuration changes VSCode will now be able to compile all of your application code, unit test, and integration test code while you are working on it.

VSCode Change Indent for File Explorer Tree

For me, I have a hard time distinguishing between the folders, sub-folders, and files in the file explorer of VSCode because the indent is not very pronounced.

In order to increase the indent go to File -> Preferences -> Settings. Search for “indent” and then click on Workbench in the left-hand side navigation pane of the settings window and scroll down to Workbench > Tree: Indent and then enter the number of pixels for the tree indentation. I doubled it, going from 8 to 16 and that made it much easier to see.

Visual Studio Code Cheat Sheet under Linux

As I’m still learning vscode, I’m keeping track of a cheat sheet for shortcuts and other functionality for the IDE.

The following is under Linux, specifically Debian 10 with XFCE.

Keyboard Shortcuts

  • Edit a string in the entire file that matches exactly the string that you have highlighted. For example: you might have a comment, or a variable name, in a file that you want to find and change globally. Highlight the string and then type CTRL+Shift+L then type the replacement string and it will replace it everywhere in the file.
  • Show All Opened Editors in Quick Open (edt command): CTRL+P
  • List all functions and symbols in a file: CTRL+P and then type @

VSCode Keyboard Shortcut to Navigate Between Split Panes

In general, I cannot stand using a mouse. It hurts my hand and takes up a ton of time having to move my hand from the keyboard, to the mouse, move the mouse, click, and then move back to the keyboard.

I am a relatively new VSCode user and was pleased that it has a really good vim emulator. I almost always write code in a split screen so that I can either see two different files at the same time, or see two different sections of the same file. I wanted to figure out how I could add a keyboard shortcut so that I could switch between split screens and found the following. See Dan Andreasson’s answer. As I write this the OP has yet to mark a correct answer.

TLDR; add the following to the keybindings.json file by typing CTRL+Shift+P and then enter Open Keyboard Shortcuts (JSON)

Under Linux this file should be in ~/.config/Code/User/keybindings.json

[
    {
        "key": "ctrl+h",
        "command": "workbench.action.navigateLeft"
    },
    {
        "key": "ctrl+l",
        "command": "workbench.action.navigateRight"
    },
    {
        "key": "ctrl+k",
        "command": "workbench.action.navigateUp"
    },
    {
        "key": "ctrl+j",
        "command": "workbench.action.navigateDown"
    }
]

[SOLVED] Deleting remote git branch; By default, deleting the current branch is denied, because the next remote: ‘git clone’ won’t result in any file checked out, causing confusion

This is a common error encountered where you are renaming your default branch for the repository. If you have a repo hosted on GitHub or some other third-party service, there is likely some way in the GUI to change the default branch for a repo.

If you are hosting your own internal git repository you will need to SSH to that server and “checkout” a different branch from the one that you are trying to delete. In reality, the remote repository has a branch “checked out”. To change it, ssh to the remote host and cd into the <project>.git dir and run the following command to see the current branch

git symbolic-ref HEAD

This will show you the current branch that is “checked out”. To change it run

git symbolic-ref <new-branch>

Once you have done that, you can delete the old default branch.