Reply 모듈을 위한 품질 보증 전략
Source: Dev.to
Problem Statement: 왜 테스트 도구가 중요한가?
직면한 문제
| 문제 | 영향 | 예시 |
|---|---|---|
| 시스템 용량을 모름 | 프로덕션에서 예상치 못한 다운타임 발생 | 얼마나 많은 사용자를 처리할 수 있나요? |
| 기능이 요구사항과 불일치 | 개발자와 이해관계자 간 혼란 | 요구사항을 어떻게 검증하나요? |
| 보안 이슈 누락 | 침해 또는 데이터 노출 | 모든 OWASP 시나리오를 테스트했나요? |
| 성능 저하 미탐지 | 경고 없이 느린 API | P95 레이턴시는 얼마인가? 상승했나요? |
체계적인 도구 없이 팀은 다음과 같이 할 수밖에 없습니다:
- 수동 테스트 (확장성 부족)
- 사용자가 버그를 보고할 때까지 기다림 (지연)
- 성능을 추측 (데이터 기반이 아님)
솔루션 레벨 3: 현대 도구 구현
2.1 k6를 이용한 스트레스 테스트: 시스템 용량 측정
도구: k6 (현대적인 부하 테스트 프레임워크)
구현
File: apps/reply/tests/performance/k6_reply_stress_test.js
export const options = {
stages: [
{ duration: '1m', target: 60 }, // Ramp up
{ duration: '1m', target: 80 }, // Peak load
{ duration: '1m', target: 100 }, // Stress test
],
thresholds: {
'http_req_duration': ['p(95) 2000 ms, test FAIL → Force improvement
2.2 침투 테스트: 사이버 위협으로부터 보호
도구: OWASP API Top 10 기반 커스텀 침투 테스트
구현
File: apps/reply/tests/test_penetration.py
def test_api1_broken_object_level_authorization(self):
"""Attacker mencoba ubah reply orang lain"""
attacker_user = User.objects.create_user("attacker")
victim_reply = Reply.objects.create(..., author="victim")
client = APIClient()
client.force_authenticate(user=attacker_user)
response = client.patch(
f'/forums/{forum_id}/replies/{victim_reply.id}/',
{"content": "Hacked content"},
)
# ✅ MUST be 403 Forbidden
assert response.status_code == 403
# ✅ Content tidak berubah
victim_reply.refresh_from_db()
assert victim_reply.content == "Original content"
테스트 결과
Ran 40+ penetration tests:
✅ API1 (BOLA) - PASSED
✅ API2 (Authentication) - PASSED
✅ API3 (Data Exposure) - PASSED
✅ API5 (Access Control) - PASSED
✅ API6 (Mass Assignment) - PASSED
✅ API7 (Injection) - PASSED
✅ API8 (Asset Management) - PASSED
✅ API9 (Logging) - PASSED
✅ Rate Limiting - PASSED
✅ Concurrent Modification - PASSED
프로젝트에 실질적인 이점
- 보안 신뢰도: OWASP Top 10이 테스트됨.
- 취약점 예방: 레이스 컨디션 같은 엣지 케이스 탐지.
- 컴플라이언스 준비: 보안 테스트 문서가 감사에 바로 사용 가능.
- 소유권 검증: 사용자가 다른 사람의 데이터를 접근·수정할 수 없음.
실행 방법
# 릴리즈 전, 보안 테스트 실행
$ python manage.py test apps.reply.tests.test_penetration
# 테스트 FAIL 시, 보안 이슈를 먼저 수정
# 이는 릴리즈에 대한 게이팅 요구사항이 됨
2.3 BDD 테스트: 기능을 요구사항과 정렬
도구: Behave (실행 가능한 요구사항을 위한 Gherkin 문법)
구현
Feature file: apps/reply/tests/bdd/features/reply.feature
Feature: Reply Management - Business Requirements & Acceptance Criteria
Scenario: User can create a new reply
When alice creates a reply with content "Hello forum!"
Then the reply should be created successfully with status 201
And the reply status should be "pending" by default
And alice should be the author of the reply
Scenario: User cannot modify other user's reply
Given a reply exists by bob with content "Bob's reply"
When alice attempts to update bob's reply to "Hacked content"
Then the modification should be rejected with status 403 Forbidden
And bob's reply content should remain "Bob's reply"
Scenario: Rate limiting prevents abuse
When alice creates 100 replies in quick succession
Then the reply creation should be rate limited
And alice should receive 429 Too Many Requests after threshold
Step implementation: apps/reply/tests/bdd/steps/reply_steps.py
@when(u'{username} creates a reply with content "{content}"')
def step_create_reply(context, username, content):
"""Execute: Create reply via API"""
context.response = context.client.post(
f'/api/forums/{context.forum.id}/replies/',
{'content': content, 'status': 'active'},
format='json'
)
@then(u'the reply should be created successfully with status 201')
def step_reply_created_success(context):
"""Verify: Response status and data"""
assert context.response.status_code == 201
assert 'id' in context.response.data
테스트 결과
$ behave apps/reply/tests/bdd/
Running 20+ scenarios:
✅ User can create a new reply
✅ User can view all replies in a forum
✅ User can update their own reply
✅ User can delete their own reply
✅ User cannot modify other user's reply (403 check)
✅ Rate limiting prevents abuse
...