<< 前 ホーム 次 >>

bakaid: 200612271

マヌケなことに、今ごろになって小林『野良犬』聡の
引退を知る。嗚呼。

--

http://www.cs.princeton.edu/~bwk/testing.html

あれ? ;login:ってまだ発行してるんだ。

これから読む。

しかし、Kernighan氏に教えてもらうとは、なんとも
幸せな話だなあ。まぁ、学生の諸君にとって、それが
どれだけ幸せなことかはわからないだろうけど。

ダイクストラかく語りき。『テストを実施することに
よってバグを見つけることはできるが、それをもって
してバグが存在していないとはいえない』。

(以降、『テストの実施』を『テスティング』とする)

しかし、Kernighanは、『テスティングを考えている
プログラマは、そもそもが正しいコードを書くようだ』
と考えている。

(以降、『Kernighan』を『K氏』とする)

K氏がテスティングに興味を持ったのは、Awkがきっかけ
だった。Awkのために1000以上のテストを作り出し、
それらの実施は自動化されていた。

自動テストというアプローチは、小さなプログラムを
大きなプログラムにスケールアップするのに適していた。
さらに、このアプローチは、プログラミングのテクニック
を教えるのにも適していた。

今でもK氏はオリジナルのAwkのメンテナである。Awkの
コードは6700行だが、そのテストは7000行ある。

テストで主なカテゴリは、機能単独のテストである。昔の
Awkはそれで十分だった。しかし、Awkで大きなプログラムが
書かれるようになり、機能の組み合わせのテストが必要に
なった。

古いバージョンと新しいバージョンの両方を走らせて
みて、ごく簡単なパフォーマンス・テストをやる。

バグが1つ見つかるたびに、1セットのテストが追加される。
新しい機能が追加されるときにも、新しいテストが追加
される。

『境界条件』でエラーがよく見つかる。ストレス・テスト
もやっている。(一般的な) セオリーとして、重要なもの
については制限を設けないようにする。Awkもそのセオリー
に従っているので、ストレス・テストが有効になる。

有効なテクニックの1つに、プログラム内部の制限を
小さくするというものがある。たとえば、ハッシュ・
テーブルの初期サイズを1にするなど。

ASCII 1文字だけからなるAwkプログラムを実行する
テストも有効だった。

コマンド行引数もすべてテストされている。

gcovを使ってすべての行のカバレッジ・テストも試みた
が、240行ほどがカバーできていない。

テストの基本的なやり方は、何らかの手段によって予め
正解を作り、新しいバージョンのAwkがそれと同じ答えを
出すかどうか調べるというものである。

テスト・データのほとんどは、通常使われる形式のもの
である。

空ファイルなどの境界条件用のデータもある。

ストレス・テスト用の巨大なデータは、テスト・コード
内で作り出すこともある。

プログラムによって生成されるランダム・データも
あり、一種のストレス・テストに用いられる。

テストというのは、できる限り自動化したいものだ。

回帰テストとして、古いバージョンのAwkと新しい
バージョンのAwkとに同じデータを喰わせ、2つの出力を
比べるということやる。違う実装 (Gawk) による比較も
有効だ。

正解をまったく別の方法 (たとえばシェルス・クリプト)
で作成するのも有効だ。ただし、この手法には移植性に
欠けるという難点がある。

テストがシェル・スクリプトやAwkそのもので書かれる
ので、Unixやコマンドの使い方の勉強にもなり、小さな
ツールの有効性を学ぶことにつながる。

もっとも興味深いテストは、特殊な言語を用いて、
テスト・ケースとその正解を生成するというものである。
Awkの正規表現は、このやり方でテストされている。

特殊な言語によるテストは、テスト・ケースの追加も
楽で、テーブル駆動テストも可能になる。

一貫性チェックのためのテストもある。NRやNFが正しく
動いているか、deleteで配列の要素をすべて消せるか
など。この種のテストは、事前条件、事後条件による
表明に似ている。

アドバイス:

* 機械化 (mechanize) 重要

* テストには自明な出力をさせろ (何をテストしていて、
  何がエラーになったか)

* 失敗するテストを再現できるように注意する (各
  テストはきれいな状態で始めること)

* 1つのバグごとにテストを用意する

* 新しい機能や変更を1つ加えたら、テストも (1個以上)
  加える

* テストを捨てるな

* テスタには進捗報告させろ

* 壊すものを警戒しろ (テスト・フレームワークは頑丈に)

* テストは移植性を高くしろ

* 頻繁にテストと足元をチェックしろ (足元 (scaffold)
  はテスト・フレームワークのことか)

* 記録を残せ (何を直したか記録する)

生徒に小さめの正規表現のコードを書かせてみた。その
中で、先に紹介した特殊な言語によるテストと似たような
ものも書かせた。

ユニット・テストも試してみたが、特殊な言語による
テストのほうが上の正規表現のコードには向いていた。

Base64のデコード、エンコードを課題として出した。
そのとき、ナスティ・テストを生成するプログラムを
書かせてみた。(ナスティ・テストとは、デタラメな
データを読み込ませるようなテストのことか?)

別の課題として、既存の大きなプログラムを、その機能を
変えずに、ちょっとした変更を加えさせてみた。当然、
生徒たちは自明なテストを書くことになった。

プログラムをテストするのは大変だ。しかし、K氏の
経験上、最初にちょっとがんばってテストを書いて、
(より大切なことだが) テストを自動的に走らせるように
しておいて、あとはちょっとずつやったとしても、多大な
恩恵をこうむるものだ。

--

結局のところ、プログラマが幸せになれないシステムは
ダメなんじゃないだろうか。

旧Mac OSにしても、Mozillaにしても、プログラマは
幸せになれなかったんじゃなかろうか。

これは広い意味でいっていて、『テストしにくい
システムは悪いシステム』の延長線上にある。
テストしやすいほうが幸せだし、機能追加しやすい
ほうが幸せだし、保守しやすいほうが幸せだし、
そもそもバグを生み出しにくいほうが幸せだ。

本家Permlink

<< 前 ホーム 次 >>


Copyright © 1905 tko at jitu.org

バカが征く on Rails