Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kadai3-1: nagaa052 #25

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

nagaa052
Copy link

タイピングゲーム

要件

  • 標準出力に英単語を出す(出すものは自由)
  • 標準入力から1行受け取る
  • 制限時間内に何問解けたか表示する

コマンド/オプション

$ tgame -h

tgame is a Typing Game
Usage:
  tgame [option]
Options:
  -c	Print Color
  -t int
    	Timeout Seconds (default 30)

パッケージ構成

├── main.go
└── pkg
    ├── game
    └── questions
  • main: 起動/コマンドオプション
  • pkg/game : タイピングゲームのメインロジック
  • pkg/questions : 問題の管理/取得

やってみたこと

  • export_test.goを使って、非公開の機能テストも書いてみた
  • interfaceを使って問題の取得先を切り替えやすくした(つもり)
  • ExampleTestを書いてみた

できなかったこと

  • メインロジックのテストが書けなかった
    • テストからだと入力と出力の制御が行えず、テスト実行中、入力と出力を繰り替えしてしまう
    • 「エラーが発生するか」のテストは書けるが、大量の書き込みが発生してしまうのでやめた

flag.Usage = usage
flag.Parse()

g, err := game.New(game.Options{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

基本ポインタにしておく。

}, os.Stdin, os.Stdout, os.Stderr)

if err != nil {
log.Fatal("Failed to start the game")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log.Fatalは使わない

)

const (
ExitOK = iota
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

プログラムの外部に出る情報にはiotaを使わない。
例:DBに保存されるもの、ネットワークを介して送られるもの、コマンドライツールの出力になるもの

// Game is manages game information
type Game struct {
qs *questions.Questions
*Result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

埋め込む必要性は?

// DefaultOptions is the default value of Options.
var DefaultOptions = Options{
TimeUpSecond: 30,
IsColor: false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

falseなら別に初期化する必要ないのでは?

// Options is a specifiable option.
type Options struct {
TimeUpSecond int
IsColor bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is?


// Options is a specifiable option.
type Options struct {
TimeUpSecond int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time.Durationを使う

}

// Print is Output the result.
func (r *Result) Print(out io.Writer) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

io.Writerの変数はwと書くことが多い


return &Game{
qs: qs,
Result: &Result{},
Copy link
Member

@tenntenn tenntenn Jun 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

埋め込むならポインタじゃなくてもいい。そしたらゼロ値で使える。

scanner := bufio.NewScanner(g.inStream)
defer close(dst)

for scanner.Scan() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

エラー処理


func (g *Game) getQuestion() (*questions.Question, error) {

rand.Seed(time.Now().UnixNano())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

呼び出しの度にSeedをセットしない

func (g *Game) getQuestion() (*questions.Question, error) {

rand.Seed(time.Now().UnixNano())
index := rand.Intn(g.qs.GetSize())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同じ問題が出る

},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これはt.Paralellしない?

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

inStream := &bytes.Buffer{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ゼロ値でよい

_, err := game.New(tt.opt, inStream, outStream, errStream)
if (err != nil) != tt.wantErr {
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returnする必要性ある?

got, err := game.ExportGetQuestion(g)
if (err != nil) != tt.wantErr {
t.Errorf("Game.getQuestion() error = %v, wantErr %v", err, tt.wantErr)
return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returnするならt.Fatalfを使う


type inMemQ struct{}

var words = []string{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

外部ファイルからもらうようにした方がよいのでは?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、なるほど、テスト用の実装?

want *qs.Questions
wantErr bool
}{
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

テストケースが少なすぎる

want bool
}{
{
name: "Is correct test",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もっと名前をシンプルにして、パット見で分かるようにする。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants