見出し画像

プログラミング テストについて

テストは普段、担当の方にしてもらうが、
それでもコードを実装する際にはある程度自分で
テストして動作を確認する。

私はまだプログラミング歴半年(しかも真っ当な教育を受けていない)の
〇んこ野郎なので今回はプログラミングの「テスト」の部分を
勉強してまとめる。

◎テストとは

そもそもテストとはなんだろう。

② 実際の使用条件に近い条件で、ものの良否を調べること。また、理論として考えられたことを実地に応用して、その当否を調べること。
                        日本国語大辞典より

色々な意味合いはあるかと思うが、
プログラミングにおいてはこの言葉が最適だろう。
最終的には納品する際の
プログラム・コード全体の品質を上げるために行うことと理解する。

◎テストの意図

なぜテストを行うのか。
コードを見ればそのプログラムの動作は基本的にわかるはず、
ではあるが、実際にコーディングした人の認識通りに
コードが必ず動くわけではない。
例えば、こういったコード。

public double subtract( double a, double b){
    return a-b;
   }
 
subtract(1, 0.9);

//実行結果 ⇒ 0.09999999999999998

これは、浮動小数点の丸め誤差という現象らしく、
プログラマーの想定では「0.1」だが、実際には
「0.09999999999999998」が結果となって表れる。
ちなみにPHPではこういった現象は起きなかった。
C#みたいな変数の型宣言を明確にする言語で起きるのか?

このように「プログラマーのプログラムに対する認識齟齬で発生する誤差や
単純なバグ、要件外の余計な動作や仕様を検出すること
」に
テストの意義はあるといえる。

◎テストの種類

単体テスト
・システム開発における最小開発単位の「モジュール」が設計書通りに
 動作することを検証。
 ⇒モジュール単位での動作確認
 ⇒複数モジュール連携での動作確認

結合テスト
・単体テスト済のモジュールを結合し、詳細設計書通りに動作することを
 検証。
 ⇒「機能」単位での動作確認
 ⇒モジュール間、プログラム間のインターフェースの妥当性の確認
 ⇒単性能測定

総合テスト
・本番環境を想定し、全プログラムがシステムとして動作することを検証。
 ⇒実業務と同等、単一または複数業務が並行する状態での確認
 ⇒非機能要件の確認。性能、信頼性、運用性、大容量テスト、負荷テスト
 ⇒他システムとの連携確認

受入テスト
・システム開発を発注した側(ユーザー)が要件通りにシステムが動く
 こと、誤りや要件の抜け等がないかを検証。
 ⇒業務を行うエンドユーザーによる確認
  (ビジネスプロセス、ユーザービリティの確認)
 ⇒システム開発プロジェクトチームによる確認
    (要件確認、品質評価、納品受領の判定などを行う)
 ⇒システム運用チームによる確認
   (保守、運用、拡張、セキュリティ、性能などを確認)

リグレッションテスト(退行テスト)
・既成プログラムのバグ改修などをした際に、その他の機能の動作不具合を
 引き起こしたり、別のバグを発生させたり(デグレーション)していない
 かを検証。
 ⇒コーディングした段階での動作確認
 ⇒バグ改修後にテストチームが要件と比較して確認

基本的に私がしているような仕事(改修)では、リグレッションテストに
分類されるテストをしているということになる。

◎テスト設計

テストといっても前述の通り、種類がいくつかあり、全体の作業段階に
よって分けられている。
それぞれのテストはいつ作成されるのだろうか。

プログラムを作成する上でプログラム作成作業の全体の流れと
テスト設計は当然連動して行われる。
ここでは「W字モデルの概念」を学んだ。

W字モデル

   引用元: JAXA 宇宙航空研究開発機構 IV&Vガイドブック より

要件定義がなされたら、受入テスト、
基本設計の段階で総合テスト、
詳細設計の段階で結合テスト、
プログラム設計の段階で単体テストをそれぞれ設計し、
プログラムが出来たら、各テストを実施するということである。

このW字モデルを実践することで設計書の曖昧性や不確実性を減らすことが
でき、上流工程でのテスト設計をすることで早期の段階でテストに係る
工数や費用を見積もることができる。

◎テストの手法

では実際にどのようにテストを実施するのか。
一口にテストといっても、一つのデータだけで要件を満たせるのか、
すべての数値を入力しないと要件を満たせないのかなど、
求められる要件によってテストの条件は異なる。
かといってすべての数値を試していくことは無駄が多く、時間的にも
精神的にも不可能である。

ここではテストケースを抽出する方法として
デシジョンテーブル』を学んだ。

4つの要素で構成されるテーブル(表)を使った手法である。
要素
・条件記述部 ⇒ 原因を記述
・条件指定部 ⇒ 原因に対する実際の値を記述
・動作記述部 ⇒ 起こりえる結果を記述
・動作指定部 ⇒ 条件指定部の各列に対応する結果を記述

例えば、
「ある団体の会員様の割引」
・団体番号が6の会員様のみ割引
・1月は男性なら10%引き、女性なら20%引き
・7月は男性なら20%引き、女性なら10%引き
・それ以外の月は割引無し

スクリーンショット (61)

凡例
条件指定部:T ⇒ 条件に当てはまる
動作指定部:X ⇒ 実際に動作する

すんごい見づらいが、こういった考えうる分岐をそれぞれ考えて、
テストする方法がデシジョンテーブルである。
ちなみにデシジョンはそのまま「決断」とか「判断」の意味。

◎テスト手法の考え方

前項ではテストの実際の手法を述べたが、どんな考え方に
基づいて設計されているのだろうか。
考え方はいくつかある。

ブラックボックステスト
・プログラムのコードは関係なく、仕様から考えうる値を取り出す。
 同値分割、境界値分割があたる。

同値分割
仕様に応じて、各範囲から値を一つ抽出し、テスト用の値とする。

仕様
・年齢が6歳未満なら100%割引
・年齢が6歳以上で18歳未満なら50%割引
・年齢が18歳以上で60歳未満なら割引無し
・年齢が60歳以上なら50%割引

この場合の取り出す値を考えると、
・0(X<6)
・12(6≦X<18)
・34(18≦X<60)
・65(60≦X)

この4つの値でテストするとすべてのケースをチェックできる。

・境界値分析
同値分割に加えてさらにテストすべきだと考えられる値を抽出する。
境界値ということで範囲に対する境界となる値になる。

前述した仕様でいうと、
・5(6歳未満)
・6(6歳以上)
・17(18歳未満)
・18(18歳以上)
・59(60歳未満)
・60(60歳以上)

これらの数値も加えてテストすることで網羅的にバグをチェックできる。

・無効値
仕様によっては無効と取られる値がある。バリデーションで排除されるべき
だが、要件によってはテストするべきである。

ホワイトボックステスト
主にコードに着目してテストをする。プログラムに応じてテストが可能で
あるが、ソースコード上に無いことはテストできないため、存在すべき条件
分岐が無い場合や、プログラマの認識齟齬による要件との相違は確実には
発見できない
。そのため、ブラックボックステストを主軸に補助的に
行うテストである。制限フローテストやデータフローテストがあたる。

・制限フローテスト
プログラムの処理経路が網羅的に実行されているかを確認する方法。
条件判定の処理分岐がある場合に、すべての経路を通過させてテストする。
条件に合わせてテストデータを用意する。

・命令網羅
すべての命令を実行するようにテストする。

・分岐網羅
すべての分岐方向を実行するようにテストする。

・条件網羅
すべての真偽が1回以上出現するようにテストする。ただし、分岐方向は
問わない。

・判定条件/条件網羅
分岐網羅と条件網羅を組み合わせてテストする。

・複合条件網羅
条件に対し、すべての組み合わせをテストする。現在主流の考え方。

例)年齢18歳以上か、1000番以内でTrue

public function isValide($age, $number){
    $result = false;
    if( $age >= 18 || $number <= 1000 ){
        $result = true;
    }
    return $result;
 }

複合条件網羅的に考えると、
・年齢10歳、番号100   ⇒ $age結果 false $number結果 true
・年齢10歳、番号1001 ⇒ $age結果 false $number結果 false
・年齢20歳、番号100   ⇒ $age結果 true  $number結果 true
・年齢20歳、番号1001 ⇒ $age結果 true  $number結果 false

というテストケースを考えることで、全ケースを網羅できる。

・データフローテスト
プログラムが順番通りに実行されるかを確認する方法。


◎テストの進捗管理

では、どのようにテストを進捗管理していくべきか。

まずは、要件定義段階でのテストケース仕様書を規定しておくことが
必要である。チームではなく、プロジェクト単位での規定とする。
テストケース仕様書の内容としては、
・テスト内容
・テスト環境
・実施ステータス
・実施結果
・テスト開始予定/実績日
・テスト終了予定/実績日
・要件トレース(要件定義書、基本設計、詳細設計の記載箇所入力)
・不具合管理(バグ票とリンク)など
があげられる。

日々の作業量が増えれば増えるほど、バグの発生数も増える
可能性が高くなる。そうなると、日々のプログラミング、テスト、
コードレビュー、改修を順次しながらでないと、テストを後に回せば
回すほど、テストもコードの改修も不毛なものに変わっていく。
ということは開発段階からの管理意識を高めておく必要がある。
また、思わぬ事態に対応すべくテスト計画時点で開発段階ごとのテストの
チェックポイントや対応プランを決めておき、状況によってリカバリの
方法や遅延リスクを最小限に抑える仕組みまで構築しておくべきである。

◎その他の用語

バグ密度
バグが製造規模あたりどのくらい発生しているかを表す指標。

試験密度
製造規模あたりどのくらいテストを実施したかを表す指標。

◎まとめ

テストについて学んだが、テストだけを生業とする企業様が存在することが
示すように、プログラミングにおいてテストは大変重要な工程であることが
わかった。
気づいていはいたが、理解はできていなかった。
重要であるだけに頭を悩ませて、ケースを想定したり、
要件を完全に理解して何度もデータを作成したりする
大変な作業だ。

テストケース仕様書を作ってくれるテスト担当の方、
本当にありがとう!
いつも不具合を見つけては突き付けてくれてありがとう!
イライラさせて本当に申し訳ない。

今回学んだことを生かし、自分でもある程度テストをしてから
「改修しました☻」といえるように心がけよう。


この記事が気に入ったらサポートをしてみませんか?