(第ニ回)JCUnitで2次方程式を解くプログラムをテストする。blogJCUnitの開発日誌(ログ)です。"その時点での"JCUnit作者の理解や考え、開発状況を日本語で書きます。この広告は、90日以上更新していないブログに表示しています。2016-03-09(第ニ回)JCUnitで2次方程式を解くプログラムをテストする。2次方程式を解くプログラムをテストさて、39件も失敗した前回のテストだが、どのテストがどのように失敗しているかつぶさに見ていこう。失敗するテストは以下の通り。40,41,42,43,45,46,48,49,51}これらが成功していたり、これら以外のものが失敗していたらJCUnitにバグがあることになる。前提として今回のテストで用いたテストメソッドはこうなっている。<NaN>NaNは浮動小数で表すことができない数に対して用いる記号であり、この場合は根を方程式で求めようとすると、虚数になってしまう=実根がないのが原因だ。テストケース4も同様。次にテストケース3を見てみる。10^-14という幾らかの大きさを持つ値になってしまっていることが原因である。係数が100や−100のように比較的大きいと、実数計算を行った際の誤差も大きくなる。結果として式の計算結果が0にならなくなってしまっている。(問題2:丸め誤差)テストケース6も似ている。<1.0>しかし、bがInteger.MIN_VALUEという大きな絶対値の数であるため、誤差も1.0という大きな値になっている。(問題3:巨大な係数)次にテストケース9。<NaN>しかし、問題1:虚数解とは少し事情が違う。aが0であるので、解の公式の分母が0になっている。浮動小数点数の演算では分母が0の計算を行った場合にもNaNが生じるのだ。(問題4:a==0)「バグ」と「仕様」、「ドキュメント」について上で見てきたいくつかの問題の修正に先立って「バグ」とは何か、「仕様」や「ドキュメント」とはなにかについて少しだけ論じておきたい。ソフトウェアのバグには2種類あって2種類しか無い。コードが間違っている。通常我々が呼ぶところの「バグ」(単に「バグ」と呼ぶと紛らわしいので今回のケーススタディのなかでは「製品バグ」と呼ぶことにする)。ひとつはコードがよって立つべき仕様自体が間違っている「仕様バグ」だ。それゆえ仕様やドキュメントがない状況ならば、どんな動きをしようと「仕様です」と言い張ることが一応は可能だ。しての矜持等々からあるソフトウェアのある挙動がバグかどうか判断される。言うなれば「こころの中に仕様がある」という場合もある。程度にもよるがそれで良い場合も多々あろう。仕様のとおりに作られたプログラムがあり、仕様自体に瑕疵が判明した場合、仕様もプログラムも修正することになる。これも「製品バグ」と「仕様バグ」の両方が同時に発生したと考えればよい。所謂「仕様変更」を仕様バグと考えるかどうか。SIer的な伝統では仕様変更はバグではない、区別する必要があるということになる。お金をもらえるかもらえないかに係るから。自分たちで作ったソフトウェアを自分たちで運用する世界ではその区別の重要性は低い。仕様変更と仕様バグの境界はSIer的マネジメントにおいて必要に応じて決めればいいのであって、ひとまず本稿では興味の対象外である。実装者が仕様の瑕疵に気づき、より適切な実装を行ったものの、仕様書の更新が行われなかった場合や、仕様のある部分を見ずに実装し、仕様と異なっていたが結果的にその実装のほうがより適切と判明した場合、特殊な条件下で一見奇妙な動作に見えるが精密に検討してみると正しいと言わざるを得ない場合、などがこれにあたる。この場合にはリリースノートの更新や、仕様書の修正が行われることになる。心の中にしか仕様書が無いなら心の中の仕様書を更新することになる。実際にどのような粒度のドキュメントがどのような抽象度、どのような詳細さで書かれるべきかはこのエントリの範囲では立ち入らない。いった粒度や抽象度の仕様が適切かはプロダクト、プロジェクト、企業文化、重要なステークホルダー、担当者の好みなど様々な要因で変わる。ある製品の仕様書は通常、その製品が何をでき何ができないかを明らかにする。「あるべき挙動」がチームや製品の状況などに照らして明々白々なときにはドキュメントの量は減ることであろう。今回の一連のエントリの中で私が「ドキュメント」や「仕様」というとき、それは単に「ソフトウェア製品の言語化されたあるべき動作」という意味である。ものものしく定式化された体系的書類のことだけではない。問題の整理では問題を改めて整理してみよう。「分析」の節で上がった問題は以下の4つ。問題4:a==0これらが昔風にいうならバグ表の項目、今どきならJIRAのチケットに対応する。これらをどういう形で決着させるか。実に色々な形があり得る。ここまでのところ、我々のQuadraticEquationクラスの仕様は以下のものでしかないので様々な側面を明確にする余地があるし、その仕様にしたって正当な理由があれば適切な手順を踏んで仕様を変えることもありえるのがソフトウェア開発というものだ。0を満たす実数x1とx2だから当初予定されていた仕様を変更して虚数解をサポートするという判断に至ることだってあるかもしれない。このポストは、JCUnitの使い方のあらましを示すためのものだ。可能な限り当初の仕様を変えない方向で、これらの問題への対応方法を決めていこう。カッコ内には先程述べたバグの分類(製品バグと仕様バグ)に基づいて、それぞれの問題がどちらに当たるかを記した。二次方程式の解の判別式を用い、実根がない組み合わせが与えられた場合例外を送出する。根を方程式に代入した時、その計算結果の絶対値が0.01を下回ること。a,b,cいずれも絶対値が100以下とし、その範囲外の値が与えられた場合例外を送出する。aに0が与えられた場合例外を送出する。(仕様バグ、製品バグ)問題の修正(1)これらの問題を修正するにあたっては、まずは仕様書を更新し、しかるのちテスト対象ソフトウェアを修正するという古式ゆかしい手順を踏んでみよう。仕様書は以下のように修正されることになる。2入力:三つの整数a,b,caが0の場合、例外が送出される。(問題4:a==0)a,b,cのいずれかの絶対値が100より大きい場合、例外が創出される。0を満たさない場合、例外が送出される。0を満たす実数x1とx2出力される解x1またはx2を上述の2次方程式に代入した時、その絶対値は0.01未満になる。(問題2:丸め誤差)次回は、テストをこの仕様書に基づいてアップデートする。今風にいうなら「テストファースト」ということになるのだろうか。22:09(第ニ回)JCUnitで2次方程式を解くプログラムをテストする。2017でJCUnitの発表をすることになりました。joinedプログラミングはてなブログをはじめよう!dakusuiさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。