Kiểm Thử Hàm Xử Lý Chuỗi
Xét một hàm utility có nhiệm vụ ghép tên và họ thành một chuỗi hoàn chỉnh. Hàm này sẽ chèn khoảng trắng ở giữa và viết hoa ký tự đầu tiên của mỗi từ trước khi trả về kết quả. Để linh hoạt hơn, hàm cũng hỗ trợ thêm tên đệm tùy chọn.
utils_name.py
def combine_names(fname, lname, mname=''):
"""Tạo ra chuỗi tên đầy đủ đã định dạng."""
if mname:
complete_name = fname + ' ' + mname + ' ' + lname
else:
complete_name = fname + ' ' + lname
return complete_name.title()
Đoạn script dưới đây minh họa cách sử dụng hàm trên trong môi trường tương tác:
run_names.py
from utils_name import combine_names
print("Nhập 'q' để thoát bất cứ lúc nào.")
while True:
fname = input("\nNhập tên: ")
if fname == 'q':
break
lname = input("Nhập họ: ")
if lname == 'q':
break
result = combine_names(fname, lname)
print(f"\n\tTên đầy đủ: {result}.")
Nguyên Lý Kiểm Thử Đơn Vị
Thư viện chuẩn unittest của Python cung cấp các công cụ cần thiết để xác minh tính đúng đắn của mã nguồn. Một bài kiểm thử đơn vị (unit test) nhằm xác nhận một khía cạnh cụ thể của hàm hoạt động chính xác. Tập hợp các bài kiểm thử đơn vị tạo thành một trường hợp kiểm thử (test case), giúp đảm bảo hàm xử lý đúng trong nhiều tình huống khác nhau. Một trường hợp kiểm thử tốt cần bao quát các đầu vào tiềm năng mà hàm có thể nhận.
Để xây dựng kịch bản kiểm thử, cần导入模块 unittest cùng hàm mục tiêu, sau đó định nghĩa một lớp kế thừa từ unittest.TestCase. Bên trong lớp này, các phương thức bắt đầu bằng tiền tố test_ sẽ được thực thi tự động.
verify_utils.py
import unittest
from utils_name import combine_names
class NameUtilsTest(unittest.TestCase):
"""Kiểm tra các hàm trong utils_name.py"""
def test_simple_name_format(self):
"""Kiểm tra định dạng tên cơ bản như 'Janis Joplin'"""
formatted = combine_names('janis', 'joplin')
self.assertEqual(formatted, 'Janis Joplin')
def test_name_with_middle(self):
"""Kiểm tra trường hợp có tên đệm"""
formatted = combine_names('wolfgang', 'mozart', 'amadeus')
self.assertEqual(formatted, 'Wolfgang Amadeus Mozart')
if __name__ == '__main__':
unittest.main()
Lớp NameUtilsTest chứa các phương thức kiểm tra hành vi của hàm. Khi chạy file này, mọi phương thức bắt đầu bằng test_ sẽ được gọi. Chúng ta sử dụng các phương thức khẳng định (assertion) như assertEqual để so sánh kết quả thực tế với giá trị kỳ vọng.
Kiểm Thử Lớp Đối Tượng
Thư viện unittest cung cấp nhiều phương thức khẳng định khác nhau trong lớp TestCase. Xét một lớp dùng để thu thập phản hồi ẩn danh.
feedback.py
class FeedbackBox:
"""Quản lý thu thập câu trả lời khảo sát"""
def __init__(self, prompt):
"""Khởi tạo câu hỏi và danh sách chứa câu trả lời"""
self.prompt = prompt
self.submissions = []
def display_prompt(self):
"""In câu hỏi khảo sát"""
print(self.prompt)
def add_submission(self, answer):
"""Thêm một câu trả lời mới vào danh sách"""
self.submissions.append(answer)
def display_results(self):
"""Hiển thị tất cả câu trả lời đã thu thập"""
print("Kết quả khảo sát:")
for ans in self.submissions:
print(f"- {ans}")
Script sử dụng lớp này sẽ tạo một thể hiện, hiển thị câu hỏi và lưu trữ các đầu vào từ người dùng.
run_feedback.py
from feedback import FeedbackBox
query = "Bạn học ngôn ngữ nào đầu tiên?"
survey = FeedbackBox(query)
survey.display_prompt()
print("Nhập 'q' để kết thúc.\n")
while True:
ans = input("Ngôn ngữ: ")
if ans == 'q':
break
survey.add_submission(ans)
print("\nCảm ơn đã tham gia!")
survey.display_results()
Xây Dựng Test Case Cho Lớp
Để kiểm tra lớp FeedbackBox, ta tạo một lớp kiểm thử kế thừa unittest.TestCase. Phương thức đầu tiên sẽ xác minh rằng một câu trả lời đơn lẻ được lưu trữ chính xác.
test_feedback.py
import unittest
from feedback import FeedbackBox
class FeedbackBoxTest(unittest.TestCase):
"""Kiểm tra lớp FeedbackBox"""
def test_verify_single_submission(self):
"""Đảm bảo một câu trả lời đơn lẻ được lưu đúng"""
question = "Bạn học ngôn ngữ nào đầu tiên?"
poll = FeedbackBox(question)
poll.add_submission('English')
self.assertIn('English', poll.submissions)
def test_verify_multiple_submissions(self):
"""Đảm bảo nhiều câu trả lời được lưu đúng"""
question = "Bạn học ngôn ngữ nào đầu tiên?"
poll = FeedbackBox(question)
answers = ['English', 'Spanish', 'Mandarin']
for ans in answers:
poll.add_submission(ans)
for ans in answers:
self.assertIn(ans, poll.submissions)
if __name__ == '__main__':
unittest.main()
Tối Ưu Hóa Với Phương Thức setUp()
Phương thức setUp() giúp khởi tạo đối tượng và dữ liệu chung cho tất cả các phương thức kiểm thử trong lớp. Các biến lưu trữ trong self sẽ có thể truy cập ở mọi nơi within the class, giúp mã nguồn gọn gàng hơn.
import unittest
from feedback import FeedbackBox
class FeedbackBoxTest(unittest.TestCase):
"""Kiểm tra lớp FeedbackBox"""
def setUp(self):
"""Khởi tạo khảo sát và danh sách câu trả lời mẫu"""
question = "Bạn học ngôn ngữ nào đầu tiên?"
self.poll = FeedbackBox(question)
self.sample_answers = ['English', 'Spanish', 'Mandarin']
def test_verify_single_submission(self):
"""Kiểm tra một câu trả lời đơn lẻ"""
self.poll.add_submission(self.sample_answers[0])
self.assertIn(self.sample_answers[0], self.poll.submissions)
def test_verify_multiple_submissions(self):
"""Kiểm tra nhiều câu trả lời"""
for ans in self.sample_answers:
self.poll.add_submission(ans)
for ans in self.sample_answers:
self.assertIn(ans, self.poll.submissions)
if __name__ == '__main__':
unittest.main()
Khi thực thi, nếu kiểm thử thành công, hệ thống sẽ hiển thị dấu chấm (.). Nếu có lỗi exception, ký tự E sẽ xuất hiện. Nếu assertion thất bại, ký tự F sẽ được in ra.