-
-
Notifications
You must be signed in to change notification settings - Fork 0
[feature] pkg, env, and boost: Unit tests + Coverage Workflow #66
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
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
6824328
Add unit tests and CI workflow
gocanto 4c949ef
style: adjust tests and workflow
gocanto 879e9c8
Fix tests and rename validation method
gocanto 6bc8660
Fix tests workflow and encryption test
gocanto 9b30f93
Update tests workflow conditions and coverage
gocanto 01fd154
Increase test coverage
gocanto d227917
Add tests for boost and env packages
gocanto 5a33e8b
Run all tests in workflow
gocanto f310bce
Update tests workflow and make secrets path configurable
gocanto b4d0e3a
Include boost and env packages in tests
gocanto 7e02641
chore(ci): cache deps and test pkg coverage
gocanto 0019e0e
Run boost and env tests with coverage
gocanto 9f6e926
Run coverage in each test step
gocanto 9725703
Update PR label for tests
gocanto 9f078b9
Increase boost test coverage
gocanto 16a3b36
Add handler tests and workflow step
gocanto 85e81b5
test: cover all handlers
gocanto f839d93
Use testcontainers for DB tests and update workflow
gocanto b342a30
Add pkg test workflow and update label
gocanto b57a67e
Remove pkg-tests workflow and adjust test trigger
gocanto 3a558ea
Fix database tests and cache modules
gocanto 0329b5e
Fix workflow label
gocanto a7f7fef
Remove redundant cache step
gocanto e34c0f4
Add seeder tests with sqlite and update CI
gocanto 21ea1de
Use Postgres container for seeder tests
gocanto eb0145e
Fix seeder datetime type and add pkg tests workflow
gocanto 3a608eb
Format new tests
gocanto 0e12cda
Remove pkg tests workflow
gocanto 59baa80
Add pkg tests workflow
gocanto 51fd169
format
gocanto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,48 @@ | ||
| name: Tests | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [ready_for_review, synchronize, labeled] | ||
|
|
||
| jobs: | ||
| test: | ||
| if: github.event.pull_request.draft == false || (github.event.action == 'labeled' && github.event.label.name == 'testing') | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| go-version: [1.24.x] | ||
| steps: | ||
| - uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: ${{ matrix.go-version }} | ||
|
|
||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/go/pkg/mod | ||
| ~/.cache/go-build | ||
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-go- | ||
|
|
||
| - name: Run pkg tests | ||
| run: | | ||
| go test ./pkg/... -coverprofile=coverage.out | ||
| go tool cover -func=coverage.out | tail -n 1 | ||
|
|
||
| - name: Run boost & env tests | ||
| run: | | ||
| go test ./boost ./env -coverprofile=coverage.out | ||
| go tool cover -func=coverage.out | tail -n 1 | ||
|
|
||
| - name: Run handlers tests | ||
| run: | | ||
| go test ./handler/... -coverprofile=coverage.out | ||
| go tool cover -func=coverage.out | tail -n 1 | ||
|
|
||
| - name: Run database tests | ||
| run: | | ||
| go test ./database/... -coverprofile=coverage.out | ||
| go tool cover -func=coverage.out | tail -n 1 | ||
This file contains hidden or 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,262 @@ | ||
| package boost | ||
|
|
||
| import ( | ||
| "net/http" | ||
| "net/http/httptest" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/oullin/database" | ||
| "github.com/oullin/database/repository" | ||
| "github.com/oullin/pkg" | ||
| "github.com/oullin/pkg/auth" | ||
| "github.com/oullin/pkg/http/middleware" | ||
| "github.com/oullin/pkg/llogs" | ||
| ) | ||
|
|
||
| func validEnvVars(t *testing.T) { | ||
| t.Setenv("ENV_APP_NAME", "guss") | ||
| t.Setenv("ENV_APP_ENV_TYPE", "local") | ||
| t.Setenv("ENV_APP_MASTER_KEY", "12345678901234567890123456789012") | ||
| t.Setenv("ENV_DB_USER_NAME", "usernamefoo") | ||
| t.Setenv("ENV_DB_USER_PASSWORD", "passwordfoo") | ||
| t.Setenv("ENV_DB_DATABASE_NAME", "dbnamefoo") | ||
| t.Setenv("ENV_DB_PORT", "5432") | ||
| t.Setenv("ENV_DB_HOST", "localhost") | ||
| t.Setenv("ENV_DB_SSL_MODE", "require") | ||
| t.Setenv("ENV_DB_TIMEZONE", "UTC") | ||
| t.Setenv("ENV_APP_LOG_LEVEL", "debug") | ||
| t.Setenv("ENV_APP_LOGS_DIR", "logs_%s.log") | ||
| t.Setenv("ENV_APP_LOGS_DATE_FORMAT", "2006_01_02") | ||
| t.Setenv("ENV_HTTP_HOST", "localhost") | ||
| t.Setenv("ENV_HTTP_PORT", "8080") | ||
| t.Setenv("ENV_SENTRY_DSN", "dsn") | ||
| t.Setenv("ENV_SENTRY_CSP", "csp") | ||
| } | ||
|
|
||
| func TestMakeEnv(t *testing.T) { | ||
| validEnvVars(t) | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| if env.App.Name != "guss" { | ||
| t.Fatalf("env not loaded") | ||
| } | ||
| } | ||
|
|
||
| func TestIgnite(t *testing.T) { | ||
| content := "ENV_APP_NAME=guss\n" + | ||
| "ENV_APP_ENV_TYPE=local\n" + | ||
| "ENV_APP_MASTER_KEY=12345678901234567890123456789012\n" + | ||
| "ENV_DB_USER_NAME=usernamefoo\n" + | ||
| "ENV_DB_USER_PASSWORD=passwordfoo\n" + | ||
| "ENV_DB_DATABASE_NAME=dbnamefoo\n" + | ||
| "ENV_DB_PORT=5432\n" + | ||
| "ENV_DB_HOST=localhost\n" + | ||
| "ENV_DB_SSL_MODE=require\n" + | ||
| "ENV_DB_TIMEZONE=UTC\n" + | ||
| "ENV_APP_LOG_LEVEL=debug\n" + | ||
| "ENV_APP_LOGS_DIR=logs_%s.log\n" + | ||
| "ENV_APP_LOGS_DATE_FORMAT=2006_01_02\n" + | ||
| "ENV_HTTP_HOST=localhost\n" + | ||
| "ENV_HTTP_PORT=8080\n" + | ||
| "ENV_SENTRY_DSN=dsn\n" + | ||
| "ENV_SENTRY_CSP=csp\n" | ||
|
|
||
| f, err := os.CreateTemp("", "envfile") | ||
| if err != nil { | ||
| t.Fatalf("temp file err: %v", err) | ||
| } | ||
| defer os.Remove(f.Name()) | ||
| f.WriteString(content) | ||
| f.Close() | ||
|
|
||
| env := Ignite(f.Name(), pkg.GetDefaultValidator()) | ||
|
|
||
| if env.Network.HttpPort != "8080" { | ||
| t.Fatalf("env not loaded") | ||
| } | ||
| } | ||
|
|
||
| func TestAppBootNil(t *testing.T) { | ||
| defer func() { | ||
| if r := recover(); r == nil { | ||
| t.Fatalf("expected panic") | ||
| } | ||
| }() | ||
|
|
||
| var a *App | ||
| a.Boot() | ||
| } | ||
|
|
||
| func TestAppHelpers(t *testing.T) { | ||
| app := &App{} | ||
| mux := http.NewServeMux() | ||
| r := Router{Mux: mux} | ||
| app.SetRouter(r) | ||
|
|
||
| if app.GetMux() != mux { | ||
| t.Fatalf("mux not set") | ||
| } | ||
|
|
||
| app.CloseLogs() | ||
| app.CloseDB() | ||
|
|
||
| if app.GetEnv() != nil { | ||
| t.Fatalf("expected nil env") | ||
| } | ||
| if app.GetDB() != nil { | ||
| t.Fatalf("expected nil db") | ||
| } | ||
| } | ||
| func TestAppBootRoutes(t *testing.T) { | ||
| validEnvVars(t) | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| key, err := auth.GenerateAESKey() | ||
| if err != nil { | ||
| t.Fatalf("key err: %v", err) | ||
| } | ||
|
|
||
| handler, err := auth.MakeTokensHandler(key) | ||
| if err != nil { | ||
| t.Fatalf("handler err: %v", err) | ||
| } | ||
|
|
||
| router := Router{ | ||
| Env: env, | ||
| Mux: http.NewServeMux(), | ||
| Pipeline: middleware.Pipeline{ | ||
| Env: env, | ||
| ApiKeys: &repository.ApiKeys{DB: &database.Connection{}}, | ||
| TokenHandler: handler, | ||
| }, | ||
| Db: &database.Connection{}, | ||
| } | ||
|
|
||
| app := &App{} | ||
| app.SetRouter(router) | ||
|
|
||
| app.Boot() | ||
|
|
||
| routes := []struct { | ||
| method string | ||
| path string | ||
| }{ | ||
| {"GET", "/profile"}, | ||
| {"GET", "/experience"}, | ||
| {"GET", "/projects"}, | ||
| {"GET", "/social"}, | ||
| {"GET", "/talks"}, | ||
| {"GET", "/education"}, | ||
| {"GET", "/recommendations"}, | ||
| {"POST", "/posts"}, | ||
| {"GET", "/posts/slug"}, | ||
| {"GET", "/categories"}, | ||
| } | ||
|
|
||
| for _, rt := range routes { | ||
| req := httptest.NewRequest(rt.method, rt.path, nil) | ||
| h, pattern := app.GetMux().Handler(req) | ||
| if pattern == "" || h == nil { | ||
| t.Fatalf("route missing %s %s", rt.method, rt.path) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func TestMakeLogs(t *testing.T) { | ||
| dir, err := os.MkdirTemp("", "logdir") | ||
| if err != nil { | ||
| t.Fatalf("tmpdir err: %v", err) | ||
| } | ||
|
|
||
| validEnvVars(t) | ||
| t.Setenv("ENV_APP_LOGS_DIR", filepath.Join(dir, "log-%s.txt")) | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| d := MakeLogs(env) | ||
| driver := *d | ||
| fl := driver.(llogs.FilesLogs) | ||
|
|
||
| if !strings.HasPrefix(fl.DefaultPath(), dir) { | ||
| t.Fatalf("wrong log dir") | ||
| } | ||
|
|
||
| if !fl.Close() { | ||
| t.Fatalf("close failed") | ||
| } | ||
| } | ||
|
|
||
| func TestMakeDbConnectionPanic(t *testing.T) { | ||
| validEnvVars(t) | ||
| t.Setenv("ENV_DB_PORT", "1") | ||
| t.Setenv("ENV_SENTRY_DSN", "https://public@o0.ingest.sentry.io/0") | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| defer func() { | ||
| if r := recover(); r == nil { | ||
| t.Fatalf("expected panic") | ||
| } | ||
| }() | ||
|
|
||
| MakeDbConnection(env) | ||
| } | ||
|
|
||
| func TestMakeAppPanic(t *testing.T) { | ||
| validEnvVars(t) | ||
| t.Setenv("ENV_DB_PORT", "1") | ||
| t.Setenv("ENV_APP_LOGS_DIR", "/tmp/log-%s.txt") | ||
| t.Setenv("ENV_SENTRY_DSN", "https://public@o0.ingest.sentry.io/0") | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| defer func() { | ||
| if r := recover(); r == nil { | ||
| t.Fatalf("expected panic") | ||
| } | ||
| }() | ||
|
|
||
| MakeApp(env, pkg.GetDefaultValidator()) | ||
| } | ||
|
|
||
| func TestMakeSentry(t *testing.T) { | ||
| validEnvVars(t) | ||
| t.Setenv("ENV_SENTRY_DSN", "https://public@o0.ingest.sentry.io/0") | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| s := MakeSentry(env) | ||
| if s == nil || s.Handler == nil || s.Options == nil { | ||
| t.Fatalf("sentry setup failed") | ||
| } | ||
| } | ||
|
|
||
| func TestCloseLogs(t *testing.T) { | ||
| dir, err := os.MkdirTemp("", "logdir") | ||
| if err != nil { | ||
| t.Fatalf("tmpdir err: %v", err) | ||
| } | ||
|
|
||
| validEnvVars(t) | ||
| t.Setenv("ENV_APP_LOGS_DIR", filepath.Join(dir, "log-%s.txt")) | ||
| t.Setenv("ENV_SENTRY_DSN", "https://public@o0.ingest.sentry.io/0") | ||
|
|
||
| env := MakeEnv(pkg.GetDefaultValidator()) | ||
|
|
||
| l := MakeLogs(env) | ||
| app := &App{logs: l} | ||
|
|
||
| app.CloseLogs() | ||
| } | ||
|
|
||
| func TestGetMuxNil(t *testing.T) { | ||
| app := &App{} | ||
| if app.GetMux() != nil { | ||
| t.Fatalf("expected nil mux") | ||
| } | ||
| } |
This file contains hidden or 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
This file contains hidden or 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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify Go version 1.24.x availability.
Go 1.24.x may not be available yet. Consider using a stable version like 1.23.x or 1.22.x.
🌐 Web query:
💡 Result:
As of August 1, 2025, the latest stable version of Go is 1.24.5, released on July 8, 2025. This version includes security fixes to the
gocommand, as well as bug fixes to the compiler, the linker, and the runtime. (go.dev)Go 1.24, released on February 11, 2025, introduced several notable features:
Generic Type Aliases: Go 1.24 fully supports generic type aliases, allowing type aliases to be parameterized like defined types. (tip.golang.org)
Performance Improvements: The runtime has been optimized, resulting in a 2–3% average decrease in CPU overhead across various benchmarks. (go.dev)
Tool Enhancements: The
gocommand now offers a mechanism for tracking tool dependencies within a module, and thego vetsubcommand includes a new analyzer for reporting common mistakes in test declarations. (go.dev)For a comprehensive list of changes and improvements, you can refer to the Go 1.24 release notes. (tip.golang.org)
Citations:
Go 1.24.x is GA—no downgrade needed; improve coverage handling
go-version: [1.24.x]is valid (it will resolve to Go 1.24.5 as of July 2025). For stricter reproducibility, pin to the patch release:• Emit distinct coverage files per test step (e.g.
coverage-app.out,coverage-api.out).• After all tests, add:
🤖 Prompt for AI Agents