可测试的文档字符串
TensorFlow 使用 DocTest 测试 Python 文档字符串中的代码片段。该片段必须是可执行的 Python 代码。要启用测试,请在行首添加 >>>
(三个左尖括号)。例如,以下是 tf.concat
函数在 array_ops.py 源文件中的摘录
def concat(values, axis, name="concat"):
"""Concatenates tensors along one dimension.
...
>>> t1 = [[1, 2, 3], [4, 5, 6]]
>>> t2 = [[7, 8, 9], [10, 11, 12]]
>>> concat([t1, t2], 0)
<tf.Tensor: shape=(4, 3), dtype=int32, numpy=
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]], dtype=int32)>
<... more description or code snippets ...>
Args:
values: A list of `tf.Tensor` objects or a single `tf.Tensor`.
axis: 0-D `int32` `Tensor`. Dimension along which to concatenate. Must be
in the range `[-rank(values), rank(values))`. As in Python, indexing for
axis is 0-based. Positive axis in the rage of `[0, rank(values))` refers
to `axis`-th dimension. And negative axis refers to `axis +
rank(values)`-th dimension.
name: A name for the operation (optional).
Returns:
A `tf.Tensor` resulting from concatenation of the input tensors.
"""
<code here>
要评估参考文档质量,请参阅 TensorFlow 2 API 文档建议 的示例部分。(请注意,此表格上的任务跟踪器不再使用。)
使用 DocTest 使代码可测试
目前,许多文档字符串使用反引号 (```) 来标识代码。要使用 DocTest 使代码可测试
- 删除反引号 (```) 并使用左括号 (>>>) 放在每行前面。在续行前面使用 (...)。
- 添加一个换行符以将 DocTest 代码片段与 Markdown 文本分隔开,以便在 tensorflow.org 上正确呈现。
自定义
TensorFlow 对内置 doctest 逻辑进行了一些自定义
- 它不将浮点值作为文本进行比较:浮点值从文本中提取,并使用
allclose
进行比较,具有宽松的atol
和rtol
容差。这允许- 更清晰的文档 - 作者无需包含所有小数位。
- 更健壮的测试 - 底层实现中的数值更改永远不会导致 doctest 失败。
- 它只在作者为某一行包含输出时才检查输出。这允许更清晰的文档,因为作者通常不需要捕获无关的中间值以防止它们被打印。
文档字符串注意事项
- 总体:doctest 的目标是提供文档,并确认文档有效。这与单元测试不同。所以
- 保持示例简单。
- 避免长或复杂的输出。
- 如果可能,使用四舍五入的数字。
- 输出格式:代码片段的输出需要直接放在生成该输出的代码下方。此外,文档字符串中的输出必须与代码执行后的输出完全相同。请参阅上面的示例。此外,请查看 DocTest 文档中的这部分。如果输出超过 80 行限制,您可以将额外的输出放在新行上,DocTest 将识别它。例如,请参阅下面的多行块。
- 全局变量:
`tf`
、np
和os
模块始终在 TensorFlow 的 DocTest 中可用。 使用符号:在 DocTest 中,您可以直接访问在同一文件中定义的符号。要使用当前文件中未定义的符号,请使用 TensorFlow 的公共 API
tf.xxx
而不是xxx
。正如您在下面的示例中看到的,`random.normal`
通过`tf.random.normal`
访问。这是因为`random.normal`
在NewLayer
中不可见。def NewLayer(): """This layer does cool stuff. Example usage: >>> x = tf.random.normal((1, 28, 28, 3)) >>> new_layer = NewLayer(x) >>> new_layer <tf.Tensor: shape=(1, 14, 14, 3), dtype=int32, numpy=...> """
浮点值:TensorFlow doctest 从结果字符串中提取浮点值,并使用
np.allclose
进行比较,具有合理的容差 (atol=1e-6
,rtol=1e-6
)。这样,作者就不需要担心过于精确的文档字符串因数值问题而导致失败。只需粘贴预期值即可。非确定性输出:对不确定的部分使用省略号 (
...
),DocTest 将忽略该子字符串。x = tf.random.normal((1,))
print(x)
<tf.Tensor: shape=(1,), dtype=float32, numpy=..., dtype=float32)>
多行块:DocTest 对单行语句和多行语句之间的区别很严格。请注意下面 (...) 的用法
if x > 0:
print("X is positive")
model.compile(
loss="mse",
optimizer="adam")
异常:除了引发的异常外,异常详细信息将被忽略。有关更多详细信息,请参阅 此处。
np_var = np.array([1, 2])
tf.keras.backend.is_keras_tensor(np_var)
Traceback (most recent call last):
ValueError: Unexpectedly found an instance of type `<class 'numpy.ndarray'>`.
使用项目本地副本的 tf-doctest。
TensorFlow 中的一些 API 来自外部项目
tf.estimator
(来自 tensorflow_estimator)tf.summary
tensorboard)tf.keras.preprocessing
(来自 keras-preprocessing)
如果您正在处理外部项目,或者正在处理位于外部项目的 TensorFlow API,那么这些说明将不起作用,除非该项目有自己的本地副本的 tf_doctest
,并且您使用该副本而不是 TensorFlow 的副本。
在本地机器上测试
有两种方法可以在本地测试文档字符串中的代码
如果您只更改类/函数/方法的文档字符串,那么您可以通过将该文件的路径传递给 tf_doctest.py 来测试它。例如
python tf_doctest.py --file=<file_path>
这将使用您安装的 TensorFlow 版本运行它。为了确保您运行的代码与您测试的代码相同
- 使用最新的 tf-nightly
pip install -U tf-nightly
- 将您的拉取请求重新绑定到来自 TensorFlow 主分支的最新拉取请求。
- 使用最新的 tf-nightly
如果您正在更改类/函数/方法的代码和文档字符串,则需要 从源代码构建 TensorFlow。一旦您设置好从源代码构建,您就可以运行测试
bazel run //tensorflow/tools/docs:tf_doctest
或
bazel run //tensorflow/tools/docs:tf_doctest -- --module=ops.array_ops
The
--module
is relative totensorflow.python
.