可測試的文件字串
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 邏輯使用了一些自訂設定
- 它不會將浮點值當做文字比較:浮點值會從文字中擷取出來,並使用寬鬆的
atol
和rtol
容差搭配allclose
進行比較。這樣可以- 更清楚的文件 - 作者不需要包含所有小數位數。
- 更穩健的測試 - 底層實作中的數值變更絕不應導致 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 會從結果字串中擷取浮點值,並使用合理的容差 (
atol=1e-6
、rtol=1e-6
) 搭配np.allclose
進行比較。這樣一來,作者就不必擔心過於精確的文件字串會因數值問題而導致失敗。只要貼上預期的值即可。非決定性輸出:針對不確定的部分使用省略符號 (
...
),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
--module
相對於tensorflow.python
。