gopherz

Collection of packages and tools to make writing Go code easier.

List Packages View Repository

Introduction

As I work on various Go projects, I often find myself creating utility functions, extending existing packages, or developing packages to solve specific problems. Moving from one project to another, I usually have to copy or rewrite these solutions. So I created this repository to have all these utilities and packages in one place. Hopefully, you'll find them useful as well.

These packages aim to enhance the functionality of the standard library and other popular packages. They are intended to be used together with other packages rather than replacing them. The APIs are designed based on my experience working with Go, focusing on simplicity and ease of use. I will try to follow best practices in Go, but not always. I also tend to choose a more performance implementation if possible.

Read More

ezpkg.io/conveyz

godoc   source

Package conveyz extends the package convey with additional functionality and make it work with gomega. See the original blog post.

Features

  • Convey functions to group tests. SConvey to skip and FConvey to focus on a test.
  • Tests can be nested, and will be executed in nested order. In the example below, it will print:
[0] → [1] → [1.1]
[0] → [1] → [1.2]
[0] → [2] → [2.1]
[0] → [2] → [2.2]

Differences to the original package

  • This package ezpkg.io/conveyz uses gomega for assertions. To me, gomega is more powerful and easier to use.
  • With this package, we only need to set FConvey at a single block level. The original package requires to set FocusConvey at every nested level.
  • FConvey and SConvey will make go test fail. This is to avoid accidentally skipping tests. To skip tests but not make go test fail, use SkipConveyAsTODO.
  • Output looks better with more colors. Stacktrace is nicer.

Examples

See conveyz/examples/conveyz_test.go or stringz/stringz_test.go for more examples.

import (
	"fmt"
	"testing"

	. "ezpkg.io/conveyz"
)

func Test(t *testing.T) {
	Convey("Start", t, func() {
		s := "[0]"
		defer func() { fmt.Printf("\n%s\n", s) }()

		add := func(part string) {
			s = AppendStr(s, part)
		}

		Convey("Test 1:", func() {
			add(" → [1]")
			Ω(s).To(Equal("[0] → [1]"))

			Convey("Test 1.1:", func() {
				add(" → [1.1]")
				Ω(s).To(Equal("[0] → [1] → [1.1]"))
			})
			Convey("Test 1.2:", func() {
				add(" → [1.2]")
				Ω(s).To(Equal("[0] → [1] → [1.2]"))
			})
		})
        // 👇change to FConvey to focus on this block and all children
        // 👇change to SConvey to skip the block
		// 👇change to SkipConveyAsTODO to mark as TODO
		Convey("Test 2:", func() {
			add(" → [2]")
			Ω(s).To(Equal("[0] → [2]"))
			
			Convey("Test 2.1:", func() {
				add(" → [2.1]")
				Ω(s).To(Equal("[0] → [2] → [2.1]"))
			})
			Convey("Test 2.2:", func() {
				add(" → [2.2]")
				Ω(s).To(Equal("[0] → [2] → [2.2]"))
			})
		})
		SkipConvey("failure message", func() {
			// 👆change SkipConvey to Convey to see failure messages
			// 👆change SkipConvey to SkipConveyAsTODO to mark as TODO

			Convey("fail", func() {
				//  Expected
				//      <string>: [0] → [2]
				//  to equal
				//      <string>: this test will fail
				Ω(s).To(Equal("this test will fail"))
			})
			Convey("UNEXPECTED", func() {
				// UNEXPECTED: Refusing to compare <nil> to <nil>.
				//  Be explicit and use BeNil() instead.  This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.
				Ω(nil).To(Equal(nil))
			})
		})
	})
}

func AppendStr(s, part string) string {	return s + part }
func WillPanic() { panic("let's panic! 💥") }
func CallFunc(fn func()) { fn() }

The output will look like this: