-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from ryichk/add-test-code
テストコードを追加
- Loading branch information
Showing
16 changed files
with
709 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,8 @@ linters: | |
linters-settings: | ||
govet: | ||
enable-all: true | ||
disable: | ||
- fieldalignment | ||
|
||
issues: | ||
exclude-use-default: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
-- name: TruncateAllTables :exec | ||
TRUNCATE TABLE | ||
app.todos | ||
CASCADE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
-- name: ListTodos :many | ||
SELECT | ||
id, | ||
title, | ||
note, | ||
done, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package handler | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/ryichk/todolist/api/internal/model" | ||
"github.com/ryichk/todolist/api/internal/testutil" | ||
) | ||
|
||
func TestHello(t *testing.T) { | ||
e := testutil.SetupEcho() | ||
req := httptest.NewRequest(http.MethodGet, "/", nil) | ||
rec := httptest.NewRecorder() | ||
c := e.NewContext(req, rec) | ||
queries := model.New() | ||
h := NewHandler(testDBPool, queries) | ||
if err := h.Hello(c); err != nil { | ||
t.Errorf("Hello() error = %v", err) | ||
} | ||
if rec.Code != http.StatusOK { | ||
t.Errorf("Hello() rec.Code = %v, want %v", rec.Code, http.StatusOK) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package handler | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/jackc/pgx/v5/pgxpool" | ||
"github.com/ory/dockertest/v3" | ||
|
||
"github.com/ryichk/todolist/api/internal/testdb" | ||
"github.com/ryichk/todolist/api/internal/testutil" | ||
) | ||
|
||
var testDBPool *pgxpool.Pool | ||
|
||
func TestMain(m *testing.M) { | ||
var dockerPool *dockertest.Pool | ||
var dockerResource *dockertest.Resource | ||
dockerPool, dockerResource, testDBPool = testutil.SetupTestDB() | ||
|
||
code := m.Run() | ||
|
||
testdb.CloseTestContainer(dockerPool, dockerResource) | ||
|
||
os.Exit(code) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package handler | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"log" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/ryichk/todolist/api/internal/model" | ||
"github.com/ryichk/todolist/api/internal/testutil" | ||
) | ||
|
||
func TestListTodos(t *testing.T) { | ||
e := testutil.SetupEcho() | ||
queries := model.New() | ||
h := NewHandler(testDBPool, queries) | ||
|
||
ctx := context.Background() | ||
|
||
userID := testutil.SeedTestUserID() | ||
conn, err := queries.AcquireConnection(ctx, testDBPool, userID) | ||
if err != nil { | ||
log.Fatalf("failed to acquire connection: %v", err) | ||
} | ||
|
||
todo := testutil.SetupTestTodo(ctx, queries, conn) | ||
|
||
t.Run("Todo一覧を取得できる", func(t *testing.T) { | ||
req := httptest.NewRequest(http.MethodGet, "/todos", nil) | ||
rec := httptest.NewRecorder() | ||
c := e.NewContext(req, rec) | ||
testutil.SetAuthContext(c) | ||
|
||
if err := h.ListTodos(c); err != nil { | ||
t.Errorf("Handler.ListTodos() error = %v", err) | ||
} | ||
if rec.Code != http.StatusOK { | ||
t.Errorf("Handler.ListTodos() got http status = %v, want %v", rec.Code, http.StatusOK) | ||
} | ||
var got []model.ListTodosRow | ||
if err := json.NewDecoder(rec.Body).Decode(&got); err != nil { | ||
t.Errorf("Handler.ListTodos() error decoding response body: %v", err) | ||
} | ||
if got[0].ID != todo.ID { | ||
t.Errorf("Handler.ListTodos() got ID = %v, want %v", got[0].ID, todo.ID) | ||
} | ||
if got[0].Title != todo.Title { | ||
t.Errorf("Handler.ListTodos() got Title = %v, want %v", got[0].Title, todo.Title) | ||
} | ||
if got[0].Note != todo.Note { | ||
t.Errorf("Handler.ListTodos() got Note = %v, want %v", got[0].Note, todo.Note) | ||
} | ||
}) | ||
|
||
testutil.Teardown(ctx, queries, conn) | ||
} | ||
|
||
func TestCreateTodo(t *testing.T) { | ||
e := testutil.SetupEcho() | ||
queries := model.New() | ||
h := NewHandler(testDBPool, queries) | ||
ctx := context.Background() | ||
userID := testutil.SeedTestUserID() | ||
conn, err := queries.AcquireConnection(ctx, testDBPool, userID) | ||
if err != nil { | ||
log.Fatalf("failed to acquire connection: %v", err) | ||
} | ||
|
||
t.Run("Todoを作成できる", func(t *testing.T) { | ||
requestBody, _ := json.Marshal(map[string]interface{}{ | ||
"title": "テストタイトル", | ||
"note": "テストメモ", | ||
}) | ||
req := httptest.NewRequest(http.MethodPost, "/todos", bytes.NewReader(requestBody)) | ||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) | ||
rec := httptest.NewRecorder() | ||
c := e.NewContext(req, rec) | ||
testutil.SetAuthContext(c) | ||
|
||
if err := h.CreateTodo(c); err != nil { | ||
t.Errorf("Handler.CreateTodo() error = %v", err) | ||
} | ||
if rec.Code != http.StatusCreated { | ||
t.Errorf("Handler.CreateTodo() got http status = %v, want %v", rec.Code, http.StatusCreated) | ||
} | ||
var got map[string]string | ||
if err := json.NewDecoder(rec.Body).Decode(&got); err != nil { | ||
t.Errorf("Handler.CreateTodo() error decoding response body: %v", err) | ||
} | ||
successMessage := "Successfully created a todo" | ||
if got["message"] != successMessage { | ||
t.Errorf("Handler.CreateTodo() got message = %v, want %v", got["message"], successMessage) | ||
} | ||
}) | ||
|
||
testutil.Teardown(ctx, queries, conn) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"user_id": "90000000-0000-0000-0000-000000000000", | ||
"user_id_str": "90000000-0000-0000-0000-000000000000" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package testdb | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"os" | ||
"time" | ||
|
||
"github.com/golang-migrate/migrate/v4" | ||
_ "github.com/golang-migrate/migrate/v4/database/postgres" | ||
_ "github.com/golang-migrate/migrate/v4/source/file" | ||
"github.com/jackc/pgx/v5/pgxpool" | ||
"github.com/ory/dockertest/v3" | ||
"github.com/ory/dockertest/v3/docker" | ||
) | ||
|
||
func CreateTestContainer(postgresUser, postgresPassword, postgresDB string) (*dockertest.Pool, *dockertest.Resource) { | ||
dockerPool, err := dockertest.NewPool("") | ||
if err != nil { | ||
log.Fatalf("Could not construct pool: %v", err) | ||
} | ||
dockerPool.MaxWait = 5 * time.Second | ||
|
||
runOptions := &dockertest.RunOptions{ | ||
Repository: "postgres", | ||
Tag: "17", | ||
Env: []string{ | ||
fmt.Sprintf("POSTGRES_USER=%s", postgresUser), | ||
fmt.Sprintf("POSTGRES_PASSWORD=%s", postgresPassword), | ||
fmt.Sprintf("POSTGRES_DB=%s", postgresDB), | ||
"listen_addresses='*'", | ||
}, | ||
} | ||
|
||
resource, err := dockerPool.RunWithOptions(runOptions, | ||
func(config *docker.HostConfig) { | ||
config.AutoRemove = true | ||
config.RestartPolicy = docker.RestartPolicy{ | ||
Name: "no", | ||
} | ||
}, | ||
) | ||
if err != nil { | ||
log.Fatalf("Could not start resource: %v", err) | ||
} | ||
|
||
return dockerPool, resource | ||
} | ||
|
||
func ConnectTestDB(dockerPool *dockertest.Pool, resource *dockertest.Resource, postgresUser, postgresPassword, postgresDB string) *pgxpool.Pool { | ||
databaseURL := getDatabaseURL(resource, postgresUser, postgresPassword, postgresDB) | ||
|
||
var pool *pgxpool.Pool | ||
|
||
if retryErr := dockerPool.Retry(func() error { | ||
var err error | ||
pool, err = pgxpool.New(context.Background(), databaseURL) | ||
if err != nil { | ||
return err | ||
} | ||
if err := pool.Ping(context.Background()); err != nil { | ||
return err | ||
} | ||
return nil | ||
}); retryErr != nil { | ||
log.Fatalf("Could not connect to Docker: %v", retryErr) | ||
} | ||
|
||
return pool | ||
} | ||
|
||
func MigrateTestDB(resource *dockertest.Resource, postgresUser, postgresPassword, postgresDB string) { | ||
databaseURL := getDatabaseURL(resource, postgresUser, postgresPassword, postgresDB) | ||
mig, err := migrate.New("file://../db/migration", databaseURL) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
if err := mig.Up(); err != nil { | ||
if err.Error() == "no change" { | ||
log.Println("No change") | ||
} else { | ||
log.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
func CloseTestContainer(dockerPool *dockertest.Pool, resource *dockertest.Resource) { | ||
if err := dockerPool.Purge(resource); err != nil { | ||
log.Fatalf("Could not purge resource: %v", err) | ||
} | ||
} | ||
|
||
func getDatabaseURL(resource *dockertest.Resource, postgresUser, postgresPassword, postgresDB string) string { | ||
hostname := os.Getenv("DOCKER_HOSTNAME") | ||
if hostname == "" { | ||
hostname = "localhost" | ||
} | ||
port := resource.GetPort("5432/tcp") | ||
databaseURL := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", | ||
postgresUser, | ||
postgresPassword, | ||
hostname, | ||
port, | ||
postgresDB, | ||
) | ||
|
||
return databaseURL | ||
} |
Oops, something went wrong.