Dev Study
← 開発の実務
レッスン 12 / 12·約 9 分·第16期 開発の実務

期待する出力が書けないとき、何と比べるか

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

前回は、戻せるのはコードでデータではないことを見ました。最終回は、比べる相手である期待する出力そのものが書けない場合を扱います。

まず結論

正しい出力を人が前もって書けない処理があります。そのとき比べられるのは、1回の実行の入力と出力の関係と、複数回の実行同士の関係です。

どちらも正しい出力を保証しない部分的な判定手順で、関係を満たす誤りは通ります。それでも「観測できない」を「誤りの一部は観測できる」に変える手です。

? 読む前に予測

商品の絞り込み検索をテストしたいが、どの条件で何件返るのが正しいかを人が前もって書けない。期待する出力を書かずに誤りを検出できる検査はどれか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

比べる相手が、誰にも書けないとき

このコースの芯は「壊れていない」は何と比べたかでしか言えない、でした。これまでは比べる相手を人が用意できました。期待する出力、前のコミット、きれいな機械。この回は、その相手を誰も前もって書けない場合です。

Barr らのサーベイは、そうしたプログラムを non-testable programs と呼ぶ定義を Weyuker の1982年の論文から引いています(Weyuker の本文は未確認で、Barr らを通した孫引きです)。

“Programs which were written in order to determine the answer in the first place. There would be no need to write such programs, if the correct answer were known.” [196].

答えを知りたくて書いたのだから、答えは手元に無い。Chen らの1998年の報告も、arXiv 掲載の抄録で判定手順(引用内の test oracles)が手に入ることを実用上ほぼ望めないとする Weyuker の指摘を挙げます。

Thirdly, as indicated by Weyuker in [6], the availability of test oracles is pragmatically unattainable in most situations.

正しい出力が無いなら、比べる相手を変えます。候補は2つです。

  1. 1回の実行の入力と出力の関係。 fast-check は性質(property)を a relationship between a code's input and output which should hold for all sets of inputs と定義します。
  2. 複数回の実行同士の関係。 Barr らはメタモルフィック関係を a relation over applications of f that we expect to hold across multiple executions of p と定義します。

後者は正しい出力と比べる代わりに、実行と実行を比べます。

期待する出力が無いときの、比べる相手
入力乱数で大量に作れる
正しい出力は誰も書けない
性質1回の実行の入力と出力の関係
メタモルフィック関係2回以上の実行の間の関係
どちらも部分的
関係を破る誤りは見つかる反例が出る
関係を満たす誤りは通る正しさの保証ではない
  • ・性質もメタモルフィック関係も、書いた関係しか見ない
  • ・並べ替えと絞り込みの例は教材用に作ったもので、Chen らのメタモルフィックテストの例ではない
具体実物

並べ替えを、答えを書かずに検査する

Python 3.14.6(macOS 26.5.2)で、標準ライブラリだけの検査を書きました。乱数の種を固定しているので毎回同じ結果になり、2回の実行で出力は完全に一致しています。

並べ替えに期待する出力は書きません。代わりに2つの性質を、200回ぶんの乱数の入力で確かめます。隣り合う2つが a <= b(並んでいる)と、入力と出力で各要素の個数が同じ(元の要素の並べ替えである)です。誤った実装として、重複を落とす sorted(set(xs)) を用意しました。

$ python3 demo12_props.py(並べ替えの3行)コマンド出力
sort_ok : OK 200 trials
sort_dedup : NG trial=1 元の要素の並べ替えになっていない xs=[1, 7, 7, 7] ys=[1, 7]
(並び順だけ検査した場合) sort_dedup: True

誤った実装は2つ目の性質で落ちました。ところが3行目、別に作った50個の入力で並び順だけを確かめると True です。[1, 7] は並んでいます。消えた要素は、並び順の性質には映りません。

✓ ここまでの確認

重複を落とす並べ替え実装を、「隣り合う2つが a <= b」という性質だけで検査するとどうなりますか。

抽象原理

実行と実行を比べる

並べ替えの性質は、1回の実行の中で閉じていました。出力が何であるべきかを入力だけから言えない処理もあります。検索がそうです。

