带有树状数据的pytest嵌套参数化
pytest nested parametrization with tree-like data
使用 pytest,我正在尝试测试树状分层场景。
让我们以文档结构为例:
Document --- Chapter --- Paragraph
1 n 1 n
文档包含多个章节;一章包含多个段落。
开始测试新文档时,一些设置代码需要运行;当开始新的章节时,一些其他的设置代码需要运行;段落也一样。
写成伪代码:
for doc in documents:
setup_doc(doc)
for chapter in doc.chapters:
setup_chapter(chapter)
for paragraph in chapter.paragraphs:
setup_paragraph(paragraph)
test_it(doc, chapter, paragraph)
teardown_paragraph(paragraph)
teardown_chapter(chapter)
teardown_doc(doc)
如果我们有以下数据:
Document Alpha
chapter A
Paragraph A1
Paragraph A2
chapter B
Paragraph B1
我希望收集的测试用例是:
test_it[Alpha, A, A1]
test_it[Alpha, A, A2]
test_it[Alpha, B, B1]
我尝试了 pytest_generate_tests、class 场景、固定装置和参数化测试函数的不同组合,但未能实现。
任何指点将不胜感激。
Pytest fixutes 应该是独立的。
因此,要解决您的任务,您必须构建一个包含所有功能组合(文档 - 章节 - 段落)的简单列表的夹具。
您可以使用 returns 此类列表中的一个元素的简单装置来完成此操作,或者您可以在测试生成阶段生成此列表,如下面的代码所示。
documents = {
'Alpha': {
'A': {'A1': {},'A2': {}},
'B': {'B1': {}}
}
}
def pytest_generate_tests(metafunc):
"""Documents tree from documents"""
if 'document' in metafunc.fixturenames:
documents_plain = []
for document in documents.keys():
for chapter in documents[document].keys():
for paragraph in documents[document][chapter].keys():
documents_plain.append({'document': document, 'chapter': chapter, 'paragraph': paragraph})
metafunc.parametrize(
'document',
documents_plain,
scope='session')
def test_it(document):
print('{}, {}, {}'.format(document['document'], document['chapter'], document['paragraph']))
py.test -s
Alpha, B, B1
Alpha, A, A1
Alpha, A, A2
如果像我一样,您希望一些测试由 document
参数化,一些由 document
、chapter
参数化,还有一些由 document
、chapter
参数化,paragraph
我的方法(受安德烈·索罗金启发)如下
在conftest.py
import pytest
documents = {
'Alpha': {
'A': {'A1': {},'A2': {}},
'B': {'B1': {}}
}
}
def pytest_generate_tests(metafunc):
if 'document' in metafunc.fixturenames:
if 'chapter' in metafunc.fixturenames:
if 'paragraph' in metafunc.fixturenames:
metafunc.parametrize(
['document', 'chapter', 'paragraph'],
[(d, c, p) for d, cs in documents.items()
for c, ps in cs.items()
for p in ps.keys()
])
else:
metafunc.parametrize(
['document', 'chapter'],
[(d, c) for d, cs in documents.items()
for c in cs.keys()
])
else:
metafunc.parametrize(
'document', documents.keys())
然后在test.py
def test_d(document):
print(document)
def test_dc(document, chapter):
print(document, chapter)
def test_dcp(document, chapter, paragraph):
print(document, chapter, paragraph)
运行
>>> pytest test.py -s
test.py Alpha
.Alpha A
.Alpha B
.Alpha A A2
.Alpha A A1
.Alpha B B1
.
使用 pytest,我正在尝试测试树状分层场景。 让我们以文档结构为例:
Document --- Chapter --- Paragraph
1 n 1 n
文档包含多个章节;一章包含多个段落。
开始测试新文档时,一些设置代码需要运行;当开始新的章节时,一些其他的设置代码需要运行;段落也一样。
写成伪代码:
for doc in documents:
setup_doc(doc)
for chapter in doc.chapters:
setup_chapter(chapter)
for paragraph in chapter.paragraphs:
setup_paragraph(paragraph)
test_it(doc, chapter, paragraph)
teardown_paragraph(paragraph)
teardown_chapter(chapter)
teardown_doc(doc)
如果我们有以下数据:
Document Alpha
chapter A
Paragraph A1
Paragraph A2
chapter B
Paragraph B1
我希望收集的测试用例是:
test_it[Alpha, A, A1]
test_it[Alpha, A, A2]
test_it[Alpha, B, B1]
我尝试了 pytest_generate_tests、class 场景、固定装置和参数化测试函数的不同组合,但未能实现。
任何指点将不胜感激。
Pytest fixutes 应该是独立的。 因此,要解决您的任务,您必须构建一个包含所有功能组合(文档 - 章节 - 段落)的简单列表的夹具。
您可以使用 returns 此类列表中的一个元素的简单装置来完成此操作,或者您可以在测试生成阶段生成此列表,如下面的代码所示。
documents = {
'Alpha': {
'A': {'A1': {},'A2': {}},
'B': {'B1': {}}
}
}
def pytest_generate_tests(metafunc):
"""Documents tree from documents"""
if 'document' in metafunc.fixturenames:
documents_plain = []
for document in documents.keys():
for chapter in documents[document].keys():
for paragraph in documents[document][chapter].keys():
documents_plain.append({'document': document, 'chapter': chapter, 'paragraph': paragraph})
metafunc.parametrize(
'document',
documents_plain,
scope='session')
def test_it(document):
print('{}, {}, {}'.format(document['document'], document['chapter'], document['paragraph']))
py.test -s
Alpha, B, B1
Alpha, A, A1
Alpha, A, A2
如果像我一样,您希望一些测试由 document
参数化,一些由 document
、chapter
参数化,还有一些由 document
、chapter
参数化,paragraph
我的方法(受安德烈·索罗金启发)如下
在conftest.py
import pytest
documents = {
'Alpha': {
'A': {'A1': {},'A2': {}},
'B': {'B1': {}}
}
}
def pytest_generate_tests(metafunc):
if 'document' in metafunc.fixturenames:
if 'chapter' in metafunc.fixturenames:
if 'paragraph' in metafunc.fixturenames:
metafunc.parametrize(
['document', 'chapter', 'paragraph'],
[(d, c, p) for d, cs in documents.items()
for c, ps in cs.items()
for p in ps.keys()
])
else:
metafunc.parametrize(
['document', 'chapter'],
[(d, c) for d, cs in documents.items()
for c in cs.keys()
])
else:
metafunc.parametrize(
'document', documents.keys())
然后在test.py
def test_d(document):
print(document)
def test_dc(document, chapter):
print(document, chapter)
def test_dcp(document, chapter, paragraph):
print(document, chapter, paragraph)
运行
>>> pytest test.py -s
test.py Alpha
.Alpha A
.Alpha B
.Alpha A A2
.Alpha A A1
.Alpha B B1
.