おまぬけ活動日誌

2002| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2003| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2004| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2005| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2006| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2007| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2008| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2009| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2010| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|
2011| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|
2012| 1| 2| 3| 4| 5| 6| 7|10|
2013| 1| 2| 3| 4| 5| 6| 8| 9|11|12|
2014| 1| 3| 4| 5| 6|

最近のツッコまれどころ

  1. Sloxagigoさん(2014年08月03日)

この日誌から Google してもらう


2013年12月21日(Sat) 公園で子どもたちと鬼ごっこ [同日]

[golang] Goのテストツール

GoとC++で作るB木シリーズ。やっとこgo testでB木のテストが動いたので今日はgo testの動作を掘り下げてみた。 go testでは*_test.goのテストケースが実行される。 テストされるコードは、 *.goから読まれたうちの、packageの記述が合っているもののようだ。 そして、テストケース内の名前空間は、 テストされるコードの名前空間と同じみたい

$ go help

してみると「Go is a tool for managing Go source code.」 サブコマンドとしては、build、clean、…、testなどがあるとのこと。

$ go help test
usage: go test [-c] [-i] [build flags] [packages] [flags for test binary]
  <中略>
'Go test' recompiles each package along with any files with names matching
the file pattern "*_test.go".
  <中略>
By default, go test needs no arguments.  It compiles and tests the package
with source in the current directory, including tests, and runs the tests.

The package is built in a temporary directory so it does not interfere with the
non-test installation.

あー。だからバイナリとかカレントディレクトリには見えなかったのか。

実行される側のソースコードはどういう風になってるんだろう。 普通のGoプログラムは実行を始める場所に package mainを記述してfunc main()を 定義しないといけないようだけれど、btree_test.goにはどちらも無い。 代わりに、package btreeという記述がある。 これは、btree.goというファイル名に対応してるのかな? それともbtree.go内のpackage btreeという記述に対応してるのかな? 試してみる。

$ touch zunuda_test.go
$ go test
can't load package: package .: 
zunda_test.go:1:1: expected 'package', found 'EOF'
$ echo package zunda >| zunda_test.go
$ go test
testing: warning: no tests to run
PASS
ok  	_/home/zunda/tmp/omanuke	0.011s

最低限packageの行があれば実行はできるようだ。 もう少し何かを実行してもらうには…zunuda_test.goに内容を下記のようにすると

package zunda

import (
	"fmt"
	"testing"
)

func TestHello(t *testing.T) {
	fmt.Printf("Hello World\n")
}

下記のように実行された。 カレントディレクトリには他のファイルは置いていない。

$ go test
Hello World
PASS
ok  	_/home/zunda/tmp/omanuke	0.011s

package zundaの行はどのように活用されるのかな。 Pythonみたいにパッケージ名とファイル名を一致させる必要があるのかな。 とりあえずzunda.goにpackage zundaを書いてみる:

package zunda

import (
	"fmt"
)

func Greet() {
	fmt.Printf("Hello World\n")
}

packageが一致してると呼び出し元からは指定する必要はないようだ。 zunda_test.goを下記のようにして

package zunda

import (
	"testing"
)

func TestHello(t *testing.T) {
	Greet()
}

go testすると「Hello World」が表示されるが、 Greet()zunda.Greet()とすると

$ go test
# _/home/zunda/tmp/omanuke
./zunda_test.go:8: undefined: zunda
FAIL	_/home/zunda/tmp/omanuke [build failed]

となる。ではファイル名を変えてみると…

$ mv zunda.go zundan.go
$ go test
Hello World
PASS
ok  	_/home/zunda/tmp/omanuke	0.011s
$ mv zundan.go zunda.ngo
$ go test
# _/home/zunda/tmp/omanuke
./zunda_test.go:8: undefined: Greet
FAIL	_/home/zunda/tmp/omanuke [build failed]

ファイル名は関係なく、 *.goからpackage zundaを頼りにコードを読んでるようだ。

$ sed s/zunda/zundan/ zunda.ngo > zunda.go
$ go test
can't load package: package .: found packages zundan (zunda.go) and zunda (zunda_test.go) in /home/zunda/tmp/omanuke

蛇足。importの時はファイル名とpackageとどちらを気にするのかな。 greet.goを用意して:

package main

import "zunda"

func main() {
	zunda.Greet()
}

あれ、8gもgccgoもないよ?gccgoをapt-get installしました。

$ gccgo greet.go 
greet.go:3:13: error: import file ‘zunda’ not found
greet.go:6:2: error: reference to undefined name ‘zunda’
$ gccgo greet.go zunda.go 
greet.go:3:13: error: import file ‘zunda’ not found
zunda.go:1:1: error: expected package ‘main’
greet.go:6:2: error: reference to undefined name ‘zunda’

おや。zundaをimportできるようにするにはどうするんだ? というかpackage mainがカレントディレクトリにあると go testもうまくいかなくなるのだね。

$ go test 
can't load package: package .: found packages main (greet.go) and zunda (zunda.go) in /home/zunda/tmp/omanuke

Goのパッケージ?のつくりかたについて勉強する必要がありそうですね。


作り手とその取り巻きだけが楽しんでる間は本物じゃない。その中身が理解できない人々の生活を変えてこそ本物だ


zunda <zunda at freeshell.org>