それでも、2回の実行の結果の間なら言えることがあります。条件を1つ足した検索の結果は、足す前の結果に含まれるはずです。Barr らは、メタモルフィック関係が数式で書ける数値の性質に限られないと書き、検索エンジンを検査した Zhou らの関係を紹介しています。

Barr らが挙げる関係(ROR と名付けられたもの)は、検索が返すページの集合(where the Ai are sets of web pages returned by queries)について、A1 が A2 と A3 の和集合なら A2 の件数は A1 を超えない、というものです。この回の絞り込みの関係に近い例です。

具体実物

絞り込みで、関係が捕まえるもの・捕まえないもの

同じスクリプトで、5件の商品に対する絞り込みを検査しました。乱数で条件 c1 を選び、そこに条件を1つ足して c2 を作り、「c2 の結果 ⊆ c1 の結果」を200回確かめます。正しい件数はどこにも書いていません。

$ python3 demo12_props.py(絞り込みの3行)コマンド出力
search_ok : OK 200 trials
search_or : NG trial=0 条件を足したのに結果が増えた {'color': 'red'}->[1, 3, 4] / {'color': 'red', 'size': 'S'}->[1, 3, 4, 5]
search_empty: OK 200 trials (関係は満たすので検出できない)

2行目は、条件を OR で扱う誤った実装です。赤で3件、赤かつ S で4件に増えました(正しい AND なら [1])。

3行目は、常に空を返す実装が通ったことを示します。空は何の部分集合でもあるので、関係は満たされます。関係が比べているのは2回の実行の間の整合であって、どちらの結果の正しさでもありません。

✓ ここまでの確認

常に空のリストを返す検索実装は、「条件を足した結果 ⊆ 足す前の結果」の検査でどうなりますか。

⇄ 2つを見比べる
具体例 A

並べ替えの性質(1回の実行)

入力と出力の関係を2つ書きました。並び順だけなら重複を落とす実装が通り、要素の個数を足すと落ちました。関係の足りない分が、そのまま検査の穴になります。

書いた性質と、捕まえた誤り表
性質 重複を落とす実装
隣り合う2つが a <= b 通る
各要素の個数が同じ 落ちる
具体例 B

絞り込みの関係(2回の実行)

条件を足した結果が足す前の結果に含まれるかを比べました。OR で扱う実装は落ち、常に空を返す実装は通りました。関係は2回の結果の整合しか見ません。

書いた関係と、捕まえた誤り表
実装 c2 の結果 ⊆ c1 の結果
OR で扱う 落ちる
常に空を返す 通る

1回の実行の関係と、2回の実行の関係。比べ方は違いますが、どちらにも共通する限界は何でしょうか。

それぞれの表で「通る」と書かれた行が、なぜ通ったのかを見てください。

この章のまとめ

  • 正しい出力を前もって書けない処理がある。Barr らは Weyuker 1982 を引いて non-testable programs と呼ぶ(孫引き)。
  • そのときの比べる相手は、**1回の実行の入力と出力の関係(性質)**か、複数回の実行同士の関係(メタモルフィック関係)。混ぜない。
  • 並べ替えは「並んでいる」だけでは足りない。重複を落とす実装が通った。
  • 絞り込みは「条件を足した結果 ⊆ 足す前の結果」で OR の誤りを捕まえたが、常に空を返す実装は通った。
  • どちらも部分的な判定手順。緑は「書いた関係を、試した入力で破らなかった」まで。
  • 序章に戻ると、これは観測できない領域に当てる観測器を1つ増やす手。何と比べるかを決めるのは、最後まで人。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

fast-check の文書が定義する「性質」と、Barr らが定義するメタモルフィック関係の違いとして正しいのはどれか。

用語集(4語)
性質(property)
すべての入力で成り立つはずの、入力と出力の関係。fast-check は `an assertion of a relationship between a code's input and output which should hold for all sets of inputs` と定義する。1回の実行の中の関係。
メタモルフィック関係
複数回の実行の間で成り立つはずの関係。Barr らの定義に従う。この回の例では「条件を足した検索の結果は、足す前の結果に含まれる」。
判定手順
このコースの言い方。実行結果が正しいか誤っているかを決める手順。英語の文献では test oracle と呼ぶ。
non-testable programs
答えを知るために書かれたので、正しい答えを前もって知りようがないプログラム。Barr らが Weyuker 1982 を出典として引く語。