はじめてのgolang デバッグ＆テストコード

というわけで最近 Tour of go をやり直してます。
golangのデバッグとテストコードはそういえばどうやるんだろう思ってやってみました。

対象は以下のFizzBuzzコードです。

```golang:fizzbuzz.go
package main

import (
	"fmt"
)

func main() {

	for i := 1; i < 100; i++ {
		if i%3 == 0 && i%5 == 0 {
			fmt.Println(i, "FizzBuzz")
		} else if i%3 == 0 {
			fmt.Println(i, "Fizz")
		} else if i%5 == 0 {
			fmt.Println(i, "Buzz")
		} else {
			fmt.Println(i)
		}
	}

}
```

##デバッグ

GDBでもできるようですが、Windows環境だったため delve というのを使いました。

https://github.com/derekparker/delve

go get コマンドでインストールしました。

```
> go get -u github.com/derekparker/delve/cmd/dlv
```

インストールしたらソースがあるフォルダに移動して、delve debug コマンドで実行します。
b (break) main.main で main関数のスタートにbreakpointを張って、c (continue)で
続行します。
n (next) で1行進む、s (step) でステップイン、p (print) で変数の値を見ることができました。
このへんはgdbやpythonのpdbと同じですね。

```
c:\work\gomi\fizzbuzz>dlv debug fizubuzz.go
Type 'help' for list of commands.
(dlv) b main.main
Breakpoint 1 set at 0x4a87b2 for main.main() c:/work/gomi/fizzbuzz/fizubuzz.go:7
(dlv) c
> main.main() c:/work/gomi/fizzbuzz/fizubuzz.go:7 (hits goroutine(1):1 total:1) (PC: 0x4a87b2)
     2:
     3: import (
     4:         "fmt"
     5: )
     6:
=>   7: func main() {
     8:
     9:         for i := 1; i < 100; i++ {
    10:                 if i%3 == 0 && i%5 == 0 {
    11:                         fmt.Println(i, "FizzBuzz")
    12:                 } else if i%3 == 0 {
(dlv) n
> main.main() c:/work/gomi/fizzbuzz/fizubuzz.go:9 (PC: 0x4a87c9)
     4:         "fmt"
     5: )
     6:
     7: func main() {
     8:
=>   9:         for i := 1; i < 100; i++ {
    10:                 if i%3 == 0 && i%5 == 0 {
    11:                         fmt.Println(i, "FizzBuzz")
    12:                 } else if i%3 == 0 {
    13:                         fmt.Println(i, "Fizz")
    14:                 } else if i%5 == 0 {
(dlv) s
> main.main() c:/work/gomi/fizzbuzz/fizubuzz.go:10 (PC: 0x4a87e4)
     5: )
     6:
     7: func main() {
     8:
     9:         for i := 1; i < 100; i++ {
=>  10:                 if i%3 == 0 && i%5 == 0 {
    11:                         fmt.Println(i, "FizzBuzz")
    12:                 } else if i%3 == 0 {
    13:                         fmt.Println(i, "Fizz")
    14:                 } else if i%5 == 0 {
    15:                         fmt.Println(i, "Buzz")
(dlv) p i
1
(dlv)
```

より詳しい使い方はこちらにまとまっています。（ありがとうございます）
https://qiita.com/minamijoyo/items/4da68467c1c5d94c8cd7

##テストコード

delveでポチポチ動作を確認していくのはさすがにつらさがあります。
テストコードで確認できるならそっちのほうがいいですよね。
でgolangでテストコードどう書くんでしたっけ？

Webの海をさまよい、golangのテストコードは以下のことを守ればよさそうです。

・testingパッケージをimportする
・ファイル名は_test.goとする
・Testで始まる関数を作成して、引数で(t *testing.T)を取る
・go testコマンドで実行する。

https://blog.alexellis.io/golang-writing-unit-tests/
※見覚えある名前と思ったら、OpenFaasの作者さんですね。

fizzbuzzの結果を関数でreturnするように変えたものへのテストコードを書いてみました。

```golang:fizzbuzz.go
package main

import (
	"fmt"
)

func fizzbuzz(x int) (result string) {

	if x%3 == 0 && x%5 == 0 {
		result = "FizzBuzz"
	} else if x%3 == 0 {
		result = "Fizz"
	} else if x%5 == 0 {
		result = "Buzz"
	} else {
		result = ""
	}
	return

}

func main() {
	for i := 1; i < 100; i++ {
		fmt.Println(i, fizzbuzz(i))
	}
}
```

テストコードです。
fizzbuzz.goではfizzbuzz関数は引数のiのをチェックしてFizz、Buzz、FizzBuzz、Null文字
を返すようにしているので、テストコードでもそれが正しく返されているかを確認します。
※エラーメッセージはおふざけでごめんなさい

```golang:fizzbuzz_test.go
package main

import (
	"testing"
)

func Test_FizzBuzz(t *testing.T) {

	for i := 0; i < 100; i++ {
		result := fizzbuzz(i)
		if i%3 == 0 && i%5 == 0 {
			if result != "FizzBuzz" {
				t.Errorf("あかんやろ")
			}
		} else if i%3 == 0 {
			if result != "Fizz" {
				t.Errorf("あかんやろ")
			}
		} else if i%5 == 0 {
			if result != "Buzz" {
				t.Errorf("あかんやろ")
			}
		} else {
			if result != "" {
				t.Errorf("あかんやろ")
			}
		}
	}

}
```

テストコードをテスト対象のコードと同じフォルダに置いて実行します。

```
c:\work\gomi\fizzbuzz\test>ls
fizubuzz.go  fizzbuzz_test.go

c:\work\gomi\fizzbuzz\test>go test
PASS
ok      _/c_/work/gomi/fizzbuzz/test    0.118s

c:\work\gomi\fizzbuzz\test>
```

ということでgolangではじめてのテストコードが通りました ヽ(・∀・ )ﾉ ｷｬｯ ｷｬｯ

おしまい。