Python单元测试异常:自动评分器仅执行1个测试用例求助
问题原因与解决方案
你的自动评分器仅运行1个测试用例,核心问题在于自定义的AutoGraderTest类仅封装了单个测试方法,且通过exec执行代码的方式没有正确识别测试文件中的所有test_*方法。以下是具体的问题分析和修复方案:
问题分析
- 自定义测试类的局限性:你定义的
AutoGraderTest只包含一个test_submission方法,unittest会将其视为单个测试用例,而非执行测试文件中所有的测试方法。 - exec执行方式的问题:直接用
exec运行测试代码和提交代码,无法将测试文件中的UnitTest类下的所有测试方法注册到测试套件中,导致仅能统计到一个测试用例。
修复后的代码
import os import unittest import importlib.util import sys class gradeCode: def __init__(self, submissions_path, unit_test_path, constraints_path): self.submissions_path = submissions_path self.unit_test_path = unit_test_path self.constraints_path = constraints_path def print_report(self, report): for student_report in report: student_id = student_report['file'] total_tests = student_report['total_tests'] successful_tests = student_report['successful_tests'] grade = student_report['grade'] report_str = '' report_str += f'\n Student ID: {student_id}' report_str += f'\n {successful_tests} of {total_tests} tests passed.' report_str += f'\n Grade: {grade:.2f}%' report_str += f'\n---------------------------------------------------' print(report_str) def run_test(self): report = [] # 动态加载测试模块 test_spec = importlib.util.spec_from_file_location('unit_test_module', self.unit_test_path) test_module = importlib.util.module_from_spec(test_spec) test_spec.loader.exec_module(test_module) test_class = test_module.UnitTest for submission in os.listdir(self.submissions_path): if submission.endswith('.py'): submission_path = os.path.join(self.submissions_path, submission) submission_name = submission.strip('.py') # 动态加载学生提交的代码,替换测试依赖的calculator模块 submission_spec = importlib.util.spec_from_file_location('calculator', submission_path) submission_module = importlib.util.module_from_spec(submission_spec) submission_spec.loader.exec_module(submission_module) sys.modules['calculator'] = submission_module # 收集测试类中所有test_*方法作为测试用例 suite = unittest.TestLoader().loadTestsFromTestCase(test_class) # 执行测试并统计结果 test_runner = unittest.TextTestRunner() test_results = test_runner.run(suite) total_tests = test_results.testsRun successful_tests = total_tests - len(test_results.failures) - len(test_results.errors) grade = (successful_tests / total_tests) * 100 if total_tests > 0 else 0 submission_results = { 'file': submission_name, 'grade': grade, 'total_tests': total_tests, 'successful_tests': successful_tests } report.append(submission_results) # 清理模块缓存,避免影响下一个学生的测试 del sys.modules['calculator'] self.print_report(report) return report
关键改进点
- 动态模块加载:使用
importlib.util替代exec,正确加载测试模块和学生提交的代码,解决测试文件中from calculator import Calculator的依赖问题。 - 自动收集测试用例:通过
unittest.TestLoader().loadTestsFromTestCase(test_class)自动识别测试类中所有的test_*方法,确保所有测试用例被执行。 - 模块缓存清理:每次测试完成后删除
sys.modules中的calculator模块,避免不同学生的代码相互干扰。
内容的提问来源于stack exchange,提问作者Sanjae Suresh
相关产品推荐
相关产品推荐

