Testing Python动态测试计划生成

Testing Python动态测试计划生成,testing,pytest,python-sphinx,Testing,Pytest,Python Sphinx,我使用Sphinx进行文档编制,使用pytest进行测试。 我需要生成一个测试计划,但我真的不想手动生成 我突然想到,一个简洁的解决方案是将测试元数据实际嵌入到测试本身中,嵌入到它们各自的docstring中。此元数据将包括完成百分比、剩余时间等内容。然后,我可以运行所有测试(此时主要包括占位符),并从中生成测试计划。这将保证测试计划和测试本身是同步的 我想做一个pytest插件或者sphinx插件来处理这个问题 使用pytest,我能看到的最近的钩子看起来像pytest\u collectio

我使用Sphinx进行文档编制,使用pytest进行测试。 我需要生成一个测试计划,但我真的不想手动生成

我突然想到,一个简洁的解决方案是将测试元数据实际嵌入到测试本身中,嵌入到它们各自的docstring中。此元数据将包括完成百分比、剩余时间等内容。然后,我可以运行所有测试(此时主要包括占位符),并从中生成测试计划。这将保证测试计划和测试本身是同步的

我想做一个pytest插件或者sphinx插件来处理这个问题

使用pytest,我能看到的最近的钩子看起来像
pytest\u collection\u modifyitems
,它在收集所有测试之后被调用

或者,我正在考虑使用Sphinx,或者复制/修改todolist插件,因为它似乎最符合这个想法。这个插件的输出会更有用,因为输出会很好地插入到我现有的基于Sphinx的文档中,尽管这个插件中有很多内容,我没有时间去理解它

docstrings中可能包含以下内容:

:plan_complete: 50 #% indicator of how complete this test is
:plan_remaining: 2 #the number of hours estimated to complete this test
:plan_focus: something #what is the test focused on testing
其思想是基于函数名、docstring和嵌入的计划信息生成一个简单的markdown/rst或类似的表,并将其用作测试计划


这样的事情已经存在了吗

最后,我使用了一个基于
pytest
的插件,因为它的编码非常简单

如果其他人感兴趣,以下是插件:

根据从测试中提取的元数据生成测试计划表的模块 文档字符串。测试描述从第一句话中提取,最多可提取到 第一个空行。从docstring中提取的数据是 格式: :测试剩余时间:完成此测试剩余的10小时数。如果 不存在,假定为0 :test_complete:#已完成测试的百分比。如果未完成 现在,假设是100 :test\u focus:测试关注的项目,例如DLL调用。 """ 导入pytest 进口稀土 从functools导入部分 从运算符导入itemgetter 从pathlib导入路径 空格\u re=re.compile(r'\s+') cut_whitespace=partial(whitespace_re.sub.)) 计划\u re=re.compile(r):计划(\w+?):') 计划处理程序={ “剩余”:lambda x:int(x.split(“#”)[0]), “完成”:lambda x:int(x.strip().split(“#”)[0]), “焦点”:lambda x:x.strip().split(“#”)[0] } csv_template=“”。csv表格::测试计划 :标题:“名称”、“焦点”、“完成”、“剩余小时数”、“说明”、“路径” :宽度:20、20、10、10、60、100 {tests} 总剩余小时数:{剩余小时数:.2f} 总完成百分比:{complete:.2f} """ 类生成计划: def uu init uu(self,output_file=Path('test_plan.rst')): self.output\u file=输出文件 def pytest_集合_修改项(自身、会话、配置、项): #断点() items_to_parse={i.nodeid.split('[')[0]:self.item_过滤器(items)中的i代表i} #parsed=map(解析_项,项到_parse.items()) parsed=[self.parse_items(n,i)for items_to_parse.items()中的(n,i)] 完成,剩余小时数=自身。获取摘要数据(已解析) self.output_file.write_text(csv_template.format( tests='\n'.join(self.generate_rst_table(已解析)), 完成, 剩余小时数=剩余小时数) def项目过滤器(自身,项目): 退货项目#覆盖我 def get_summary_数据(自解析): completes=[p['complete']表示解析后的p] 总体完成=总和(完成)/len(完成) 总时数剩余=总和(p[‘剩余’]表示解析后的p) 返回总完成时间、总剩余时间 def生成表格(自身,项目): “为了简单起见,请使用CSV类型” 已排序的\u项=已排序(项,项=lambda x:x['name']) quoter=lambda x:“{}”。格式(x) getter=itemgetter(*“名称焦点完成剩余描述路径”.split()) 对于已排序项目中的项目: 产生3*''+'','.join(映射(引用、获取(项))) def parse_项(自身、路径、项): “处理pytest提供的项目” 数据={ “名称”:item.name.split(“[”)[0], “路径”:path.split(“:”)[0], “描述”:“, “剩余”:0, “完成”:100, “焦点”:“ } 单据=项目功能。\u单据__ 如果文件: desc=自我提取描述(doc) 数据['description']=desc 计划信息=自身提取信息(单据) 数据更新(计划信息) 返回数据 def提取描述(自我、文档): 第一句话=doc.split('\n\n')[0]。替换('\n','') 返回剪切空白(第一句) def提取信息(自我、文档): 计划信息={} 对于文档拆分('\n\n')中的子字符串: 已清理=剪切空白(子结构替换('\n','') 拆分=计划重新拆分(已清理) 如果len(拆分)>1: i=iter(拆分[1:])#拆分器从索引1开始 尽管如此: 尝试: 键=下一个(i) val=下一个(i) 除停止迭代外: 打破 断言键 如果输入plan_处理程序: 计划信息[键]=计划处理程序[键](val) 退货计划信息 从我的
conftest.py
文件中,我在
pytest\u addoption函数中配置了一个命令行参数:
parser.addoption('--generate\u test\u plan',action='store\u true',default=False,help=“generate test p
Autogenerated test_plan
=======================

The below test_data is extracted from the individual tests in the suite.

.. include:: test_plan.rst


def my_test():
    """
    .. test:: My test case
       :id: TEST_001
       :status: in progress
       :author: me

       This test case checks for **awesome** stuff.
    """
    a = 2
    b = 5
    # ToDo: chek if a+b = 7
My tests
========

.. automodule:: test.my_tests:
   :members:
.. test-report: My Test report
   :id: REPORT_1
   :file: ../pytest_junit_results.xml
   :links: [[tr_link('case_name', 'signature')]]