Skip to content

Instantly share code, notes, and snippets.

@atotto
Last active May 9, 2021 00:46
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save atotto/d753d91f5f3661b07a3391c0c9f6fb05 to your computer and use it in GitHub Desktop.
Save atotto/d753d91f5f3661b07a3391c0c9f6fb05 to your computer and use it in GitHub Desktop.
golang testing pattern
package calc
import (
"go/token"
"go/types"
)
func Compute(expr string) (string, error) {
tv, err := types.Eval(token.NewFileSet(), types.NewPackage("main", "main"), token.NoPos, expr)
if err != nil {
return "", err
}
return tv.Value.String(), nil
}
1+1=2
1.0/2.0=0.5
package calc
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"testing"
"testing/quick"
)
func TestCompute_simple(t *testing.T) {
s, err := Compute("1+1")
if err != nil {
t.Fatal(err)
}
if s != "2" {
t.Errorf("Compute(1+1) = %s, want 2", s)
}
}
func TestCompute_with_table(t *testing.T) {
computeTests := []struct {
in string
out string
}{
{"1+1", "2"},
{"1.0/2.0", "0.5"},
}
for _, test := range computeTests {
s, err := Compute(test.in)
if err != nil {
t.Fatal(err)
}
if s != test.out {
t.Errorf("Compute(%s) = %s, want %s", test.in, s, test.out)
}
}
}
func TestCompute_with_quicktest(t *testing.T) {
add := func(a, b int16) bool {
s, err := Compute(fmt.Sprintf("%d+%d", a, b))
if err != nil {
t.Fatal(err)
}
expected := strconv.Itoa(int(a) + int(b))
if s != expected {
t.Logf("Compute(%d+%d) = %s, want %s", a, b, s, expected)
return false
}
return true
}
if err := quick.Check(add, nil); err != nil {
t.Fatal(err)
}
}
func TestCompute_with_tRun(t *testing.T) {
t.Run("add sub", func(t *testing.T) {
testCompute(t, "1+1", "2")
testCompute(t, "-2+1", "-1")
})
t.Run("div", func(t *testing.T) {
testCompute(t, "1.0/2.0", "0.5")
testCompute(t, "2.0/1.0", "2")
})
}
func testCompute(t *testing.T, in, expected string) {
t.Helper()
s, err := Compute(in)
if err != nil {
t.Fatal(err)
}
if s != expected {
t.Errorf("Compute(%s) = %s, want %s", in, s, expected)
}
}
func TestCompute_with_file(t *testing.T) {
f, err := os.Open("testdata/compute.txt")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := bufio.NewReader(f)
for {
line, _, err := r.ReadLine()
if err == io.EOF {
break
}
test := strings.Split(string(line), "=")
if len(test) != 2 {
t.Fatal("invalid test data: %s", string(line))
}
testCompute(t, test[0], test[1])
}
}
func SetupComputeTest(t *testing.T, fname string) (*bufio.Reader, func()) {
f, err := os.Open(fname)
if err != nil {
t.Fatal(err)
}
return bufio.NewReader(f), func() {
f.Close()
}
}
func TestCompute_with_setupFunc(t *testing.T) {
r, Teardown := SetupComputeTest(t, "testdata/compute.txt")
defer Teardown()
for {
line, _, err := r.ReadLine()
if err == io.EOF {
break
}
test := strings.Split(string(line), "=")
if len(test) != 2 {
t.Fatal("invalid test data: %s", string(line))
}
testCompute(t, test[0], test[1])
}
}
type computeTest struct {
testing.TB
f *os.File
r *bufio.Reader
}
func SetupComputeTest2(tb testing.TB, fname string) *computeTest {
f, err := os.Open(fname)
if err != nil {
tb.Fatal(err)
}
return &computeTest{
TB: tb,
f: f,
r: bufio.NewReader(f),
}
}
func (t *computeTest) Teardown() {
t.f.Close()
}
func (t *computeTest) testData() (in, out string, ok bool) {
line, _, err := t.r.ReadLine()
if err == io.EOF {
return "", "", false
}
test := strings.Split(string(line), "=")
if len(test) != 2 {
t.Fatal("invalid test data: %s", string(line))
}
return test[0], test[1], true
}
func TestCompute_with_testutil(tt *testing.T) {
t := SetupComputeTest2(tt, "testdata/compute.txt")
defer t.Teardown()
for {
in, out, ok := t.testData()
if !ok {
break
}
testCompute(tt, in, out)
}
}
@atotto
Copy link
Author

atotto commented Dec 18, 2017

https://qiita.com/atotto/items/f6b8c773264a3183a53c

go test -v
=== RUN   TestCompute_simple
--- PASS: TestCompute_simple (0.00s)
=== RUN   TestCompute_with_table
--- PASS: TestCompute_with_table (0.00s)
=== RUN   TestCompute_with_quicktest
--- PASS: TestCompute_with_quicktest (0.00s)
=== RUN   TestCompute_with_tRun
=== RUN   TestCompute_with_tRun/add_sub
=== RUN   TestCompute_with_tRun/div
--- PASS: TestCompute_with_tRun (0.00s)
    --- PASS: TestCompute_with_tRun/add_sub (0.00s)
    --- PASS: TestCompute_with_tRun/div (0.00s)
=== RUN   TestCompute_with_file
--- PASS: TestCompute_with_file (0.00s)
=== RUN   TestCompute_with_setupFunc
--- PASS: TestCompute_with_setupFunc (0.00s)
=== RUN   TestCompute_with_testutil
--- PASS: TestCompute_with_testutil (0.00s)
PASS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment