単体テストを学ぼう!① -自分のプログラムに自信を持ちたい-

f:id:monozukuri-bu:20191126184429j:plain

こんにちは、ふじもんです。
朝、お布団からでるのが辛い季節になってきましたね。
いつのまにか出勤時に乗る電車が前よりも20分遅くなっていました。

遅刻ギリギリ。

さてさてお話は変わりまして。

私は業務でプログラムを書くときは、分析データの整形など、分析の前処理のスクリプトが主です。
そしてプログラムを組んでいるときに常々不安を抱えています。
それは

私のプログラム、本当に合ってる???

って。
自分で組んだプログラムが想定通りの挙動をしているかいつも不安です。

毎回処理途中のデータや最終的なアウトプットをちまちまと目視で確認はしているけど、
何せプログラムで処理したいデータなんて少ないはずがない。
それはもう膨大

さて、どうしよっかな。

この不安感、なんとかして解消できないものか。

そう思い、上司に相談してみました。

上司「最近現場どう?」
私 「現場は順調なんですけど、ちょっと悩みが…」
上司「え。どしたの」
私 「自分でスクリプト書くじゃないですか。それを実行してみて、一見思い通りに動いてるように見えるんですけど、コレ本当に全てのデータに対して正しく動いてるのかなって…。」
上司「それならテストコード書けばいいんじゃない?」
私 「テストコード」
上司「…ふじもんって開発業務とかにおけるテストってどういうことするかわかる?」
私 「ばなな。」
上司「わからないなら素直に言おうか。じゃあまずテストとは何なのかを調べてみようか。そうしたら、自分のプログラムがちゃんと想定通りに動いてるか調べる方法とかもわかるかもね。」

テストってなんだ?

上司に言われるがままに、開発経験ゼロの私は早速テストについて調べてみました。
そもそも、開発業務に置けるテストには、大きく分けて以下の3種類があるようです。

単体テスト
 プログラム1つが期待した通りに動作するかテストを行う。

結合テスト
 複数のプログラムを組み合わせ、それらが一体として期待したとおり動作するかテストを行う。

・総合テスト
 システムの全機能を最初から最後まで一通り運転させ、期待したとおり動作するのかテストを行う。

ふむなるほど。
プロジェクトによってどのテストを行うかはまちまちだそうですが、上記3つは大体行われるようです。

また、テストの範囲はプログラムに限らずモジュールや関数などにも適用され、厳密には決まっていません。
システム開発ではこれらを行うことにより、仕様通りに動くことを確かめてからリリースします。

つまり・・・?

私の悩みは自分の書いたプログラム1つが正しい挙動をしているか確認したいので、
上記の3種類の中で必要なテストは「単体テスト」に当たります。

単体テストってどうやるの!!! はやく!はやくこの不安感から解放されたいんだ!!

単体テストってどうやるの?

逸る気持ちで単体テストについて調べていると、単体試験の中にも2種類あって、観点が違うもよう。

確かに、プログラムを確認する観点を決めていなかったな…
漠然と入出力を見て間違いがないかを確認していたな…
それで、確認しても不安が残っていたのか。。。

これは重大な気付きです!!!

ブラックボックステスト

テスト対象の入出力に着目し、入力に対して期待した出力になるかを検証する。

その観点は、

同値分割

起こりうる全ての事象をいくつかのグループに分け、各グループから代表値を選んでテストを行う。

境界地分析

同値分割によって分けられた各グループの境界値付近をテストを行う。

ホワイトボックステスト

テスト対象の内部構造に着目し、条件分岐や繰り返しなどの各部分を確実に検証する。

その観点は、

命令網羅(C0)

テスト対象となるプログラムの命令文それぞれが、1回以上実行されるようにテストを行う。

分岐網羅(C1)

テスト対象となるプログラムに含まれる判定条件について、真となるケース、偽となるケースそれぞれが、1回以上実行されるようにテストを行う。

条件網羅(C2)

テスト対象となるプログラムの条件文について、真となるケース、偽となるケースそれぞれが、1回以上は実行されるようにテストを行う。

なるほど!!!

ブラックボックステストは、ソースコードはどうあれ入力に対して出力が正しいかを確認して、
ホワイトボックステストは、ソースコードの中身の挙動が正しいかを確認するってことですね。

お、確かにこの観点でプログラムの挙動をチェックしていけば、「なんとなく大丈夫そう」よりは圧倒的に不安が取り除かれる気がする…!
これは不安から解放される日も近いのでは!

テスト基準のモノづくり -テスト駆動開発-

よーし、じゃあさっそくテスト…って思ったけど、テストするにもテスト対象のモノがない。
なら作れば良いじゃない。
じゃあテストをするための簡単なシステムを作ろう。
せっかくテストのことを理解するなら、テストしやすいものを作りたい。
何をどんな風に作ろうかなと調べていると、テスト駆動開発という言葉を発見しました。

テスト駆動開発(TDD:Test-Driven Development)

テストファーストという考えに基づいた開発手法。
テストファーストとは、まず本番で使用するプロダクションコードを書く前に何をテストするかを決め、テストコードを先に書くのが特徴。

そのテストファーストという考え方を組み込んだテスト駆動開発は、最低限必要なテストを積み重ねていき、少しずつ確実に実装できるそう。
そして、この手法の大きなメリットとして確実に動くコード読みやすく綺麗に書けること。

よく自分の書いたコードがあとで読めなくなったり、学生時代に「コードの汚さは頭の中の汚さ」とゼミの先生に言われていた私にとって、もうこんな最適な開発手法あったの?もっと早く知りたかった。
確実に動くコードを書けると、心理的負担も減りますしね!
他にもデバッグの時間が短くなったり、実装コードの修正があった場合に修正と無関係な部分を破壊していないかをチェックするリグレッションテストにも役立つメリットもあるようです。

まとめ

今回の記事では以下のことについて調べて記載しました。
開発におけるテストには以下の種類がある。
単体テスト
結合テスト
・総合テスト
それぞれを行うことにより、一つのシステムのバグの検証や確実性を高めてからリリースできる。

単体テストは以下の種類がある。
ブラックボックステスト
ホワイトボックステスト
それぞれを行うことにより、プログラムの入出力からソースコードの挙動までを確認することができる。

テストファーストの開発「テスト駆動開発」というものがあり、プロダクションコードよりテストコードを先に書くことにより、
確実に動くコードを綺麗に書けるメリットがある。

次回の記事ではテスト駆動開発でプログラムを実装しながら、テストについてより理解を深めていきます!