如何用unittest为GitHub Classroom的多输入Mad Libs Generator作业实现自动批改
基于unittest实现Mad Libs Generator自动批改的方案
核心逻辑是通过模拟标准输入流传递多组测试输入,同时捕获程序输出和预期结果对比,全程不需要修改学生的作业代码结构,只要提前约定好提交规范即可。
1. 提前约定学生提交规范
- 学生的Mad Libs Generator代码必须保存在名为
mad_libs.py的文件中 - 程序所有输入通过标准输入(Python内置
input()函数)获取,最终生成的完整故事通过标准输出(print()函数)打印 - 输入接收顺序固定,比如按「形容词→名词→动词→副词」的约定顺序读取,不能随意调整顺序
2. 编写自动批改单元测试代码
测试文件命名为test_mad_libs.py,GitHub Classroom会自动执行该文件完成评分:
import unittest import sys from io import StringIO from unittest.mock import patch # 自定义多组测试用例,格式为:(输入参数列表, 预期输出的故事内容片段) TEST_CASES = [ ( ["软乎乎的", "柯基", "蹦", "欢快地"], "路边有一只软乎乎的柯基欢快地蹦到了我脚边" ), ( ["圆滚滚的", "熊猫", "爬", "慢悠悠地"], "园子里有一只圆滚滚的熊猫慢悠悠地爬到了竹子上" ), # 可自行添加更多测试用例,覆盖边界场景 ] class TestMadLibs(unittest.TestCase): def test_all_input_cases(self): # 遍历所有测试用例,单个用例失败不会中断整体测试 for input_list, expected_story in TEST_CASES: with self.subTest(input_group=input_list): # 模拟多轮输入:将输入列表按换行拼接,对应多次input()调用 with patch('builtins.input', side_effect=input_list): # 捕获程序的所有输出 output_buffer = StringIO() with patch('sys.stdout', new=output_buffer): # 重载学生代码模块,避免缓存导致仅执行一次的问题 if 'mad_libs' in sys.modules: import importlib importlib.reload(sys.modules['mad_libs']) else: import mad_libs actual_output = output_buffer.getvalue().strip() # 断言判断输出是否符合预期,assertIn可兼容学生额外打印输入提示的场景 self.assertIn(expected_story, actual_output, msg=f"输入组{input_list}测试失败,输出内容不符合要求") if __name__ == '__main__': unittest.main()
小提示:如果要求学生输出完全匹配(包括输入提示语、换行格式等),把
assertIn替换为assertEqual,同时调整测试用例中的预期内容为完整输出即可。
3. 配置GitHub Classroom自动评分规则
- 在作业的评分配置页,设置自动执行命令为
python -m unittest test_mad_libs.py - 可按测试用例数量拆分分值,比如10组测试用例每组占10分,通过多少组对应得多少分
- 可将测试用例拆分为公开用例和私有用例:公开用例给学生做本地调试参考,私有用例不对外公开,避免学生硬编码测试结果作弊
内容的提问来源于stack exchange,提问作者Hariienesh Arumugam
相关产品推荐
相关产品推荐

