Skip to content

Ci/integration test#34

Open
ga111o wants to merge 4 commits intomainfrom
ci/integration-test
Open

Ci/integration test#34
ga111o wants to merge 4 commits intomainfrom
ci/integration-test

Conversation

@ga111o
Copy link
Copy Markdown
Member

@ga111o ga111o commented Mar 18, 2026

  • 모든 브랜치에 push or pr올라갈 때 실행되는 api 테스트 워크플로우입니다.
  • 실제 백/코어에 요청을 보내거나 실제 db를 사용하지는 않았습니다. api명세서 바탕으로 시뮬레이션 돌리는 방식입니다.
  • 백의 요청이나 코어로의 요청 및 반환값들 확인과 실제 db에 어떠한 작업이 수행되는지 등을 검증합니다.

Summary by CodeRabbit

Release Notes

  • Tests

    • Added comprehensive integration tests for VM operations including start, status, shutdown, and connection flows with mock services
    • Implemented unit tests for database transaction handling and validation
  • Chores

    • Configured automated testing workflow with continuous validation on code pushes and pull requests

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

This PR adds a comprehensive API integration test suite with a new GitHub Actions workflow to validate VM lifecycle operations. The changes introduce end-to-end tests for VM management, dependencies for mocking databases and Redis, and unit tests for SQL interactions.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.github/workflows/api-integration-tests.yaml
New workflow that executes Go API integration tests for VM and structure packages on push and pull requests, with JSON reporting and validation that no tests are skipped.
VM Integration Tests
api/vm_integration_test.go
Comprehensive integration test suite covering VM lifecycle operations (start, status, shutdown, connect) with mocked core server, Guacamole auth service, Redis storage, and database interactions. Includes helper functions for request handling and mock assertions.
Test Dependencies
go.mod
Added three new dependencies: go-sqlmock for database mocking, miniredis for Redis simulation, and gopher-lua as an indirect dependency.
ControlContext SQL Tests
structure/control_infra_sql_test.go
Unit tests validating ControlContext SQL operations (AddInstance and UpdateInstance) using sqlmock to verify transaction execution and query correctness.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 New tests hop into place so bright,
With mocked servers running left and right,
VMs start and stop with grace divine,
Redis seeds dance in perfect line,
Integration flows now verified—all fine! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and generic, using non-descriptive abbreviation 'Ci' without context; it doesn't clearly convey that the PR adds integration tests with mocked services and test infrastructure. Consider revising to a more descriptive title such as 'Add API integration tests with mocked services' or 'Implement integration tests for VM lifecycle and ControlContext' to better reflect the substantial additions.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/integration-test
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use TruffleHog to scan for secrets in your code with verification capabilities.

Add a TruffleHog config file (e.g. trufflehog-config.yml, trufflehog.yml) to your project to customize detectors and scanning behavior. The tool runs only when a config file is present.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
structure/control_infra_sql_test.go (1)

29-36: Add one rollback-path test per transactional method.

Both cases only assert the happy BEGIN ... COMMIT flow. If AddInstance or UpdateInstance stops rolling back after an Exec failure, this suite will still pass. A negative case that forces an error and expects ROLLBACK would close that gap.

Also applies to: 65-69

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@structure/control_infra_sql_test.go` around lines 29 - 36, The tests only
cover the successful BEGIN...COMMIT path; add a negative test for each
transactional method (AddInstance and UpdateInstance) that simulates an Exec
failure and verifies a ROLLBACK is issued and the method returns an error. For
each method, change the sqlmock setup to ExpectBegin(), set one of the Expected
Exec calls (e.g., the inst_info or inst_loc insert used in the current diff) to
WillReturnError(someErr), add mock.ExpectRollback(), call the method and assert
it returns the error, and finally ensure mock.ExpectationsWereMet() passes so
the rollback path is validated.
api/vm_integration_test.go (1)

300-303: Use a bounded client in the HTTP helpers.

Both helpers go through http.DefaultClient, which has no timeout. If a handler or one of the mocked downstream calls hangs, this job waits for the full workflow timeout instead of failing fast.

♻️ Proposed change
+var integrationHTTPClient = &http.Client{Timeout: 5 * time.Second}
+
 func doJSONRequest(t *testing.T, srv *httptest.Server, method, path string, payload map[string]any) testHTTPResponse {
 	t.Helper()
@@
-	resp, err := http.DefaultClient.Do(req)
+	resp, err := integrationHTTPClient.Do(req)
@@
-	resp, err := http.DefaultClient.Do(req)
+	resp, err := integrationHTTPClient.Do(req)

Also applies to: 330-333

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/vm_integration_test.go` around lines 300 - 303, The test HTTP helpers
currently call http.DefaultClient.Do(req) which has no timeout; replace those
calls (both occurrences that match "http.DefaultClient.Do(req)" around the shown
diff and the similar block at 330-333) with a bounded http.Client instance that
sets a sensible Timeout (for example: client := &http.Client{Timeout: 5 *
time.Second}; resp, err := client.Do(req)); alternatively, accept or reuse a
shared *http.Client with a Timeout in the helper so requests fail fast instead
of hanging.
.github/workflows/api-integration-tests.yaml (1)

