为多个 Python 文件编写单元测试
Posted
技术标签:
【中文标题】为多个 Python 文件编写单元测试【英文标题】:Writing a unit test for multiple Python files 【发布时间】:2020-05-28 09:54:18 【问题描述】:我正在尝试编写一个测试程序来测试许多(相同的)学生作业。我有一个使用unittest library 编写的测试。该文档似乎表明每个测试都应与一个文件相关联。相反,我想要一个测试文件并使用命令行参数将测试指向它应该测试的文件。
我知道我可以通过在单元测试中使用argparse 模块来做到这一点,但有没有更好的方法?似乎应该在 unittest 中支持这种行为,但我在文档中找不到任何内容...
【问题讨论】:
作业有什么要求? 我的答案取决于您要准确测试的内容。 @ReinstateMonica 作业要求学生从标准输入(stdin)获取输入(str),进行一些计算,并将适当的值(str)返回到标准输出。我设计的测试将给定的文件(目前是硬编码的)作为子进程运行,并使用 subprocess.communicate 进行 IPC(进程间通信)。 【参考方案1】:创建主测试目录并添加子测试包。为您创建一个指向测试目录的测试运行程序。它可以作为一个套件。我附上了一段用于我的测试套件的代码。
import os
import unittest
def main(test_path, test_pattern):
print(('Discovering tests in : '.format(test_path)))
suite = unittest.TestLoader().discover(test_path, test_pattern)
unittest.TextTestRunner(verbosity=2).run(suite)
if __name__ == '__main__':
root_path = os.path.abspath('.')
test_path = os.path.join(root_path, 'src/tests/')
test_pattern = 'test_*'
main(test_path, test_pattern)
【讨论】:
谢谢,我今天晚些时候试试。【参考方案2】:一般来说,unittest 用于测试模块级别的python 代码,而不是 python 代码与外部程序的交互。 AFAIK,写入标准输出(即打印)意味着您正在调试或将信息传递给另一个程序。
在您的情况下,我认为 unittest 并不是真正必要的,除非您想分配“通过此单元测试”的作业(这在野外很常见)。
相反,我会简单地遍历包含分配的目录,使用子进程检查标准输出,然后将结果写入 csv 文件:
import subprocess
import os
import csv
ASSIGNMENT_DIR = '/path/to/assignments'
expected_stdout = 'Hello World!'
def _determine_grade(stdout):
if stdout == expected_stdout:
return '100%'
return '0%'
grades =
for assignment in os.listdir(ASSIGNMENT_DIR):
filepath = os.path.join(ASSIGNMENT_DIR, assignment)
stdout = subprocesss.check_output(f'python3 filepath', shell=True)
grade = _determine_grade(stdout)
grades.append('assignment':assignment, 'grade':grade)
with open('/path/to/grades.csv', 'w+') as f:
w = csv.DictWriter(f, ('assignment', 'grade'))
w.writeheader()
w.writerows(grades)
【讨论】:
这也可以很容易地规范化以处理任何作业,如果你愿意,我可以向你展示。 感谢您的回答。我同意这很好用。我决定使用 unittest 的原因是学生的代码可能在某些情况下有效,而在其他情况下无效。因此,我有几个测试用例要在每个作业上运行,每个测试用例检查不同类型的错误。一旦定义了测试用例,unittest 会自动运行所有测试用例,并以格式良好的方式报告每个测试的结果,这是我不必编写的大量样板文件。未来,我想给我的学生测试自己跑,增加一种“现实感”。以上是关于为多个 Python 文件编写单元测试的主要内容,如果未能解决你的问题,请参考以下文章