问题描述
我正在使用doctest测试.rst文件中的代码段。在许多情况下,最重要的测试是对yaml配置的简单有效性检查。
例如:
>>> my_yaml = """
... foo:
... bar:
... - baz1
... - baz2
... """
>>> my_yaml_dict = yaml.load(my_yaml_string,Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
为了使代码更具可读性和可粘贴性,我只想显示yaml块,并将测试本身放在隐藏的代码块中。
这有效:
>>> my_yaml = """
... foo:
... bar:
... - baz1
... - baz2
... """
.. invisible-code-block: python
>>> my_yaml_dict = yaml.load(my_yaml_string,Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
但是,yaml块仍封装在my_yaml="""..."""
中,这使得复制粘贴变得很困难。
是否有一种方法可以将代码块本身视为变量?我正在按照以下思路进行构想:
.. code-block:: yaml # doctest: +varname=my_yaml_string
foo:
bar:
- baz1
- baz2
.. invisible-code-block: python
>>> my_yaml_dict = yaml.load(my_yaml_string,Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
解决方法
根据文档,我认为不可以更改/跳过文档字符串定界符(>>>
和...
):
任何期望的输出必须立即跟随包含代码的最后'>>>'或'...'行,并且期望的输出(如果有的话)扩展到下一个'>>>'或全空白行。 https://docs.python.org/3/library/doctest.html#how-are-docstring-examples-recognized
另一种解决方案是将Yaml数据移动到外部变量,该变量在doctest块中未定义:
my_yaml_string = """
foo:
bar:
- baz1
- baz2
"""
然后可以直接在doctest块中使用上述变量:
>>> my_yaml_dict = yaml.load(my_yaml_string,Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
另外,可以在另一个模块中定义my_yaml_string
变量,以不影响运行时性能:
>>> import test_constants
>>> my_yaml_dict = yaml.load(test_constants.my_yaml_string,Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
此外,测试数据可以完全移动到单独的文件中。这样做还有一个好处,就是可以为所选的数据序列化语言(在本例中为Yaml)启用静态分析器覆盖范围:
# test_data.yaml
foo:
bar:
- baz1
- baz2
>>> my_yaml_dict = yaml.load(open("test_data.yaml"),Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
请注意,"test_data.yaml"
可能需要转换为绝对路径,这取决于doctest的执行方式。