LoginSignup
48
35

More than 5 years have passed since last update.

Go言語のテスト方法初歩の初歩

Posted at

Goテストの基本

  • testingパッケージを使う。
  • ファイル名は必ず_test.goがつくようにする。
  • testingパッケージをimportする
  • 関数名はfunc TestXxx (t *testing.T)の形式にする

テスト実行

以下のコードをサンプルとして動かしてみる。

package gotest

import (
  "testing"
)

func Test_Division_1(t *testing.T) {
  if i, e := Division(6, 2); i != 3 || e != nil { //try a unit test on function
      t.Error("除算関数のテストが通りません") // もし予定されたものでなければエラーを発生させます。
  } else {
      t.Log("はじめのテストがパスしました") //記録したい情報を記録します
  }
}

func Test_Division_2(t *testing.T) {
  t.Error("パスしません")
}

Goでテストをどのように書くか

テストを全て実行

go test

スクリーンショット 2017-11-06 17.11.21.png

ただ、これではテスト結果がわかりにくい。go testを実行するとテストがパスする情報は表示されない。

表示させるには-vをつける必要がある。

go test -v

スクリーンショット 2017-11-06 17.11.28.png

1つのテストメソッドを実行

go test -run メソッド名

スクリーンショット 2017-11-06 17.11.35.png

Hello Worldのテストを書いてみる

go_test
├── hello.go
└── hello_test.go

go_testというディレクトリにhelloworldを出力するhello.goとテストするためのhello_test.goを置く。

hello.go
package main

import "fmt"

func getHello() string {
  return "Hello World"
}

func main() {
    fmt.Println(getHello())
}

hello.goは実行すればHelloWordの出力。これをテストします。

スクリーンショット 2017-11-06 17.14.25.png

hello_test.go
package main

import (
    "testing"
)

func TestHello(t *testing.T) {
  if "Hello World" != getHello() {
    t.Fatal("failed test")
  }
}

testingをimport。ファイル名は必ず〇〇_test.goにしなければいけないようなので、hello_test.go。メソッド名も規則に則りTestHello()です。

これを実行すると、テストは通りますね。

go test -v

スクリーンショット 2017-11-06 17.15.16.png

assertやexpect的なものがない?

go言語にはphpのassertやrubyのexpectのようなものがないみたいです。

公式のgithubのサンプルを少しみてみましょう。

func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
    ok = true

    var eg InternalExample

    for _, eg = range examples {
        matched, err := matchString(*match, eg.Name)
        if err != nil {
            fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
            os.Exit(1)
        }
        if !matched {
            continue
        }
        ran = true
        if !runExample(eg) {
            ok = false
        }
    }

    return ran, ok
}

https://github.com/golang/go/blob/master/src/testing/example.go
if文で行っていますね。
ちょっと不思議な感じですが、これがgoなのでしょう。

ドキュメントに理由が書いてあります。
アサーション機能はないのですか?

アサーション機能は無いのですか?¶

Goはアサーション機能を提供しません。アサーションが便利なのは否定できませんが、我々の経験上プログラマは、それを適切なエラー処理とエラー出力を避けるために使っています。適切なエラー処理とは、サーバがクラッシュする代わりに致命的ではないエラーを発生するにとどめ、処理を続けられるということを意味しています。適切なエラー出力は、エラーが直接的や部分的だったとき、クラッシュ時の膨大なトレースを翻訳する作業からプログラマを開放することを意味します。正確なエラー出力は、エラーを見つけたプログラマーがそのコードに精通していない時ほど重要です。

いや、それでもAssert使いたい

Goの考えはわかった。でも、私はassertを使いたい。そんな時にはassertのパッケージがあるので、それを使いましょう。

https://github.com/stretchr/testify
これです。

こんな使い方ができるようです。


func TestSomething(t *testing.T) {

  // assert equality
  assert.Equal(t, 123, 123, "they should be equal")

  // assert inequality
  assert.NotEqual(t, 123, 456, "they should not be equal")

  // assert for nil (good for errors)
  assert.Nil(t, object)

  // assert for not nil (good when you expect something)
  if assert.NotNil(t, object) {

    // now we know that object isn't nil, we are safe to make
    // further assertions without causing any errors
    assert.Equal(t, "Something", object.Value)

  }

https://github.com/stretchr/testify
テストっぽい感じがしますね。
さっきのHello Wordのテストをこっちに書き換えます。

go get github.com/stretchr/testify/assert
//インストール
hello_test.go
package main

import (
    "testing"
    "github.com/stretchr/testify/assert"
)

func TestHello(t *testing.T) {
    assert.Equal(t, getHello(), "Hello World")
}

さっきと同じようにテストを実行すると、通ります。
スクリーンショット 2017-11-06 17.11.48.png

48
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
35