Go入門したときに開発環境を考えた話の続きです。
まず、やりたかったことの復習です。
- さっくり関数を書いて、単体テストを通すことでGoの勉強がしたい
- GOPATHに依存したくない
- 本コードとテストをキッチリ分けたい
前回の記事では、gbというビルドツールを導入することで一応の解決を迎えました。
その後コメントにて、shibukawa様からありがたいことに貴重なコメントを頂戴致しました。

一番の驚きは、direnv(direnvを使おう)の存在でした。これで、GOPATHの依存の不満は一気に解決しました。テストの流儀も指摘にあるように、IDE等の恩恵を得られなくなるのは、厳しいなと重い受け入れることとしました(複雑になったらモジュールを分けるなど、すればシンプルに保てそう?)
shibukawa様のアドバイスを元に早速構造を練り直してみました。
プロジェクトルート
├── .envrc
├── .gitignore
├── robo.yml
└── src
└── sandbox
├── lock.json
├── manifest.json
└── stringutil
├── reverse.go
└── reverse_test.go
まず、.envrc
がdirenvのための環境変数ファイルです。
$ cat .envrc
export GOPATH=`pwd`
はじめに、dep init
を試したのですが、以下のようなエラーが出ました。GOPATH自体は通っているのですが、init場所として適していなかったようです。結論としては、$GOPATH/src/[any package]
以下でないと、init出来ないようでした。パッケージ(github.com/user/)に依存関係があると考えると当たり前でした。今回(というより小さいサンプルを量産したい私にとって)は、sandboxという名前を使うのが習慣だったので、そちらを採用しました。
determineProjectRoot: /Users/abab/Desktop/go-sandbox not in any $GOPATH
改めて手順を書くと、
cd $GOPATH/src/sandbox
$ dep init
すると、lock.json、manifest.json のファイルが生成されます。このdep中々素晴らしいツールで、依存関係があるようなコードを書いた後(今回は、テストコードでgospelを利用しました)、以下を実行すると、
$ dep ensure
自動的に依存パッケージをlock.jsonに書き込んでくれました!
$ cat src/sandbox/lock.json
{
"memo": "973bc344957137b370558931392f7993dd258e75eede17df4a8772ecaa3b1635",
"projects": [
{
"name": "github.com/r7kamura/gospel",
"branch": "master",
"revision": "d575dd12c2eb84612ae5c84fab56ccb4ce156a1e",
"packages": [
"."
]
}
]
}
その後、テストを実行するとには以下のようにする必要があります。
$ go test sandbox/stringutil
ok sandbox/stringutil 0.005s
これで、無事目的が達成された訳ですが、depの使用ディレクトリが限られてしまうのとテストパッケージを一々指定しなければいけないことが不満として残りました。以下のように実行すれば、まとめてテストを実行出来るのですが依存パッケージ(vendor以下)のテストも走ってしまう問題が発生しました。
$ cd $GOPATH
$ go test ./src/sandbox/...
ok sandbox/stringutil 0.008s
ok sandbox/vendor/github.com/r7kamura/gospel 0.009s
そうとなれば、後は不満を自分で埋める工夫が必要です。roboというタスクランナーを導入することで解決しました。内容は見てもらえればわかると思います。
$ cat robo.yml
init:
summary: dep initialize
command: |
cd $GOPATH/src/sandbox
dep ensure
cd $GOPATH
test:
summary: go test all (note; previous execute go init)
command: |
ls -F ./src/sandbox | grep / | grep -v vendor | awk '{system("go test sandbox/" $0)}'
最終的なsandboxコードは、こちらになります。使い方は、こちらのようになります。
$ robo init
$ robo test
ok sandbox/stringutil 0.006s
IDEAでも問題なく動作が確認できました。かなり満足の出来に仕上がりました! ご指摘コメントありがとうございました。