上流品質を担保するために必要な3つのこと

高橋寿一氏(以下、高橋):Dailyで上流品質を担保するために必要な3つのことです。単体テスト、リファクタリング、要求仕様、ユーザーストーリーのテストケース展開という3つのアクティビティをしっかりやっていただくと、上流でも品質がかなり担保されていくんじゃないのかなと思っています。

単体テストに関しては、基本的には「網羅率を担保してください」みたいなことなので、シンプルです。ただ、まだまだ知られていませんが、0から70パーセントとか80パーセントに持ってくるのは地獄のような作業なので、だいたいみなさん諦めちゃうんです。

でも、テクノロジーが進んでいるのでそこまでやる必要はなくて、「2:8の法則」ですよね。ソフトウェア全体の2割の危ないところだけをテストすれば、だいたい品質は担保されますという。超いい加減な言い方をしましたが、そういうものがあります。

実際にこれは2010年代ぐらいから研究がすごく進んでいて。2割の部分で8割以上のバグが潜んでいることが、定量的にわかりました。1980年代、1990年代ぐらいは、実はなんとなく勘で学者が言っていましたが、今はいろいろなオープンソフトが増えてきたので、そういうところが計算で出せるようになったということですね。

バグはよく変更されるファイルから出てくる

基本的には、よく変更されるファイルからほとんどバグが出ます。よく変更されるファイルって、やはりみんなガチャガチャいじっているんですよね。だから自ずとそこからバグが出ると。

2、3年前に1回作ったファイルをぜんぜんいじらなかったら、そこからバグは出ないので、そんなところを単体テストする必要はない。メディカルとか、例えば車とかだと、やはり国際スタンダードがあるので全体に網羅しなきゃいけないんですけれども。

「もし国際スタンダードがないならば」という言い方はおかしいですが、そういうアルゴリズムを利用して、2割の部分を注力して8割のバグを潰していきましょうというようなスタイルでも十分です。

HotSpotという概念があります。これもググっていただければ。BugCacheというやり方もあります。Googleはちょっと違うやり方をしています。いろいろ理由がありますが、適切なやり方をやっていくと効率的にバグが見つかる。バグが見つかるということは、その網羅率が担保できているということ。ニアリーイコールの概念です。

これをざっと10パーセントテストすると、73パーセントから95パーセントのバグが見つかるようなすごい世界なので。こういうかたちで利用するのは、僕はいいかなとは思っています。

さっきの繰り返しになってしまいますが、HotSpot値、いわゆる直近でフィックスされているようなファイルがたくさんあると、サクサク終わりますというところが解説になります。

複雑度とHotSpot値を測るチャート

以前では、複雑度が高いモジュール、「どこかのclass」「どこかの関数」という、関数単位でバグが出るんじゃないのかという研究がすごくされていました。しかしある時、ある学者によって「いや、関数じゃないな。やはりバグってファイル単位なんだ」というのがわかって。今の考え方だと、ファイル単位で「ここのファイルはバグが出るから、ここのファイルはリファクタリングしましょう」みたいな言い方をしている。

(スライドを示して)これは僕がよく使っているチャートなんですけれど、なんだかんだいって、複雑度もやはり気になるんですよね。関数の複雑度が高いところも気になるので、複雑度と、あとHotSpot。直近でどれだけ変えられているかをこういうチャートで出して。「ここはリファクタリングしようね」「ここはリファクタリングせずに」。複雑度が低いのをリファクタリングしてもしょうがないので。

リファクタリングはやはりかなり時間がかかったりとか、へたっぴだとバグが出たりするので、必要以上にリファクタリングをする必要はないと思う。ただ必要なところは絶対にしなきゃいけないので、リファクタリングターゲットを決めて、開発者に対して「ここはリファクタリングしてね」みたいなところを指示していく。

実際に、市場バグって突然出るものじゃないんですよ。自分たちで開発していって、「あ〜、なんかこんな致命的なバグが出ちゃった」「バグを修正しました」「でも、同じパターンがまた出るんじゃないのかな」とか。

