Go言語のテスト用ライブラリとGospel

先週初めてGo言語を触る機会があったので、テストの書き方を調べた。
要約すると、標準ライブラリのtestingが好きになれず他に調べても気に入ったものが見付からなかったので自分でつくった

testing

Go言語にはtestingという標準ライブラリが用意されていて、 「go test」コマンドを実行すると「*_test.go」という名前のテスト用ファイルがそれぞれ実行される。 具体的には、そのファイル内で定義されたTest*という名前のテスト用関数がそれぞれ実行されるようになっている。 公式サイトの例ではこういうコードが紹介されていた。

type doubleTest struct {
  in, out int
}

var doubleTests = []doubleTest{
  doubleTest{1, 2},
  doubleTest{2, 4},
  doubleTest{-5, -10},
}

func TestDouble(t *testing.T) {
  for _, dt := range doubleTests {
    v := Double(dt.in)
    if v != dt.out {
      t.Errorf("Double(%d) = %d, want %d.", dt.in, v, dt.out)
    }
  }
}

他のライブラリ

色々あるっぽい。

Gospel

https://github.com/r7kamura/gospel

どれもあんまり使う気にならず、結局自分で適当に新しいのを書いて、 その日見た映画の名前を付けた。 RSpecっぽい記法になっていて、こういう風に書ける。

func TestDescribe(t *testing.T) {
  Describe(t, "Expectation#To", func() {
    Context("with Equal", func() {
      It("evaluates actual == expected", func() {
        Expect(1).To(Equal, 1)
      })
    })

    Context("with NotEqual", func() {
      It("evaluates actual != expected", func() {
        Expect(1).To(NotEqual, 2)
      })
    })

    Context("with Exist", func() {
      It("evaluates actual != nil", func() {
        Expect(1).To(Exist)
      })
    })

    Context("with NotExist", func() {
      It("evaluates actual == nil", func() {
        Expect(nil).To(NotExist)
      })
    })
  })
}

Expectにテスト対象の値を渡して、Toに期待する状態を渡す。 EqualやExist等はただの関数なので、自分で好きなものを定義しても良い。 例えばEqualは次のように定義されている。 値を可変長引数で受け取って、エラーメッセージか空文字列を返せば良い。

// Checks if actual == expected.
func Equal(values ...interface{}) (failureMessage string) {
    if values[0] != values[1] {
        failureMessage = fmt.Sprintf("Expected `%v` to equal `%v`", values[0], values[1])
    }
    return
}

「go test」でテストを実行できる。成功すると"."、失敗すると"F"が表示される。これは成功例。

「go test -v」で実行すると出力形式が変わる。失敗するとどこが違ったかが表示される。