0
0

More than 3 years have passed since last update.

golangのユニットテストにおけるprivateとpublic

Last updated at Posted at 2020-07-28

春の終わりからgolang修行中の身。
趣味以外ではproductionのgolangコードをまだいじったことのない、ひよっこの考察を残してみる。

golangにおけるprivate / publicの理解

関数名や変数名・定数名の先頭を大文字にすることで別packageから参照可能になるいわゆるpublicな状態が exported
反対に先頭を小文字にして同一package内のみ参照が可能になるいわゆるprivateな状態が unexported と理解している。

参考:https://tour.golang.org/basics/3

testpackageとの出会い

書きかけのアプリケーションに、Linter(golangci-lint)をいれたところ、以下のような指摘に遭遇。

$ golangci-lint run ./... 
/usecase/hoge_test.go:1:9: package should be `usecase_test` instead of `usecase` (testpackage)
package usecase
        ^

testpackage にて、テストのpackage指定は _test をつけるように言われている模様。

golangのユニットテストは、テスト対象コードと同一ディレクトリ内に配置するのがお作法で、
packageを同じにすることで unexported なテストも書きやすいのが良いなと思っていた矢先だったのでちょっともにょる。

unexportedなテストの考慮

識者からの助言で、レポジトリの説明にexported/unexported的な話があるということで見てみる。
ちゃんとドキュメントを読もう。
https://github.com/maratori/testpackage

The linter reports if a test is in a package without suffix _test. If you really need to test unexported function, then put the test into file XXX_internal_test.go. The linter skips such files by default. It also skips the file export_test.go by default (see the last article below).

どうやら、unexportedなテストでもにょることは見通されており、
XXX_internal_test.go のファイル名に従うことで、unexportedなテストはlint対象から除外されるようになっている。

また、以下のように同一package内でexportしてテストをおこなう XXX_export_test.go の場合も同様に除外される。
後ほどわかったがこの記法でpackage内のself importはできず、そもそもself import自体が不可だったため解釈誤っている可能性あり(2020/8/4追記)

hoge_test.go
package hoge

// export test
var Hoge = hoge

参考:https://medium.com/@robiplus/golang-trick-export-for-test-aa16cbd7b8cd

除外するファイル名の定義は自分で指定することも可能になっている。

exportedとunexportedなテストの使い分け

いまのところサンプルレベルの自身のコードでは、ユニットテストはexportedとunexportedを意識せずに同一package内で記述している。

testpackageの想定に従うこともできるが、

  • テストは対象コードと同一ディレクトリ内に xxx_test.go として1つだけ配置する
  • unexportedなテストはpackage内参照でそのまま書く
  • exportedなテストは一度変数に入れてから、変数経由でpackage外参照を想定して書く
    • 上述のコメントの通りself importは不可のため想定しているやり方はできず、結果的に xxx_test_go (package別にしてexported想定) xxx_internal_text.go (同一packageでunexported想定)としているのが今(2020/8/4追記)

が自分には合っていそうと感じた。

想定に従って例えば

  • hoge_test.go
    • → packageは xxx_test
  • hoge_internal_test.go
    • → packageは 対象コードと同じxxx

のように分けるとすると、
同一ディレクトリ内で対象コードよりテストコードが増えてしまうのがなんとなく見通し悪くなりそうなのと、
別packageにするのであれば、並列に配置する意図が薄れるためtestをまとめた別ディレクトリをつくってそちらで書くことも検討したくなってくる。

と考えていたが、今は分けるのがベターという見解。ただしディレクトリの見通しは落ちており、exportedなテストは別ディレクトリでもいいのでは?はキープ(2020/8/4追記)

いざ複雑なロジックを含むコードを書き出すとまた考え方が変わってくる可能性もあるが、現時点ではgolangci-lint自体の開発でもdisabledになっているようだし、今日のところは自分のコードでもdisabledにさせてもらおう。

いやでもすぐに気が変わるかもしれないから、一旦コメントアウトで。

.golangci.yml
# - testpackage
0
0
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
0
0