市場問題を出してお偉いさんに呼び出されて、「すみません、ここから出るとは思いました」とみなさん言い訳をします。でも、みなさんのその言い訳の顔はいつも笑っている。笑っているというか、なんかわかっていて。「全部わかっていたんだよね」みたいなことを、ローカルで話すと「そうなんですよね」と正直に言ってくれて。

なので、基本的には市場バグの繰り返しになります。単体テストなりシステムテスト内でやはり致命的なところから出るので、こういう表を書いて、どのへんから出ているのか。言わんとしていることは、HotSpot値を測ると市場バグがどこのファイルから出るのかがかなり高い確率でわかります。

単体テストの確認は網羅率だけでは不十分

ここはちょっと新しいトピックです。単体テストをやりましたといった時に、それで十分だよね/十分じゃないよねというのを、やはり網羅率で測っていくのが1つの指標です。ただ、「網羅率だけで十分なの?」というのは、私にも微妙にあります。

実際にあった話ですが、僕が以前勤めていた会社で「単体テストは100パーセントです」というオフショアの会社があって。僕らのオフショアの会社じゃないよ。

「あ、すっげえな。さすがオフショア。100パーセントまで持っていけるんだ」と(思って)よくよくソースコードを見ていると、期待値チェックが0だったっていう。ただ単に網羅をしているだけだったということがあったので。そういうズルいことをやっていないか。あと、やはりテストケースが適切に書かれているかという指標もたぶん重要だとは思っています。

話は戻りますが、Googleの網羅率はだいたい78パーセント、80パーセントぐらい網羅しているといわれています。とはいえ、さっき言ったように僕らは0パーセントがいきなり80パーセントにいかないというのはわかっていて。Googleでもそういうチームがあり、「まずは60パーセントで許容しましょう」みたいなところもあるので。「まずはみなさん、60パーセントを目指しましょう」みたいな言い方も、もし品質の部署の責任者だったならばしてもいいのかなとは思っています。

単体テストのテスト基準ですが、さっきも言ったように、レガシーコードがやはりあるから、そこに対してがんばってもしょうがないので。そこに関して放っておく。放っておくソリューションというのもおかしいんですけど、放っといてもいいのかなと思って。

新しく書いたコードに対してしっかりやっていくのは、極めてアメリカ人的な考えだけれども、実務の落としどころとしてはいいので。やはり僕らはビジネスで仕事をしているし、この時までにはものを出さなきゃいけないので、そういう適切なソリューションという言い方はアレですけが、出してもいいのかなとは思います。

ミューテーションテスト

新しいトピックを少しだけ紹介させてください。ミューテーションテストというものがありまして。先ほど言ったように、網羅率は担保しているんだけれど、期待値はぜんぜんチェックしていないみたいなところをチェックするツールです。あと、ちゃんと境界値を網羅しているかどうかとか、単体テストが適切であるかどうかをチェックするためのミューテーションテスト。

この概念としては、実際にソースコードに人為的にバグを仕込むわけです。仕込んだら、当然その仕込んだバグはみなさんの単体テストで見つけてくれるはずですよね。でも、見つけられない場合には「なんでですか?」みたいなところをチェックするテスト手法になります。

当然、期待値が入っていなければ、いくらバグを突っ込んだソースコードを入れてもただ単に網羅しているだけなので、一切単体テストバグが出ないことになります。このテスト手法は2000年初頭に出てきて、そんなに新しくはありません。

アジャイル時代になって、単体テストに重きを置かれていく時に、こういうテスト手法はすごく便利という言い方はおかしいですが、(便利な)テスト手法だなあとは思っています。

実際に「PITest」というツールもあります。これはJavaですが、こういうツールを使えばマルチランゲージでたぶんSwiftとかCでもいくような気がするので。こういうツールがオープンソースで落ちていたりします。

(次回に続く)