Skip to content

Commit

Permalink
wip - starting storing of player scores
Browse files Browse the repository at this point in the history
  • Loading branch information
quii committed Apr 26, 2018
1 parent ffdf8a1 commit 73d8877
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 1 deletion.
33 changes: 32 additions & 1 deletion http-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ func assertResponseBody(t *testing.T, got, want string) {

We're checking the status in all our tests now so I made a helper `assertStatus` to facilitate that.

Now our first two tests fail because of the 404 instead of 200 so we can fix `PlayerServer`.
Now our first two tests fail because of the 404 instead of 200 so we can fix `PlayerServer` to only return not found if the score is empty.

```go
func (p *PlayerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand All @@ -627,3 +627,34 @@ func (p *PlayerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
```

### Storing scores

Now that we can retrieve scores from a store it now makes sense to be able to store new scores.

## Write the test first

```go
func TestStoreWins(t *testing.T) {
store := StubPlayerStore{
map[string]string{},
}
server := &PlayerServer{&store}

t.Run("it accepts POSTs to /win", func(t *testing.T) {
req, _ := http.NewRequest(http.MethodPost, "/players/Pepper/win", nil)
res := httptest.NewRecorder()

server.ServeHTTP(res, req)

assertStatus(t, res.Code, http.StatusAccepted)
})
}
```

For a start let's just check we get the correct status code if we hit the particular route with POST. This lets us drive out the functionality of accepting a different kind of request and handling it differently to `GET /player/{name}`. Once this works we can then start asserting on our handler's interaction with the store


## Try to run the test
## Write the minimal amount of code for the test to run and check the failing test output
## Write enough code to make it pass
## Refactor
22 changes: 22 additions & 0 deletions http-server/v3/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"log"
"net/http"
)

// InMemoryPlayerStore collects data about players in memory
type InMemoryPlayerStore struct{}

// GetPlayerScore retrieves scores for a given player
func (i *InMemoryPlayerStore) GetPlayerScore(name string) string {
return "123"
}

func main() {
server := &PlayerServer{&InMemoryPlayerStore{}}

if err := http.ListenAndServe(":5000", server); err != nil {
log.Fatalf("could not listen on port 5000 %v", err)
}
}
28 changes: 28 additions & 0 deletions http-server/v3/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"fmt"
"net/http"
)

// PlayerStore stores score information about players
type PlayerStore interface {
GetPlayerScore(name string) string
}

// PlayerServer is a HTTP interface for player information
type PlayerServer struct {
store PlayerStore
}

func (p *PlayerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
player := r.URL.Path[len("/players/"):]

score := p.store.GetPlayerScore(player)

if score == "" {
w.WriteHeader(http.StatusNotFound)
}

fmt.Fprint(w, score)
}
91 changes: 91 additions & 0 deletions http-server/v3/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
)

type StubPlayerStore struct {
scores map[string]string
}

func (s *StubPlayerStore) GetPlayerScore(name string) string {
score := s.scores[name]
return score
}

func TestGETPlayers(t *testing.T) {
store := StubPlayerStore{
map[string]string{
"Pepper": "20",
"Floyd": "10",
},
}
server := &PlayerServer{&store}

t.Run("returns Pepper's score", func(t *testing.T) {
req := newGetScoreRequest("Pepper")
res := httptest.NewRecorder()

server.ServeHTTP(res, req)

assertStatus(t, res.Code, http.StatusOK)
assertResponseBody(t, res.Body.String(), "20")
})

t.Run("returns Floyd's score", func(t *testing.T) {
req := newGetScoreRequest("Floyd")
res := httptest.NewRecorder()

server.ServeHTTP(res, req)

assertStatus(t, res.Code, http.StatusOK)
assertResponseBody(t, res.Body.String(), "10")
})

t.Run("returns 404 on missing players", func(t *testing.T) {
req := newGetScoreRequest("Apollo")
res := httptest.NewRecorder()

server.ServeHTTP(res, req)

assertStatus(t, res.Code, http.StatusNotFound)
})
}

func IgnoreTestStoreWins(t *testing.T) {
store := StubPlayerStore{
map[string]string{},
}
server := &PlayerServer{&store}

t.Run("it accepts POSTs to /win", func(t *testing.T) {
req, _ := http.NewRequest(http.MethodPost, "/players/Pepper/win", nil)
res := httptest.NewRecorder()

server.ServeHTTP(res, req)

assertStatus(t, res.Code, http.StatusAccepted)
})
}

func assertStatus(t *testing.T, got, want int) {
t.Helper()
if got != want {
t.Errorf("did not get correct status, got %d, want %d", got, want)
}
}

func newGetScoreRequest(name string) *http.Request {
req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("/players/%s", name), nil)
return req
}

func assertResponseBody(t *testing.T, got, want string) {
t.Helper()
if got != want {
t.Errorf("response body is wrong, got '%s' want '%s'", got, want)
}
}

0 comments on commit 73d8877

Please sign in to comment.