31-34: The name-based -run filter is easy to outgrow.

This job only runs tests that keep the current TestVM... / TestControlContext_... prefixes, so a renamed or newly added integration test in ./api or ./structure can silently stop running while the workflow still stays green. Consider a dedicated build tag or package-level entrypoint instead of name-based selection.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/api-integration-tests.yaml around lines 31 - 34, The
workflow uses a fragile name-based filter "'TestVM.*|TestControlContext_.*'" in
the go test invocation "go test -json -count=1 ./api ./structure -run
'TestVM.*|TestControlContext_.*'", which can silently drop renamed/new tests;
instead mark integration tests with a dedicated build tag (e.g. add "//go:build
integration" / "+build integration" to integration files or use a package-level
TestMain) and update the workflow command to run "go test -json -count=1
-tags=integration ./api ./structure" (removing the -run filter) so tests are
selected by tag rather than test-name prefixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/vm_integration_test.go`:
- Around line 31-35: The mocked handlers for the POST routes "/BOOTVM" (case for
r.Method == http.MethodPost && r.URL.Path == "/BOOTVM") and "/forceShutDownUUID"
currently always return 200 without decoding/validating the JSON request body,
so add payload contract validation similar to the existing "/getStatusUUID"
branch: decode the request body into the expected struct (e.g., a UUID/payload
type used by getStatusUUID test), check for required fields/valid UUID format,
respond with 400 on decode/validation errors, and only write the 200 success
JSON when validation passes; update both BOOTVM and forceShutDownUUID handler
branches to mirror the validation logic used by getStatusUUID to ensure
malformed requests fail the test.

---

Nitpick comments:
In @.github/workflows/api-integration-tests.yaml:
- Around line 31-34: The workflow uses a fragile name-based filter
"'TestVM.*|TestControlContext_.*'" in the go test invocation "go test -json
-count=1 ./api ./structure -run 'TestVM.*|TestControlContext_.*'", which can
silently drop renamed/new tests; instead mark integration tests with a dedicated
build tag (e.g. add "//go:build integration" / "+build integration" to
integration files or use a package-level TestMain) and update the workflow
command to run "go test -json -count=1 -tags=integration ./api ./structure"
(removing the -run filter) so tests are selected by tag rather than test-name
prefixes.

In `@api/vm_integration_test.go`:
- Around line 300-303: The test HTTP helpers currently call
http.DefaultClient.Do(req) which has no timeout; replace those calls (both
occurrences that match "http.DefaultClient.Do(req)" around the shown diff and
the similar block at 330-333) with a bounded http.Client instance that sets a
sensible Timeout (for example: client := &http.Client{Timeout: 5 * time.Second};
resp, err := client.Do(req)); alternatively, accept or reuse a shared
*http.Client with a Timeout in the helper so requests fail fast instead of
hanging.

In `@structure/control_infra_sql_test.go`:
- Around line 29-36: The tests only cover the successful BEGIN...COMMIT path;
add a negative test for each transactional method (AddInstance and
UpdateInstance) that simulates an Exec failure and verifies a ROLLBACK is issued
and the method returns an error. For each method, change the sqlmock setup to
ExpectBegin(), set one of the Expected Exec calls (e.g., the inst_info or
inst_loc insert used in the current diff) to WillReturnError(someErr), add
mock.ExpectRollback(), call the method and assert it returns the error, and
finally ensure mock.ExpectationsWereMet() passes so the rollback path is
validated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b60314f2-51fd-49de-85cc-f652044ea5a4

📥 Commits

Reviewing files that changed from the base of the PR and between a904eae and 26c5453.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (4)
  • .github/workflows/api-integration-tests.yaml
  • api/vm_integration_test.go
  • go.mod
  • structure/control_infra_sql_test.go

Comment on lines +31 to +35
case r.Method == http.MethodPost && r.URL.Path == "/BOOTVM":
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"message":"BootVM operation success"}`))
return
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate the mocked core payloads for start and shutdown.

