Open7

テスト駆動 go

engineer rebornengineer reborn

テスト駆動goのめも

home/work/test_go

  • next action
    • command lineまでは理解する
      • timeやwebsocketは基礎知識が足りてなくて頭が整理できない
    • [] 分解して解読する
      - /work/go_tdd/selft_tdd

基本知識

File周り

// hoge.db.json
//
db, err := os.OpenFile("hoge.db.json", os.O_RDWR|os.O_CREATE, 0666)

// デコード: jsonから構造体に変換して、読み込む
var league []Player
err = json.NewDecoder(file).Decode(&league)

// エンコード:
database := json.NewEncoder(tape{file})

// 書き込み
f.database.Encode(f.league)

TrimPrefix

player := strings.TrimPrefix(r.URL.Path, "/players/")

fmt.Fprint

第一引数の構造体に第二引数のデータを書き込む

func handler(w http.ResponseWriter, r *http.Request) {
	score := 10
	fmt.Fprint(w, score) // レスポンスに「10」と書き込まれる
}

これは w.Write([]byte(...)) と同じらしい

レスポン

  • ヘッダー
w.Header().Set("Content-Type", "application/json")
  • ステータスコード
    WriteHeaderとHeader()(こっちはmap)では指定してる箇所が違うらしい
w.WriteHeader(http.StatusAccepted) // 例: 202
  • ボディ
w.Write([]byte(`{"message":"accepted"}`))
engineer rebornengineer reborn

witer reader

  • interface
    • io reader
      • os.File
      • net.Conn
      • strings.Reader
    • io writer
      • os.Stdout
      • bytes.Buffer
  • interfaceにしている理由
    • 柔軟性をあげてくれる
      • いろんなパッケージに置き換えられる
      • 内部の実装を自由にカスタマイズできる

Reader実装

  • インターフェースで変数を作成
  • メモリ確保: buf
  • r.Readでメモリにデータを入れる
    • errでエラーハンドリング
package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	var r io.Reader = strings.NewReader("Hello, Go!")
	buf := make([]byte, 4)

	for {
		n, err := r.Read(buf)
		if err == io.EOF {
			break
		}
		fmt.Printf("Read: %s\n", buf[:n])
	}
}

jsonDedorder

  • json Decorderの構造
    • pcakage json
    • decor構造体
      • フィールドに io.Reader保持
    • NewDecorderのファクトリー関数
      • decor構造体を返却
    • レシーバー(decor構造体)Decode関数
      • d.reader(&"aaaa")
func NewLeague(rdr io.Reader) ([]Player, error) {
    var league []Player
    err := json.NewDecoder(rdr).Decode(&league)
    if err != nil {
        err = fmt.Errorf("problem parsing league, %v", err)
    }

    return league, err
}

Writer実装

  • w.Witeでバイト([]byte バイトスライス)のデータを渡すと、ターミナルに出力される
    • io.WriteString(w, "Hello, Writer!\n") これも内部では[]byteに変換されているらしい
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	var w io.Writer = os.Stdout
	w.Write([]byte("Hello, Writer!\n"))
}
engineer rebornengineer reborn

テストコードの構成

  • テスト関数の定義
  • t *testing.T
    • t.Run
      • テスト実行
    • t.Errorf(format)
      • 結果を出力
  • got・want: 期待と結果を書く
engineer rebornengineer reborn

code

https://github.com/andmorefine/learn-go-with-tests/tree/main/command-line

コマンド

https://andmorefine.gitbook.io/learn-go-with-tests/build-an-application/command-line

  • やりたいこと

    • 2つのアプリケーション間、でデータベースを共有して、新しいアプリケーションを記録された勝利に応じて、リーグが更新される
  • CLIは2つ

    • ポーカーの入力を受け付けるCLI?
    • webサーバーコードの起動
  • CLI構造体を作成

  • ディレクトリ構造

.
|-- file_system_store.go
|-- file_system_store_test.go
|-- cmd
|   |-- webserver
|       |-- main.go
|-- league.go
|-- server.go
|-- server_integration_test.go
|-- server_test.go
|-- tape.go
|-- tape_test.go