muno-claude-plugin 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -169,37 +169,33 @@ status: ready
|
|
|
169
169
|
|
|
170
170
|
## 출력: 인수 테스트 코드
|
|
171
171
|
|
|
172
|
-
###
|
|
172
|
+
### 프로젝트 언어 감지
|
|
173
|
+
|
|
174
|
+
**테스트 코드 생성 전 반드시 프로젝트의 기술 스택을 파악합니다:**
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
1. build.gradle.kts / build.gradle → Kotlin/Java + Spring
|
|
178
|
+
2. pom.xml → Java + Spring
|
|
179
|
+
3. package.json → TypeScript/JavaScript + Node.js
|
|
180
|
+
4. requirements.txt / pyproject.toml → Python
|
|
181
|
+
5. go.mod → Go
|
|
182
|
+
6. 기존 테스트 코드 패턴 확인 → 프로젝트 컨벤션 따르기
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 언어별 Integration Test 패턴
|
|
188
|
+
|
|
189
|
+
### Kotlin + Spring Boot
|
|
173
190
|
|
|
174
191
|
```kotlin
|
|
175
|
-
package com.example.integration.chat
|
|
176
|
-
|
|
177
|
-
import org.junit.jupiter.api.*
|
|
178
|
-
import org.springframework.beans.factory.annotation.Autowired
|
|
179
|
-
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
|
180
|
-
import org.springframework.boot.test.context.SpringBootTest
|
|
181
|
-
import org.springframework.http.MediaType
|
|
182
|
-
import org.springframework.test.web.servlet.MockMvc
|
|
183
|
-
import org.springframework.test.web.servlet.post
|
|
184
|
-
import org.springframework.transaction.annotation.Transactional
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* STORY-001: 채팅방 관리
|
|
188
|
-
*
|
|
189
|
-
* TC 기반 인수 테스트 - Story 완료 검증
|
|
190
|
-
* TC 생성 직후 작성 (Test First)
|
|
191
|
-
*/
|
|
192
192
|
@SpringBootTest
|
|
193
193
|
@AutoConfigureMockMvc
|
|
194
194
|
@Transactional
|
|
195
195
|
@DisplayName("STORY-001: 채팅방 관리 인수 테스트")
|
|
196
196
|
class ChatRoomAcceptanceTest {
|
|
197
197
|
|
|
198
|
-
@Autowired
|
|
199
|
-
lateinit var mockMvc: MockMvc
|
|
200
|
-
|
|
201
|
-
@Autowired
|
|
202
|
-
lateinit var chatRoomRepository: ChatRoomRepository
|
|
198
|
+
@Autowired lateinit var mockMvc: MockMvc
|
|
203
199
|
|
|
204
200
|
@Nested
|
|
205
201
|
@DisplayName("TC-001-01: 채팅방 생성 - Happy Path")
|
|
@@ -207,50 +203,10 @@ class ChatRoomAcceptanceTest {
|
|
|
207
203
|
|
|
208
204
|
@Test
|
|
209
205
|
@DisplayName("인증된 사용자가 유효한 제목으로 채팅방 생성 시 성공")
|
|
210
|
-
fun `POST api_chat-rooms - 201 Created
|
|
211
|
-
// Arrange (사전 조건)
|
|
212
|
-
val token = createTestUserToken(userId = 1L)
|
|
213
|
-
val requestBody = """
|
|
214
|
-
{
|
|
215
|
-
"title": "새 채팅방"
|
|
216
|
-
}
|
|
217
|
-
""".trimIndent()
|
|
218
|
-
|
|
219
|
-
// Act (실행 단계)
|
|
220
|
-
val result = mockMvc.post("/api/chat-rooms") {
|
|
221
|
-
contentType = MediaType.APPLICATION_JSON
|
|
222
|
-
content = requestBody
|
|
223
|
-
header("Authorization", "Bearer $token")
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Assert (기대 결과)
|
|
227
|
-
result.andExpect {
|
|
228
|
-
status { isCreated() }
|
|
229
|
-
jsonPath("$.chatRoomId") { exists() }
|
|
230
|
-
jsonPath("$.title") { value("새 채팅방") }
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// DB 검증
|
|
234
|
-
val chatRooms = chatRoomRepository.findAll()
|
|
235
|
-
assertThat(chatRooms).hasSize(1)
|
|
236
|
-
assertThat(chatRooms[0].title).isEqualTo("새 채팅방")
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
@Nested
|
|
241
|
-
@DisplayName("TC-001-02: 채팅방 생성 - 빈 제목 오류")
|
|
242
|
-
inner class TC_001_02_EmptyTitle {
|
|
243
|
-
|
|
244
|
-
@Test
|
|
245
|
-
@DisplayName("빈 제목으로 채팅방 생성 시 400 Bad Request")
|
|
246
|
-
fun `POST api_chat-rooms with empty title - 400 Bad Request`() {
|
|
206
|
+
fun `POST api_chat-rooms - 201 Created`() {
|
|
247
207
|
// Arrange
|
|
248
208
|
val token = createTestUserToken(userId = 1L)
|
|
249
|
-
val requestBody = """
|
|
250
|
-
{
|
|
251
|
-
"title": ""
|
|
252
|
-
}
|
|
253
|
-
""".trimIndent()
|
|
209
|
+
val requestBody = """{"title": "새 채팅방"}"""
|
|
254
210
|
|
|
255
211
|
// Act & Assert
|
|
256
212
|
mockMvc.post("/api/chat-rooms") {
|
|
@@ -258,86 +214,135 @@ class ChatRoomAcceptanceTest {
|
|
|
258
214
|
content = requestBody
|
|
259
215
|
header("Authorization", "Bearer $token")
|
|
260
216
|
}.andExpect {
|
|
261
|
-
status {
|
|
262
|
-
jsonPath("$.
|
|
217
|
+
status { isCreated() }
|
|
218
|
+
jsonPath("$.chatRoomId") { exists() }
|
|
263
219
|
}
|
|
264
220
|
}
|
|
265
221
|
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Java + Spring Boot
|
|
226
|
+
|
|
227
|
+
```java
|
|
228
|
+
@SpringBootTest
|
|
229
|
+
@AutoConfigureMockMvc
|
|
230
|
+
@Transactional
|
|
231
|
+
@DisplayName("STORY-001: 채팅방 관리 인수 테스트")
|
|
232
|
+
class ChatRoomAcceptanceTest {
|
|
233
|
+
|
|
234
|
+
@Autowired
|
|
235
|
+
private MockMvc mockMvc;
|
|
266
236
|
|
|
267
237
|
@Nested
|
|
268
|
-
@DisplayName("TC-001-
|
|
269
|
-
|
|
238
|
+
@DisplayName("TC-001-01: 채팅방 생성 - Happy Path")
|
|
239
|
+
class TC_001_01_CreateChatRoom {
|
|
270
240
|
|
|
271
241
|
@Test
|
|
272
|
-
@DisplayName("
|
|
273
|
-
|
|
242
|
+
@DisplayName("인증된 사용자가 유효한 제목으로 채팅방 생성 시 성공")
|
|
243
|
+
void createChatRoom_withValidTitle_returns201() throws Exception {
|
|
274
244
|
// Arrange
|
|
275
|
-
|
|
276
|
-
{
|
|
277
|
-
"title": "새 채팅방"
|
|
278
|
-
}
|
|
279
|
-
""".trimIndent()
|
|
245
|
+
String requestBody = """{"title": "새 채팅방"}""";
|
|
280
246
|
|
|
281
247
|
// Act & Assert
|
|
282
|
-
mockMvc.post("/api/chat-rooms")
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
status
|
|
287
|
-
|
|
248
|
+
mockMvc.perform(post("/api/chat-rooms")
|
|
249
|
+
.contentType(MediaType.APPLICATION_JSON)
|
|
250
|
+
.content(requestBody)
|
|
251
|
+
.header("Authorization", "Bearer " + testToken))
|
|
252
|
+
.andExpect(status().isCreated())
|
|
253
|
+
.andExpect(jsonPath("$.chatRoomId").exists());
|
|
288
254
|
}
|
|
289
255
|
}
|
|
290
|
-
|
|
291
|
-
private fun createTestUserToken(userId: Long): String {
|
|
292
|
-
// 테스트용 JWT 토큰 생성
|
|
293
|
-
return "test-token-for-user-$userId"
|
|
294
|
-
}
|
|
295
256
|
}
|
|
296
257
|
```
|
|
297
258
|
|
|
298
|
-
|
|
259
|
+
### TypeScript + Jest + Supertest
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
describe('STORY-001: 채팅방 관리 인수 테스트', () => {
|
|
263
|
+
describe('TC-001-01: 채팅방 생성 - Happy Path', () => {
|
|
264
|
+
it('인증된 사용자가 유효한 제목으로 채팅방 생성 시 성공', async () => {
|
|
265
|
+
// Arrange
|
|
266
|
+
const token = await createTestUserToken(1);
|
|
267
|
+
const requestBody = { title: '새 채팅방' };
|
|
268
|
+
|
|
269
|
+
// Act
|
|
270
|
+
const response = await request(app)
|
|
271
|
+
.post('/api/chat-rooms')
|
|
272
|
+
.set('Authorization', `Bearer ${token}`)
|
|
273
|
+
.send(requestBody);
|
|
274
|
+
|
|
275
|
+
// Assert
|
|
276
|
+
expect(response.status).toBe(201);
|
|
277
|
+
expect(response.body.chatRoomId).toBeDefined();
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
```
|
|
299
282
|
|
|
300
|
-
|
|
283
|
+
### Python + pytest + FastAPI/Django
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
import pytest
|
|
287
|
+
from httpx import AsyncClient
|
|
288
|
+
|
|
289
|
+
class TestChatRoomAcceptance:
|
|
290
|
+
"""STORY-001: 채팅방 관리 인수 테스트"""
|
|
291
|
+
|
|
292
|
+
class TestTC_001_01_CreateChatRoom:
|
|
293
|
+
"""TC-001-01: 채팅방 생성 - Happy Path"""
|
|
294
|
+
|
|
295
|
+
@pytest.mark.asyncio
|
|
296
|
+
async def test_create_chatroom_with_valid_title_returns_201(
|
|
297
|
+
self, client: AsyncClient, auth_token: str
|
|
298
|
+
):
|
|
299
|
+
response = await client.post(
|
|
300
|
+
"/api/chat-rooms",
|
|
301
|
+
json={"title": "새 채팅방"},
|
|
302
|
+
headers={"Authorization": f"Bearer {auth_token}"}
|
|
303
|
+
)
|
|
304
|
+
assert response.status_code == 201
|
|
305
|
+
assert "chatRoomId" in response.json()
|
|
306
|
+
```
|
|
301
307
|
|
|
302
|
-
###
|
|
308
|
+
### Go + testing + httptest
|
|
303
309
|
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
+
```go
|
|
311
|
+
func TestChatRoomAcceptance(t *testing.T) {
|
|
312
|
+
t.Run("TC-001-01: 채팅방 생성 - Happy Path", func(t *testing.T) {
|
|
313
|
+
// Arrange
|
|
314
|
+
token := createTestUserToken(1)
|
|
315
|
+
body := `{"title": "새 채팅방"}`
|
|
310
316
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
inner class TC_XXX_XX { ... }
|
|
314
|
-
}
|
|
315
|
-
```
|
|
317
|
+
req := httptest.NewRequest("POST", "/api/chat-rooms", strings.NewReader(body))
|
|
318
|
+
req.Header.Set("Authorization", "Bearer "+token)
|
|
316
319
|
|
|
317
|
-
|
|
320
|
+
// Act
|
|
321
|
+
rec := httptest.NewRecorder()
|
|
322
|
+
router.ServeHTTP(rec, req)
|
|
318
323
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
class XxxE2ETest {
|
|
323
|
-
@Autowired lateinit var restTemplate: TestRestTemplate
|
|
324
|
-
|
|
325
|
-
@Test
|
|
326
|
-
@Order(1)
|
|
327
|
-
fun `Step 1: 사용자 생성`() { ... }
|
|
328
|
-
|
|
329
|
-
@Test
|
|
330
|
-
@Order(2)
|
|
331
|
-
fun `Step 2: 로그인`() { ... }
|
|
332
|
-
|
|
333
|
-
@Test
|
|
334
|
-
@Order(3)
|
|
335
|
-
fun `Step 3: 채팅방 생성`() { ... }
|
|
324
|
+
// Assert
|
|
325
|
+
assert.Equal(t, http.StatusCreated, rec.Code)
|
|
326
|
+
})
|
|
336
327
|
}
|
|
337
328
|
```
|
|
338
329
|
|
|
339
330
|
---
|
|
340
331
|
|
|
332
|
+
## 테스트 유형별 패턴 (언어 공통)
|
|
333
|
+
|
|
334
|
+
### Integration Test (API 레벨)
|
|
335
|
+
- HTTP 요청/응답 검증
|
|
336
|
+
- DB 상태 검증
|
|
337
|
+
- 트랜잭션 롤백으로 격리
|
|
338
|
+
|
|
339
|
+
### E2E Test (전체 흐름)
|
|
340
|
+
- 실제 서버 구동 (랜덤 포트)
|
|
341
|
+
- 순차적 시나리오 실행
|
|
342
|
+
- 외부 의존성 Mock 또는 실제 연동
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
341
346
|
## 생성 워크플로우
|
|
342
347
|
|
|
343
348
|
### Step 1: TC 분석
|
|
@@ -153,21 +153,26 @@ status: todo
|
|
|
153
153
|
|
|
154
154
|
## 출력: Unit Test 코드
|
|
155
155
|
|
|
156
|
-
###
|
|
156
|
+
### 프로젝트 언어 감지
|
|
157
|
+
|
|
158
|
+
**테스트 코드 생성 전 반드시 프로젝트의 기술 스택을 파악합니다:**
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
1. build.gradle.kts / build.gradle → Kotlin/Java + Spring
|
|
162
|
+
2. pom.xml → Java + Spring
|
|
163
|
+
3. package.json → TypeScript/JavaScript + Node.js
|
|
164
|
+
4. requirements.txt / pyproject.toml → Python
|
|
165
|
+
5. go.mod → Go
|
|
166
|
+
6. 기존 테스트 코드 패턴 확인 → 프로젝트 컨벤션 따르기
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 언어별 Unit Test 패턴
|
|
172
|
+
|
|
173
|
+
### Kotlin + JUnit5
|
|
157
174
|
|
|
158
175
|
```kotlin
|
|
159
|
-
package com.example.domain.chat.model
|
|
160
|
-
|
|
161
|
-
import org.junit.jupiter.api.*
|
|
162
|
-
import org.assertj.core.api.Assertions.assertThat
|
|
163
|
-
import org.assertj.core.api.Assertions.assertThatThrownBy
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* TASK-001: ChatRoom Entity 생성
|
|
167
|
-
*
|
|
168
|
-
* TDD 기반 Unit Test - 구현 전 작성
|
|
169
|
-
* Task 완료 조건을 검증하는 테스트
|
|
170
|
-
*/
|
|
171
176
|
@DisplayName("ChatRoom Entity 테스트")
|
|
172
177
|
class ChatRoomTest {
|
|
173
178
|
|
|
@@ -176,8 +181,8 @@ class ChatRoomTest {
|
|
|
176
181
|
inner class Creation {
|
|
177
182
|
|
|
178
183
|
@Test
|
|
179
|
-
@DisplayName("유효한 값으로 Entity 생성 시
|
|
180
|
-
fun `유효한 userId와 title로 ChatRoom 생성 시
|
|
184
|
+
@DisplayName("유효한 값으로 Entity 생성 시 성공")
|
|
185
|
+
fun `유효한 userId와 title로 ChatRoom 생성 시 성공`() {
|
|
181
186
|
// Arrange
|
|
182
187
|
val userId = 1L
|
|
183
188
|
val title = "테스트 채팅방"
|
|
@@ -187,80 +192,150 @@ class ChatRoomTest {
|
|
|
187
192
|
|
|
188
193
|
// Assert
|
|
189
194
|
assertThat(chatRoom.externalId).isNotNull()
|
|
190
|
-
assertThat(chatRoom.userId).isEqualTo(userId)
|
|
191
195
|
assertThat(chatRoom.title).isEqualTo(title)
|
|
192
|
-
assertThat(chatRoom.status).isEqualTo(ChatRoomStatus.ACTIVE)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
@Test
|
|
196
|
-
@DisplayName("externalId는 UUIDv7 형식이다")
|
|
197
|
-
fun `externalId는 UUIDv7 형식으로 생성된다`() {
|
|
198
|
-
// Arrange & Act
|
|
199
|
-
val chatRoom = ChatRoom(userId = 1L, title = "테스트")
|
|
200
|
-
|
|
201
|
-
// Assert
|
|
202
|
-
assertThat(chatRoom.externalId).isNotNull()
|
|
203
|
-
assertThat(chatRoom.externalId.toString()).matches(
|
|
204
|
-
"^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
205
|
-
)
|
|
206
196
|
}
|
|
207
197
|
}
|
|
208
198
|
|
|
209
199
|
@Nested
|
|
210
|
-
@DisplayName("
|
|
211
|
-
inner class
|
|
200
|
+
@DisplayName("유효성 검증")
|
|
201
|
+
inner class Validation {
|
|
212
202
|
|
|
213
203
|
@Test
|
|
214
204
|
@DisplayName("빈 제목으로 생성 시 예외 발생")
|
|
215
|
-
fun `빈 title로 ChatRoom 생성 시
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
ChatRoom(userId = 1L, title = "")
|
|
219
|
-
}.isInstanceOf(IllegalArgumentException::class.java)
|
|
220
|
-
.hasMessageContaining("title")
|
|
205
|
+
fun `빈 title로 ChatRoom 생성 시 예외`() {
|
|
206
|
+
assertThatThrownBy { ChatRoom(userId = 1L, title = "") }
|
|
207
|
+
.isInstanceOf(IllegalArgumentException::class.java)
|
|
221
208
|
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
222
212
|
|
|
223
|
-
|
|
224
|
-
@DisplayName("100자 초과 제목으로 생성 시 예외 발생")
|
|
225
|
-
fun `100자 초과 title로 ChatRoom 생성 시 IllegalArgumentException 발생`() {
|
|
226
|
-
// Arrange
|
|
227
|
-
val longTitle = "가".repeat(101)
|
|
213
|
+
### Java + JUnit5
|
|
228
214
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
215
|
+
```java
|
|
216
|
+
@DisplayName("ChatRoom Entity 테스트")
|
|
217
|
+
class ChatRoomTest {
|
|
218
|
+
|
|
219
|
+
@Nested
|
|
220
|
+
@DisplayName("Entity 생성")
|
|
221
|
+
class Creation {
|
|
235
222
|
|
|
236
223
|
@Test
|
|
237
|
-
@DisplayName("
|
|
238
|
-
|
|
224
|
+
@DisplayName("유효한 값으로 Entity 생성 시 성공")
|
|
225
|
+
void createChatRoom_withValidInput_succeeds() {
|
|
239
226
|
// Arrange
|
|
240
|
-
|
|
227
|
+
Long userId = 1L;
|
|
228
|
+
String title = "테스트 채팅방";
|
|
241
229
|
|
|
242
230
|
// Act
|
|
243
|
-
|
|
231
|
+
ChatRoom chatRoom = new ChatRoom(userId, title);
|
|
244
232
|
|
|
245
233
|
// Assert
|
|
246
|
-
assertThat(chatRoom.
|
|
234
|
+
assertThat(chatRoom.getExternalId()).isNotNull();
|
|
235
|
+
assertThat(chatRoom.getTitle()).isEqualTo(title);
|
|
247
236
|
}
|
|
248
237
|
}
|
|
249
238
|
|
|
250
239
|
@Nested
|
|
251
|
-
@DisplayName("
|
|
252
|
-
|
|
240
|
+
@DisplayName("유효성 검증")
|
|
241
|
+
class Validation {
|
|
253
242
|
|
|
254
243
|
@Test
|
|
255
|
-
@DisplayName("생성 시
|
|
256
|
-
|
|
244
|
+
@DisplayName("빈 제목으로 생성 시 예외 발생")
|
|
245
|
+
void createChatRoom_withEmptyTitle_throwsException() {
|
|
246
|
+
assertThatThrownBy(() -> new ChatRoom(1L, ""))
|
|
247
|
+
.isInstanceOf(IllegalArgumentException.class);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### TypeScript + Jest
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
describe('ChatRoom Entity', () => {
|
|
257
|
+
describe('Entity 생성', () => {
|
|
258
|
+
it('유효한 값으로 Entity 생성 시 성공', () => {
|
|
259
|
+
// Arrange
|
|
260
|
+
const userId = 1;
|
|
261
|
+
const title = '테스트 채팅방';
|
|
262
|
+
|
|
263
|
+
// Act
|
|
264
|
+
const chatRoom = new ChatRoom({ userId, title });
|
|
265
|
+
|
|
266
|
+
// Assert
|
|
267
|
+
expect(chatRoom.externalId).toBeDefined();
|
|
268
|
+
expect(chatRoom.title).toBe(title);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('유효성 검증', () => {
|
|
273
|
+
it('빈 제목으로 생성 시 예외 발생', () => {
|
|
274
|
+
expect(() => new ChatRoom({ userId: 1, title: '' }))
|
|
275
|
+
.toThrow('title');
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Python + pytest
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
import pytest
|
|
285
|
+
from domain.chat.model import ChatRoom
|
|
286
|
+
|
|
287
|
+
class TestChatRoom:
|
|
288
|
+
"""ChatRoom Entity 테스트"""
|
|
289
|
+
|
|
290
|
+
class TestCreation:
|
|
291
|
+
"""Entity 생성"""
|
|
292
|
+
|
|
293
|
+
def test_create_chatroom_with_valid_input_succeeds(self):
|
|
294
|
+
# Arrange
|
|
295
|
+
user_id = 1
|
|
296
|
+
title = "테스트 채팅방"
|
|
297
|
+
|
|
298
|
+
# Act
|
|
299
|
+
chat_room = ChatRoom(user_id=user_id, title=title)
|
|
300
|
+
|
|
301
|
+
# Assert
|
|
302
|
+
assert chat_room.external_id is not None
|
|
303
|
+
assert chat_room.title == title
|
|
304
|
+
|
|
305
|
+
class TestValidation:
|
|
306
|
+
"""유효성 검증"""
|
|
307
|
+
|
|
308
|
+
def test_create_chatroom_with_empty_title_raises_error(self):
|
|
309
|
+
with pytest.raises(ValueError, match="title"):
|
|
310
|
+
ChatRoom(user_id=1, title="")
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Go + testing
|
|
314
|
+
|
|
315
|
+
```go
|
|
316
|
+
func TestChatRoom(t *testing.T) {
|
|
317
|
+
t.Run("Entity 생성", func(t *testing.T) {
|
|
318
|
+
t.Run("유효한 값으로 Entity 생성 시 성공", func(t *testing.T) {
|
|
319
|
+
// Arrange
|
|
320
|
+
userID := int64(1)
|
|
321
|
+
title := "테스트 채팅방"
|
|
322
|
+
|
|
257
323
|
// Act
|
|
258
|
-
|
|
324
|
+
chatRoom, err := NewChatRoom(userID, title)
|
|
259
325
|
|
|
260
326
|
// Assert
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
327
|
+
assert.NoError(t, err)
|
|
328
|
+
assert.NotEmpty(t, chatRoom.ExternalID)
|
|
329
|
+
assert.Equal(t, title, chatRoom.Title)
|
|
330
|
+
})
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
t.Run("유효성 검증", func(t *testing.T) {
|
|
334
|
+
t.Run("빈 제목으로 생성 시 에러", func(t *testing.T) {
|
|
335
|
+
_, err := NewChatRoom(1, "")
|
|
336
|
+
assert.Error(t, err)
|
|
337
|
+
})
|
|
338
|
+
})
|
|
264
339
|
}
|
|
265
340
|
```
|
|
266
341
|
|