unittest의 TestSuite 기능은 유연한 테스트 케이스 관리를 가능하게 하지만, 사전에 코드로 테스트 셋을 구성해야 하는 단점이 있습니다. 본문에서는 Flask와 unittest.TestSuite, pickle을 활용하여 간단한 테스트 케이스 관리 시스템을 구현합니다.
구현 방식:
- 테스트 케이스 수집: unittest.discover를 사용해 모든 테스트 항목을 탐색 → 사용자 선택에 따라 TestSuite 생성 → pickle을 통해 파일로 저장
- 테스트 실행: os.listdir로 생성된 TestSuite 목록 조회 → pickle로 역직렬화 → TestSuite 실행 후 결과 보고서 생성
필요 패키지 설치: pip install flask pip install HTMLTestReportCN
프로젝트 구조:
- dashboard 디렉토리(웹 애플리케이션) ├─ suites: 직렬화된 TestSuite 파일 저장 ├─ templates: HTML 템플릿 └─ app.py: 메인 서버 파일
- test 디렉토리(테스트 케이스) └─ case: 실제 테스트 코드
서버 로직 구현:
from flask import Flask, request, render_template, redirect
import os
import unittest
import pickle
# 경로 설정
APP_DIR = os.path.dirname(os.path.abspath(__file__))
TEST_CASE_DIR = os.path.join(os.path.dirname(APP_DIR), 'test', 'case')
TEST_SUITE_DIR = os.path.join(APP_DIR, 'suites')
def gather_test_cases():
test_suite = unittest.TestSuite()
def _collect(tests):
if isinstance(tests, unittest.TestSuite):
if tests.countTestCases():
for item in tests:
_collect(item)
else:
test_suite.addTest(tests)
_collect(unittest.defaultTestLoader.discover(TEST_CASE_DIR))
return test_suite
app = Flask(__name__)
@app.route("/test_suite_add", methods=["GET", "POST"])
def add_test_suite():
test_cases = [case.id() for case in gather_test_cases()]
if request.method == "POST":
suite_name = request.form.get("suite_name")
selected_cases = request.form.getlist("cases")
test_suite = unittest.defaultTestLoader.loadTestsFromNames(selected_cases)
with open(os.path.join(TEST_SUITE_DIR, f"{suite_name}.ts"), "wb") as f:
pickle.dump(test_suite, f)
return redirect("/")
return render_template("add_test_suite.html", cases=test_cases)
if __name__ == "__main__":
app.run()
템플릿 파일 예시 (templates/add_test_suite.html):
<!DOCTYPE html>
<html>
<head><title>테스트 세트 생성</title></head>
<body>
<h1>새로운 테스트 세트 만들기</h1>
<form method="post">
<input type="text" name="suite_name" placeholder="세트 이름"><br>
<h4>선택 가능한 테스트 항목:</h4>
{% for case in cases %}
<div><input type="checkbox" name="cases" value="{{ case }}">{{ case }}</div>
{% endfor %}
<button type="submit">저장</button>
</form>
</body>
</html>
테스트 실행 및 보고서 생성:
from HTMLTestReportCN import HTMLTestRunner
@app.route("/", methods=["GET", "POST"])
def list_test_suites():
test_suites = [f.split(".")[0] for f in os.listdir(TEST_SUITE_DIR) if f.endswith(".ts")]
if request.method == "POST":
selected_suite = request.form.get("suite")
with open(os.path.join(TEST_SUITE_DIR, f"{selected_suite}.ts"), "rb") as f:
test_suite = pickle.load(f)
report_path = os.path.join(APP_DIR, "reports", f"{selected_suite}_report.html")
with open(report_path, "wb") as f:
runner = HTMLTestRunner(stream=f, title="API 테스트 보고서")
runner.run(test_suite)
return redirect("/report")
return render_template("test_suites.html", suites=test_suites)
보고서 페이지:
@app.route("/report")
def show_report():
return render_template("report.html")