Those branches always return 200 without decoding the request body, so this test will not catch a broken UUID or payload shape for /BOOTVM or /forceShutDownUUID. The /getStatusUUID branch already does contract validation; mirror that here so all lifecycle calls are actually verified.

Also applies to: 51-55

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/vm_integration_test.go` around lines 31 - 35, The mocked handlers for the
POST routes "/BOOTVM" (case for r.Method == http.MethodPost && r.URL.Path ==
"/BOOTVM") and "/forceShutDownUUID" currently always return 200 without
decoding/validating the JSON request body, so add payload contract validation
similar to the existing "/getStatusUUID" branch: decode the request body into
the expected struct (e.g., a UUID/payload type used by getStatusUUID test),
check for required fields/valid UUID format, respond with 400 on
decode/validation errors, and only write the 200 success JSON when validation
passes; update both BOOTVM and forceShutDownUUID handler branches to mirror the
validation logic used by getStatusUUID to ensure malformed requests fail the
test.

@kwonkwonn
Copy link
Copy Markdown
Contributor

kwonkwonn commented Mar 19, 2026

  1. .github 는 Main 에 올라가야할 것 같습니다. Dev 에는 test 코드가 올라가는게 좋아보입니다. .github를 메인 기준으로 깃허브가 인식하는거 같은데 Dev를 기준으로 바라보게 하는것도 좋아보입니ㄷ .

  2. @wind5052 변경사항에서 service/vm에 있던 api 들이 포함되기 때문에 해당 pr 이 머지된이후 모든 api 에 대해 테스트를 붙이는게 좋아보여요.

  3. api 단에서는 변경 사항이 있어도 디팬던시가 적고 api 수 자체가 엄청 적기때문에 일단 @wind5052 의 pr을 붙이려고 합니다. 기능별로 나누기 위해 들이는 시간보다 다른 리펙토링을 진행하는게 좋아보여요.

@ga111o
의견 부탁드립니다.

Copy link
Copy Markdown
Contributor

@kwonkwonn kwonkwonn left a comment

Choose a reason for hiding this comment

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

아직 마이그레이션이 되지 않은 부분이 너무 많기도 하고 유닛테스트도 없어 통합테스트를 바로 붙이기엔 어렵지 않을까 생각합니다
깃허브 워크플로우자체는 좋아보입니다...

}
}

type testHTTPResponse struct {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

테스트 유틸함수는 밖으로 빼거나 위로 올리는게 좀 더 읽기 쉬울 것 같습니다.
또 통합테스트라면 /test 로 빼는게 좀 더 이쁠 거 같아요.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

통합테스트가 아니라, 예상 값들 바탕으로 api직접 값 넣어보는 유닛테스트에 가까워 괜찮지 않을까 싶었습니다.

테스트 유틸함수는 확실히 위로 올리는 게 더 좋을 것 같네요.

통합 테스트이면 /test로 빼는 게 좋아보이긴 하는데, api 요청/응답 부분만 각각 테스트하는 코드라 api폴더에 넣어놓긴 했습니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

아하 테스트 이름 보고 헷갈렸네요.
유닛테스트는 보통 "*_test.go" 로 파일별로 생성하는 것을 컨밴션으로 알고 있는데 한번 확인해주세용.(go test가 자동으로 인식할겁니다)

파일이 너무 많으면 오히려 가독성이 떨어질 것 같아서 그런경우에는 그냥 지금처럼 이름지어도 될 거 같긴합니다.

테스트 코드중에서 api 레이어 전반에서 사용할만한 함수가 있다면 /test/api로 빼고 가져다 쓰는것도 방법이 될 수 있을 것 같습니다.

@ga111o
Copy link
Copy Markdown
Member Author

ga111o commented Mar 19, 2026

  1. .github 는 Main 에 올라가야할 것 같습니다. Dev 에는 test 코드가 올라가는게 좋아보입니다. .github를 메인 기준으로 깃허브가 인식하는거 같은데 Dev를 기준으로 바라보게 하는것도 좋아보입니ㄷ .

    1. @wind5052 변경사항에서 service/vm에 있던 api 들이 포함되기 때문에 해당 pr 이 머지된이후 모든 api 에 대해 테스트를 붙이는게 좋아보여요.

    2. api 단에서는 변경 사항이 있어도 디팬던시가 적고 api 수 자체가 엄청 적기때문에 일단 @wind5052 의 pr을 붙이려고 합니다. 기능별로 나누기 위해 들이는 시간보다 다른 리펙토링을 진행하는게 좋아보여요.

@ga111o 의견 부탁드립니다.

  1. 혹시 .github는 main에 올리고, test코드는 Dev에 올린다는 게 어떤 뜻일까요? 현재는 어떤 브랜치에 push 혹은 pr되든 .github내에 있는 workflow파일들이 작동하고, 해당 workflow파일들은 go로 작성된 test코드들을 실행하고 있습니다.

  2. 그게 좋아보이네요. 머지 되면 해당 부분 가져와서 다시 작성해보도록 하겠습니다.

  3. 기능별로 나눈다는 게 어떤 뜻일까요?

@kwonkwonn
Copy link
Copy Markdown
Contributor

  1. 기능개발을 Dev브랜치에서 하고 있는것으로 알고 있는데 그런경우 작성하신 테스트가 돌지 않을까했습니당.
    workflow 가 브랜치 상관없이 돈다면 테스트코드를 Dev로 올리는게 괜찮아보이네요
  2. 생각이 꼬여서 코멘트를 좀 이상하게 작성했네요. file change : api #36 에서 기능별로 api를 묶는게 지금 시점에서는 큰 의미가 없겠다는 생각으로 썻던거 같아요.
    이 pr 에서는 큰 의미 없을 것 같습니다.

@kwonkwonn
Copy link
Copy Markdown
Contributor

#37
혹시 해당 이슈 확인 가능하실까요

테스트 -> 마이그레이션이 되면 2중으로 마이그레이션을 진행해야 돼서 작업이 복잡해질 것 같습니다.
마이그레이션 -> 테스트 형식으로 진행하려고 합니다.

http + my_sql 모킹 및 검증으로 구성되어 있는 것 같은데 해당 함수들을 /test/api/test/sql 혹은 /test/utils처럼 중앙화 시킨 후 마이그레이션이 끝나는 레이어별로 유닛테스트를 붙이는 순서가 자연스러울 것 같아요.

@charlie3965
Copy link
Copy Markdown
Member

  1. .github 는 Main 에 올라가야할 것 같습니다. Dev 에는 test 코드가 올라가는게 좋아보입니다. .github를 메인 기준으로 깃허브가 인식하는거 같은데 Dev를 기준으로 바라보게 하는것도 좋아보입니ㄷ .

    1. @wind5052 변경사항에서 service/vm에 있던 api 들이 포함되기 때문에 해당 pr 이 머지된이후 모든 api 에 대해 테스트를 붙이는게 좋아보여요.
    2. api 단에서는 변경 사항이 있어도 디팬던시가 적고 api 수 자체가 엄청 적기때문에 일단 @wind5052 의 pr을 붙이려고 합니다. 기능별로 나누기 위해 들이는 시간보다 다른 리펙토링을 진행하는게 좋아보여요.

@ga111o 의견 부탁드립니다.

  1. 혹시 .github는 main에 올리고, test코드는 Dev에 올린다는 게 어떤 뜻일까요? 현재는 어떤 브랜치에 push 혹은 pr되든 .github내에 있는 workflow파일들이 작동하고, 해당 workflow파일들은 go로 작성된 test코드들을 실행하고 있습니다.
  2. 그게 좋아보이네요. 머지 되면 해당 부분 가져와서 다시 작성해보도록 하겠습니다.
  3. 기능별로 나눈다는 게 어떤 뜻일까요?

.github의 workflow는 어느 브랜치에 있던 해당 브랜치에서는 정상작동하긴 합니다. 하지만 actions 탭에서 toggle 등을 통해 직접 실행시키고 관리하려면 main에 있어야 적용됩니다.


jobs:
api-integration-tests:
runs-on: ubuntu-latest
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

self hosted runner를 사용하지 않는 이유가 있을까요?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

테스트 돌리는 서버는 실제 서버와 분리시키는 게 좋다고 생각했습니다
컴퓨팅 자원 많이 먹거나 하는 테스트가 아녀서 별도 ci서버 들이기 전까지는 저렇게 해도 무방하지 않을까 싶었습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants