2024년 10월 17일 목요일
복잡한 테스트 설계 전략
복잡한 테스트 설계 전략 사례
우리는 좀 더 복잡한 테스트 케이스를 추가하여 프로그램의 안정성을 높이려면 다양한 상황을 고려한 테스트 설계가 필요합니다. 여기서는 예외 처리, 엣지 케이스, 입력 유효성 검사, 그리고 통합 테스트를 중심으로 어떻게 테스트 코드를 작성할 수 있는지 보여드리겠습니다.
1. 복잡한 테스트 설계 전략
- 기본 기능 테스트: 정상적인 입력이 예상된 대로 변환되는지 확인합니다.
- 엣지 케이스 테스트: 빈 입력, 특수 문자, 예상치 못한 마크업이 들어올 때의 동작을 검증합니다.
- 에러 처리 테스트: 잘못된 입력을 처리할 수 있도록 예외 처리를 점검합니다.
- 통합 테스트: GUI의 각 요소가 올바르게 상호작용하는지 테스트합니다.
2. 예외 처리 추가 (코드 개선)
pythonimport markdown
def convert_markup_to_html(markup_code):
"""입력된 마크업 코드를 HTML로 변환합니다."""
try:
return markdown.markdown(markup_code)
except Exception as e:
raise ValueError(f"마크업 변환 중 오류 발생: {str(e)}")
3. 테스트 케이스 작성
tests/test_markup.py
에 복잡한 테스트 케이스를 추가합니다.
pythonimport unittest
from converter import convert_markup_to_html
class TestMarkupToHTML(unittest.TestCase):
def test_basic_conversion(self):
"""정상적인 마크업 변환 테스트"""
markup = "# Hello"
expected_html = "<h1>Hello</h1>"
self.assertEqual(convert_markup_to_html(markup), expected_html)
def test_empty_input(self):
"""빈 입력 테스트"""
markup = ""
expected_html = ""
self.assertEqual(convert_markup_to_html(markup), expected_html)
def test_special_characters(self):
"""특수 문자 입력 테스트"""
markup = "Hello <World> & Everyone"
expected_html = "<p>Hello <World> & Everyone</p>"
self.assertEqual(convert_markup_to_html(markup), expected_html)
def test_invalid_markup(self):
"""잘못된 마크업 처리 테스트"""
with self.assertRaises(ValueError):
convert_markup_to_html(None) # None 입력은 에러 발생
def test_html_injection(self):
"""HTML 인젝션 방어 테스트"""
markup = "<script>alert('XSS')</script>"
expected_html = "<p><script>alert('XSS')</script></p>"
self.assertEqual(convert_markup_to_html(markup), expected_html)
if __name__ == "__main__":
unittest.main()
테스트 케이스 설명
- 기본 변환 테스트:
# Hello
가<h1>Hello</h1>
로 변환되는지 검증합니다. - 빈 입력 테스트: 입력이 없을 때 빈 HTML이 반환되는지 확인합니다.
- 특수 문자 테스트: 특수 문자가 안전하게 HTML 인코딩되는지 점검합니다.
- 잘못된 입력 처리 테스트:
None
과 같은 잘못된 입력이 발생할 때 예외를 발생시키는지 테스트합니다. - HTML 인젝션 방어 테스트: 악성 스크립트가 HTML 인젝션으로부터 안전하게 처리되는지 확인합니다.
4. 통합 테스트 작성 (GUI 상호작용)
tests/test_gui.py
파일을 추가해 GUI와 함수의 상호작용을 테스트합니다.
pythonimport unittest
import tkinter as tk
from converter import convert_markup_to_html
class TestGUI(unittest.TestCase):
def setUp(self):
"""GUI 테스트를 위한 초기화"""
self.root = tk.Tk()
self.input_text = tk.Text(self.root)
self.output_text = tk.Text(self.root)
def test_gui_interaction(self):
"""GUI에서 입력한 텍스트가 변환되는지 테스트"""
self.input_text.insert(tk.END, "# Hello")
markup = self.input_text.get("1.0", tk.END).strip()
html = convert_markup_to_html(markup)
self.output_text.insert(tk.END, html)
self.assertEqual(self.output_text.get("1.0", tk.END).strip(), "<h1>Hello</h1>")
def tearDown(self):
"""테스트 후 자원 해제"""
self.root.destroy()
if __name__ == "__main__":
unittest.main()
통합 테스트 설명
setUp()
과tearDown()
메서드를 사용해 테스트 환경을 초기화하고 해제합니다.- GUI 상호작용을 통해 입력된 마크업이 올바르게 변환되는지 검증합니다.
5. GitHub Actions에 통합
python-app.yml
에 통합 테스트 실행을 위한 명령을 추가합니다.
yaml - name: Run GUI Tests
run: |
python -m unittest discover tests
6. 요약
이제 더 복잡한 테스트 케이스와 GUI 통합 테스트가 준비되었습니다. 이를 통해:
- 다양한 입력 시 발생할 수 있는 예외를 처리할 수 있습니다.
- GUI의 상호작용이 올바르게 동작하는지 보장할 수 있습니다.
- GitHub Actions와 연계하여 코드 푸시 시마다 자동으로 테스트가 실행됩니다.