gotestfmt

repository·main·Indexed 20 days ago

https://github.com/gotesttools/gotestfmt

A tool that transforms verbose Golang test logs into human-readable, interactive logs suitable for CI systems like GitHub Actions, GitLab CI, and CircleCI. It features a pipeline architecture consisting of a tokenizer, parser, and renderer, and supports output customization via Go templates and external formatters.

Tokens
5.2K
Snippets
16
Records
27
Agent score
64%

What's inside gotestfmt

  1. How gotestfmt works internally

    main

    The gotestfmt architecture is a data pipeline consisting of three main components running in separate goroutines, communicating via channels:

    1. Tokenizer: Converts raw go test output into a stream of events.
    2. Parser: Interprets tokens to construct logical units like test cases, packages, and package downloads.
    3. Renderer: Takes the parsed streams and renders them into human-readable text using templates (either baked-in or located in the .gotestfmt directory).
  2. Configure CI system output detection

    main

    gotestfmt automatically detects the CI environment by inspecting environment variables (e.g., GITHUB_WORKFLOW for GitHub Actions, GITLAB_CI for GitLab CI). If detection fails, it defaults to a generic colored output. You can manually override the detection mode using the -ci flag followed by the system name.

    Supported CI systems for specialized output include:

    • github
    • gitlab
    • circleci (Note: CircleCI does not support advanced features like log folding, so specialized templates are not used.)
  3. How the parser works in gotestfmt

    main
    The parser is a core component that sits between the tokenizer and the renderer. It consumes low-level tokens produced by the tokenizer and converts them into high-level objects. These high-level objects are then used by the renderer to generate human-readable test output. The structure of these objects is defined in model.go.
  4. What the tokenizer does

    main
    The tokenizer provides basic, event-based parsing for go test output. It is similar to test2json but produces a specialized output format designed specifically for rendering GitHub Actions output. The resulting stream of events is consumed by the parser to structure the test results.
  5. Set up gotestfmt in GitHub Actions

    main

    The easiest way to use gotestfmt in GitHub Actions is via the gotestfmt-action. This action handles the setup and provides specialized output for GitHub. You can also install it manually using go install.

    To ensure you capture the original logs for debugging, it is recommended to pipe the go test output to tee and save it to a file (e.g., /tmp/gotest.log), then upload that file as a GitHub artifact.

    jobs:
      build:
        name: Test
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v2
    
          - name: Set up Go
            uses: actions/setup-go@v2
            with:
              go-version: 1.16
    
          - name: Set up gotestfmt
            uses: gotesttools/gotestfmt-action@v2
            with:
              token: ${{ secrets.GITHUB_TOKEN }}
    
          - name: Run tests
            run: |
              set -euo pipefail
              go test -json -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
    
          - name: Upload test log
            uses: actions/upload-artifact@v2
            if: always()
            with:
              name: test-log
              path: /tmp/gotest.log
              if-no-files-found: error
  6. Customize gotestfmt output with Go templates

    main

    You can customize how gotestfmt renders output by creating a .gotestfmt directory in your project root and adding Go template (.tpl) files.

    When running on a recognized CI system like GitHub Actions, gotestfmt will look for templates in .gotestfmt/github before falling back to .gotestfmt.

    Key template files include:

    • downloads.tpl: Controls the output for package downloads.
    • package.tpl: Controls the output for a single package and its constituent test cases.
  7. Set up gotestfmt in GitLab CI

    main

    For GitLab CI, it is recommended to create a custom Docker image that includes gotestfmt to avoid downloading it during every job. You can use the official ghcr.io/gotesttools/gotestfmt:latest image as a build stage to copy the binary into your Go-based image.

    Gotestfmt detects GitLab CI via the GITLAB_CI environment variable. You can force this mode using the -ci gitlab option.

    # Include gotestfmt as a base image for building
    FROM ghcr.io/gotesttools/gotestfmt:latest AS gotestfmt
    
    # Use the golang base image
    FROM golang
    # Copy gotestfmt into the golang image
    COPY --from=gotestfmt /gotestfmt /usr/local/bin/
    # Example .gitlab-ci.yaml snippet
    script:
      - |
        docker build -t gotestfmt .
        docker run \
          -v $(pwd):/source \
          -v /tmp:/tmp | \
          -e GITLAB_CI=${GITLAB_CI} \
          gotestfmt \
          /bin/sh -c "cd /source; go test -json -v ./... 2>&1 | tee /tmp/gotest.log | /usr/local/bin/gotestfmt"
  8. Install gotestfmt manually or via container

    main

    Manual Installation

    Download the pre-compiled binaries directly from the releases section. These binaries are standalone and have no dependencies.

    Containerized Execution

    You can run gotestfmt using a Docker container by piping your test output into it. This is useful for environments where you don't want to install the binary directly.

    Note: If you have a high volume of requests, consider mirroring the image to your own private registry.

    go test -json ./... | docker run ghcr.io/gotesttools/gotestfmt:latest
  9. Set up gotestfmt in CircleCI

    main

    Since CircleCI does not support advanced log folding features, you can run gotestfmt by using its Docker container directly in your pipeline. Pipe the output of go test -json -v into the container.

    version: 2
    jobs:
      test:
        docker:
          - image: circleci/golang:1.16
        steps:
          - checkout
          - setup_remote_docker:
              version: 19.03.13
          - run:
              name: Run tests
              command: go test -json -v ./... 2>&1 | tee /tmp/gotest.log | docker run -i ghcr.io/gotesttools/gotestfmt:latest
          - store_artifacts:
              path: /tmp/gotest.log
              destination: gotest.log
  10. Install gotestfmt via go install

    main

    You can install the gotestfmt binary using the standard Go toolchain. Ensure your Go bin directory is in your system PATH to use the command immediately after installation.

    go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
  11. Configure CI environment detection

    main

    gotestfmt automatically detects common CI environments by checking for specific environment variables and uses corresponding subdirectories within the .gotestfmt template folder:

    • GitHub Actions: Detected via GITHUB_WORKFLOW (uses github subdirectory).
    • TeamCity: Detected via TEAMCITY_VERSION (uses teamcity subdirectory).
    • GitLab CI: Detected via GITLAB_CI (uses gitlab subdirectory).

    You can manually override this detection using the -ci flag to specify a different subdirectory within the template directory.