Go でテストを書く

Go でテストを書くとき、private 定義しているものの扱いについてちょっとしたコツです。

目次

Goでのpublic/private

Go では変数名や関数名などの先頭が大文字だと public、小文字だと private となります。
↓ こんな感じ。

var PublicVariable string = "publicな変数です。"

var privateVariable string = "privateな変数です。"

異なるパッケージから、参照するためには、public で定義する必要があります。

Goでは、同一パッケージのファイルは同一ディレクトリに配置するのですが、テストパッケージは例外でテスト対象パッケージと同一ディレクトリに配置します。
しかし、あくまでテストパッケージとテスト対象パッケージは別パッケージです。

つまり、テストパッケージから、テスト対象パッケージ内で定義されたものを参照したい場合 public である必要があるわけです

ただ、元の実装として private としているものをテストのためだけに public にするのは微妙です。
なので対処法を書いておきます。

export_test.go

まずは export_test.go というファイルを用意します。_test.goとついていますが、export_test.go のパッケージはテストパッケージではなく、テスト対象パッケージとします。 ここでは、pkg

├── main.go
└── pkg
    ├── export_test.go
    ├── pkg.go
    └── pkg_test.go

Goではxxx_test.goという命名のファイルはgo buildのビルド対象に入りません。go testでのみビルドされます。

こうすることで、pkgパッケージ内のprivateなものを参照可能で、テスト時以外ビルドされないファイルとなります。
このファイルの中で private のものを public で定義し直していきます。

変数, 定数

// pkg.go
package pkg

var variable string = "プライベートな変数"

const constant string = "プライベートな定数"
// export_test.go
package pkg

var Variable = variable

const Constant = constant

先頭大文字で定義する。

関数

// pkg.go
package pkg

func fn(s string) error {
    // do something
}
// export_test.go
package pkg

var Fn = fn

変数、定数と同じ。

構造体

  • フィールドが public な場合
// pkg.go
package pkg

type st struct {
    Name string
}
// export_test.go
package pkg

type St st
  • フィールドも private な場合
// pkg.go
package pkg

type st struct {
    name string
}
// export_test.go
package pkg

func NewSt(name string) st {
    return st{
        name: name,
    }
}

func (s *st) Name() string {
    return s.name
}

ファクトリ関数を作る。フィールドにアクセスしたければ、Getter も作る。

構造体のメソッド

// pkg.go
package pkg

type st struct {
    name string
} 

func (s *st) name() string {
    return s.name
}
// export_test.go
package pkg

type St struct {
    st
}

func (s *st) Name() string {
    return s.name()
}

元の構造体にpublicなメソッドを定義。
publicな構造体に元の構造体を埋め込む。
これでいけます。ここ迷いました~。

インタフェース

// pkg.go
package pkg

type reader interface {
    Read() ([]byte, error)
}
// export_test.go
package pkg

type Reader interface {
    reader
}

埋め込む。

おわりに

privateな変数や関数などをテストで扱う方法を書きました。
これらの方法で、無駄に public な定義物を増やすことなくテストが書けそうです。