• 検索結果がありません。

単体テスト設計のコツ

N/A
N/A
Protected

Academic year: 2021

シェア "単体テスト設計のコツ"

Copied!
32
0
0

読み込み中.... (全文を見る)

全文

(1)

日本システム開発株式会社

ESEC2011

ブース内セッション

単体テスト設計のコツ

http://www.nskint.co.jp

(2)

目次

1. ユニットテストについて知っておかないといけないこと

1-1. 品質問題の原因とユニットテストの関係

1-2. ソースコードレビューとユニットテストの違い

2. 有効なユニットテストデータの与え方[事例]

2-1. [事例1] 有効な値が10~20のunsigned short変数

2-2. [事例2] 参照のみ行う領域の確認

2-3. [事例3] メモリ破壊が起きるコピー処理

3. 危険コードに対するテストデータの与え方[事例]

3-1. [事例1] 欠陥となる可能性がある符号変換処理

3-2. [事例2] オーバーフローに誘発されたゼロ割処理

4. ユニットテスト

まとめ

(3)

1.ユニットテストについて

(4)

1-1 品質問題の原因とユニットテストの関係

約6割がソフトウェア

の不具合

約6割がソフトウェア

の不具合

不具合の原因の割合

引用:2010年版組込みソフトウェア産業実態調査報告書-事業責任者向け調査-(経済産業省)

品質の悪い製品を作り出す原因の一部は、ユニットテストにある。

ユニットテストは製品不具合の原因に

直接的

直接的

または

または

間接的

間接的

関与する。

関与する。

(5)

ユニットテスト工程で検出すべき欠陥を、検出できなかった。

そのまま製品が出荷されたため欠陥が発生し、品質問題による

損失を発生させた

1-1 品質問題の原因とユニットテストの関係

ユニットテスト

統合テスト

レビュー

・・・

・・・

検出できなかった

ユニットテスト工程以降でも欠陥を検出できず、

ユニットテスト工程以降でも欠陥を検出できず、

そのまま流出させてしまった。

そのまま流出させてしまった。

製品欠陥に対して直接的に関与する場合

ユニットテスト欠陥の流出

(6)

ユニットテスト工程に不備があり、その後のテスト工程で行う

はずであった機能テストなどが十分に実施できなかった。

必要なテストが不十分なまま出荷されたため欠陥が発生し、

品質問題による損失を発生させた

1-1 品質問題の原因とユニットテストの関係

ユニットテスト

統合テスト

・・・

・・・

予定

・・・

実績

・・・

検出できなかった

統合テストが十分にできず、統合テストで検出すべき欠陥を流出させてしまった。

統合テストが十分にできず、統合テストで検出すべき欠陥を流出させてしまった。

製品欠陥に対して間接的に関与する場合

ユニットテスト以降のテストが不十分

直接の原因が統合テストであるため、そもそもの原因である ユニットテストに改善の意識が向きにくい。

ここで検出

ユニットテスト 欠陥の対応

(7)

ユニットテストは実施しなければならない。

ユニットテストとソースコードレビューの工程の

目的は大きく異なる

ため、ユニットテスト工程を省略することは不可能。

ユニットテストを実施しないと、他の工程は本来の目的を果たすことが

できない。

※仮に現状ユニットテスト工程を省略していて問題が出ないとしても、今の開発体制が

崩れたら問題が発生する可能性は大。

ユニットテストは実施しなければならない。

ユニットテストは実施しなければならない。

ユニットテストとソースコードレビューの工程の

目的は大きく異なる

ため、ユニットテスト工程を省略することは不可能。

ユニットテストを実施しないと、他の工程は本来の目的を果たすことが

できない。

※仮に現状ユニットテスト工程を省略していて問題が出ないとしても、

今の開発体制が

崩れたら問題が発生する可能性は大

ユニットテスト

に対するよくある誤解

ソースコードレビューをしっかり行えば、

ユニットテストは実施しなくても問題ないのでは?

1-2 ソースコードレビューとユニットテストの違い

(8)

1-2 ソースコードレビューとユニットテストの違い

工程

評価対象

評価範囲

インプット

評価内容

欠陥検出範囲

品質保証

ソース

コード

レビュー

ソース

コード

関数

詳細設計

静的分析

仕様網羅性確認

コーディング規約適用確認

冗長性確認

コメント確認

タイミング欠陥確認

(ロバスト性確認)

不可能

ユニット

テスト

実行

モジュール

関数

詳細設計

動的分析

仕様網羅性確認

コードカバレッジ確認

ロバスト性確認

可能

(動作させた範囲)

ソースコードレビューとユニットテストの比較

ユニットテストのコツとして、ソースコードレビューとの違いを認識

しておくことが重要

ソースコードレビューとユニットテストは「評価範囲」と「インプット」は

同じだが、それ以外は異なる。

ソースコードレビューとユニットテストは「評価範囲」と「インプット」は

同じだが、それ以外は異なる。

同じ

(9)

:

void func()

{

if (1 == a) {

b = a;

}

return;

}

:

:

void func()

{

if (1 == a) {

b = a;

}

return;

}

:

ここで割り込み

a = 3;

Q.タイミングによる欠陥を検出できるか?

Q.タイミングによる欠陥を検出できるか?

aが1の時にbをa(1)にすることを

期待しているが、割り込みが

上がると期待しない結果になる。

aが1の時にbをa(1)にすることを

期待しているが、割り込みが

上がると期待しない結果になる。

A.

ソースコードレビュー

なら、タイミングによる欠陥を

検出できる。

ユニットテスト以降の工程で

この状況を確実に作り出すことは

できない

ユニットテスト以降の工程で

この状況を確実に作り出すことは

できない

ソースコードレビュー以外では検出できない欠陥

1-2 ソースコードレビューとユニットテストの違い

(10)

:

unsigned char a = 255, b = 255;

unsigned short c;

c = (unsigned short)(a

+ b);

:

:

unsigned char a = 255, b = 255;

unsigned short c;

c = (unsigned short)(a

+ b);

:

Q.コンパイル環境によって動作が異なる場合、

必ず正しいソースコードレビューが行えるか?

Q.コンパイル環境によって動作が異なる場合、

必ず正しいソースコードレビューが行えるか?

ある環境

では510

ある環境

では254

A.

レビューアが全てのコンパイラの動作を把握することは

ほぼ不可能

であるため、必ず正しく行えるとは限らない。

実際に動作させるユニットテストで差分を検出する必要がある。

ユニットテスト以外では検出できない欠陥

1-2 ソースコードレビューとユニットテストの違い

(11)

1. 欠陥検出範囲はソースコードレビューの方が広い

ソースコードレビューの方が多くの欠陥を検出できる

まとめ

1-2 ソースコードレビューとユニットテストの違い

2. ユニットテストは機械的に全ステップ評価する唯一の工程

目視で行うソースコードレビューに対し、

ユニットテストは機械的にテストすることで

ヒューマンエラーを防ぐ

ユニットテストの後工程では全ステップに対してテストを行わないため、ユニットテスト

でステップに対する評価を完了しておく必要がある。

3. ソースコードレビューは品質証明にならない

ソースコードレビューはレビューアがNGと判断した箇所だけに指摘が出るため、他に

欠陥が10件潜伏している可能性も、100件潜伏している可能性もある。

ユニットテストは与えるINPUTに対するテスト結果を記録として残すため、「このINPUT

を与えれば正常に動作する」ということを証明できる。(INPUTを網羅する必要あり)

ユニットテストは品質証明になる

ソースコードレビューとユニットテストは共に必要。

ソースコードレビューとユニットテストは共に必要。

(それぞれで何を重視すればよいか?が重要となる)

(それぞれで何を重視すればよいか?が重要となる)

(12)

2.有効なユニットテストデータの

与え方[事例]

(13)

2 有効なユニットテストデータの与え方[事例]

[事例1] 有効な値が10~20のunsigned short変数

[事例2] 参照のみ行う領域の確認

[事例3] メモリ破壊が起きるコピー処理

有効なユニットテストにするために重要なこと

このようなユニットテストをOJTで行うことは難しい

(現場に指導できる人材が少ない)

このようなユニットテストをOJTで行うことは難しい

(現場に指導できる人材が少ない)

どのようなテストケースを作成するか

どのようなテストケースを作成するか

どのようなテストデータを与えるか

どのようなテストデータを与えるか

有効なユニットテストを考えるための事例

(14)

同値分割とは

同値分割

同値分割

同値分割はテストデータを抽出する手法の一つ。

起こりうるすべての事象を洗い出し、同じ事象を発生させる入力値

の集合を作成。

この入力値の集合を同値クラスと呼ぶ。

同値分割では、同値クラスから代表値を選出し、テストデータとする。

2-1 [事例1]

有効な値が10~20のunsigned short変数

(15)

20

10

9

同値クラス

同値クラス

同値クラス

21

15

0

同値クラスの代表値

50

例)有効な値が10~20のunsigned short変数の場合

long func(unsigned

short data)

{

if ((10 <= data) && (20 >= data)) {

:

}

:

}

long func(unsigned

short data)

{

if ((10 <= data) && (20 >= data)) {

:

}

:

}

Q.dataの初期値に何の値を指定するか?

Q.dataの初期値に何の値を指定するか?

A.

例えば

0、15、50 を

指定したとする。

50では欠陥が検出できない

可能性がある。

しかし・・・

10、20を境界とした同値クラスに分割。

分割した同値クラスから代表値を選出。

2-1 [事例1]

有効な値が10~20のunsigned short変数

(16)

2バイトの変数である

有効範囲は10~20の1バイト範囲である

2バイトの変数である

有効範囲は10~20の1バイト範囲である

例)有効な値が10~20のunsigned short変数の場合

検出できない欠陥と対策

下位バイトが有効値と同じビットの値の

評価が正しくできない可能性がある。

(例えば266が有効値とみなされる欠陥)

2-1 [事例1]

有効な値が10~20のunsigned short変数

変数を2バイトで評価しているか検証

できる値を使用する。(例えば266)

対策

対策

上位バイトを評価に

使用しているか確認できる

下位バイトが有効範囲内で

あれば、誤った判断をして

いないか確認できる

50

上位バイト

0000 0000

下位バイト

0011 0010

50をテストデータとして指定

266

上位バイト

0000 0001

下位バイト

0000 1010

266をテストデータとして指定

(17)

関数func()は外部変数flagを参照している。(更新はしない)

例)参照のみ行う領域を更新していないことを確認する場合

flagが更新されていないことを確認

→func()を呼び出す前と後でflagの値が同じであればよい。

Q.flagの初期値に何の値を指定するか?

Q.flagの初期値に何の値を指定するか?

A.

例えば1を指定

したとする。

1では欠陥が検出できない

可能性がある。

しかし・・・

2-2 [事例2] 参照のみ行う領域の確認

外部変数flag

外部変数flag

関数func()

関数func()

参照

flagがxxなら、

更新していない

flagがxxなら、

更新していない

func()呼び出し flagにxxを設定 flagがxxか?

(18)

外部変数flag

外部変数flag

関数func()

関数func()

参照

一般的によく使用する値(1や0)では、

意図しない所で偶然初期値と同じ値に書き

換えられている可能性がある。

flagの初期値として

1 を指定

関数func()は外部変数flagを参照している。(更新はしない)

func()呼び出し前

flag = 1

func()呼び出し後

flag = 1

マジックナンバー(0xaaなど)を指定する

値を変えて複数回テストする

対策

対策

偶然初期値と同じ値に

flagを更新している可

能性がある。

例)参照のみ行う領域を更新していないことを確認する場合

検出できない欠陥と対策

2-2 [事例2] 参照のみ行う領域の確認

(19)

例)配列をコピーする場合

2-3 [事例3] メモリ破壊が起きるコピー処理

多くの場合、サイズに着目した

テストを実施している。

(0、配列の最大値を指定)

サイズだけに着目したテスト

では、欠陥が検出できない

可能性がある。

しかし・・・

元データ

コピー先

From

From

To

To

Size

Size

元データ(From)がコピー先(To)へ

Sizeの値だけコピーできていればよい。

From、To、Sizeを指定してコピーを行う処理。

(From、Toはメモリのどこでも指定できる)

(20)

メモリ破壊が起きるパターン

メモリ破壊が起きるパターン

①元データの後方とコピー先の領域が重なっている場合

②元データの前方とコピー先の領域が重なっている場合

元データ

コピー先

先頭から順にコピーすると、

後方のデータを使用する時には

コピー処理により上書きされて

しまっている。

先頭から順にコピーすると、

後方のデータを使用する時には

コピー処理により上書きされて

しまっている。

元データ

コピー先

末尾から順にコピーすると、

前方のデータを使用する時には

コピー処理により上書きされて

しまっている。

末尾から順にコピーすると、

前方のデータを使用する時には

コピー処理により上書きされて

しまっている。

例)配列をコピーする場合

検出できない欠陥

コピー元データの開始位置(From)、コピー先データの開始(To)、

データサイズ(Size)の関係によって発生するメモリ破壊。

2-3 [事例3] メモリ破壊が起きるコピー処理

(21)

コピー処理がある場合の正しいテスト観点

From

To

Size

コピー処理がある場合の正しいテスト観点

コピー処理がある場合の正しいテスト観点

From

To

Size

元データ

コピー先

この3つの

組み合わせ

が必要。

組み合わせを考えないとテストに抜けが発生する。

From

From

To

To

Size

Size

例)メモリ破壊が起こるコピー処理

対策

2-3 [事例3] メモリ破壊が起きるコピー処理

(22)

3.危険コードに対する

(23)

3 危険コードに対するテストデータの与え方[事例]

危険コードに対するテストデータ

危険コードは多くの値で正常に動作するが、ある特異な値

を与えた場合に欠陥となる

危険コードを考慮しないとテストが漏れる

本章で紹介する事例

[事例1] 欠陥となる可能性がある符号変換処理

[事例2] オーバーフローに誘発されたゼロ割処理

(24)

例)signed変数をunsigned変数として扱いたい場合

long func(signed

char arg)

{

:

if (0 > arg) {

arg

= -arg; //符号変換処理

}

:

}

long func(signed

char arg)

{

:

if (0 > arg) {

arg

= -arg; //符号変換処理

}

:

}

A.

例えば

10、-10 を

指定したとする。

10、-10では欠陥が検出できない

可能性がある。

しかし・・・

符号変換処理としてよく実装されるが、欠陥

が潜んでいる。

これまで複数のプロジェクトで同じ誤りが

あった。

3-1 [事例1] 欠陥となる可能性がある符号変換処理

Q.argに何の値を指定するか?

Q.argに何の値を指定するか?

(25)

long func(signed

char arg)

{

:

if (0 > arg) {

arg

= -arg; //符号変換処理

}

:

}

long func(signed

char arg)

{

:

if (0 > arg) {

arg

= -arg; //符号変換処理

}

:

}

例)signed変数をunsigned変数として扱いたい場合

検出できない欠陥とポイント

argに-128を与えた場合のみ、符号変換処理

を行っても符号が変換されないため、

unsigned変数として扱うことができない。

argに-128が指定されないことを確認する

-128が指定される場合、指定されても問題

ないことを確認する

ポイント

ポイント

この符号変換処理において、

符号を変換できない値が1点

だけ存在する。

3-1 [事例1] 欠陥となる可能性がある符号変換処理

(26)

long func(unsigned char arg1)

{

:

a = (b / (unsigned char)(arg1 + 5));

:

}

long func(unsigned char arg1)

{

:

a = (b / (unsigned char)(arg1 + 5));

:

}

例)演算後に除算している場合

A.

例えば

0、10、255 を

指定したとする。

代表値、最小値、最大値だけ

では欠陥が検出できない可能

性がある。

しかし・・・

arg1を「+5」しているため、ゼロ割

が発生しないと判断を誤りやすい。

Q.arg1に何の値を指定するか?

Q.arg1に何の値を指定するか?

3-2 [事例2] オーバーフローに誘発されたゼロ割処理

long func() { : } long func() { : } arg1 = 0

(27)

long func(unsigned char arg1)

{

:

a = (b / (unsigned char)(arg1 + 5));

:

}

long func(unsigned char arg1)

{

:

a = (b / (unsigned char)(arg1 + 5));

:

}

例)演算後に除算している場合

検出できない欠陥とポイント

この演算処理において、ゼロ割

を発生させる値が1点だけ存在

する。

arg2に251を与えた場合のみ、「+5」すると

オーバーフローするため、除算の分母が0に

なり、ゼロ割が発生する。

特定の値を与えられた場合のみ欠陥となるコード

があることを認識してテストを行う。

コードを見ないと有効なテストができないケース

もあり得ることを認識する。

ポイント

ポイント

3-2 [事例2] オーバーフローに誘発されたゼロ割処理

(28)
(29)

4 ユニットテスト

まとめ

品質の良いユニットテストのために必要なもの

3

3

つの知識が揃って始めて、品質の良いユニットテストができる

つの知識が揃って始めて、品質の良いユニットテストができる

ただし、3つの知識をOJTだけで習得するのは難しい。

Off

Off

-

-

JT

JT

3

3

つの知識を習得する必要がある。

つの知識を習得する必要がある。

ユニットテストの位置づけについての正しい理解

(特にソースコードレビューとの違い)

ユニットテストは開発において非常に重要な工程だが、正しい知識を持って実施

できていることが少ない。

テストケース設計の知識

いかに有用なテストケースを作るかが重要。

テストデータの与え方の知識

テストケースが正しくても、与えるテストデータによって欠陥が検出できるかでき

ないかが決まる。

(30)

単体テスト関連サービスについて

ご質問・ご相談・資料請求はこちらまで

[email protected]

単体テストはどの開発プロジェクトでも実施しますが、明確に実施方法が定まっていません。 そんな開発現場で活用してもらうために単体テストに特化した教育コンテンツを揃えています。 ※【C言語版】【C++言語版】のコンテンツがあります。 本コンテンツを使用したセミナーを定期的に開催しています。 【主催】ガイオ・テクノロジー株式会社 URL : http://www.gaio.co.jp/event/event.html 単体テストはどの開発プロジェクトでも実施しますが、明確に実施方法が定まっていません。 そんな開発現場で活用してもらうために単体テストに特化した教育コンテンツを揃えています。 ※【C言語版】【C++言語版】のコンテンツがあります。 本コンテンツを使用したセミナーを定期的に開催しています。 【主催】ガイオ・テクノロジー株式会社 URL : http://www.gaio.co.jp/event/event.html

単体テスト教育

単体テスト代行サービス

テスト導入支援

ソフトウェア品質を確保するために重要な工程である「単体テスト」を代行します。 ブラックボックス、ホワイトボックス、ロバスト性の観点から、高品質な単体テストを実施します。 単体テスト代行サービスの効果に不安がある場合、試験的に数関数に対して単体テスト代行サービスを実施することも 可能です。 ※ガイオ・テクノロジー株式会社の単体テスト代行サービスを支援しております。 ソフトウェア品質を確保するために重要な工程である「単体テスト」を代行します。 ブラックボックス、ホワイトボックス、ロバスト性の観点から、高品質な単体テストを実施します。 単体テスト代行サービスの効果に不安がある場合、試験的に数関数に対して単体テスト代行サービスを実施することも 可能です。 ※ガイオ・テクノロジー株式会社の単体テスト代行サービスを支援しております。 テスト導入支援は単体テスト以外の内容もカバーしたサービスです。 単体テスト以外(設計や結合テスト)の工程も改善しなければソフトウェア品質が向上しない場合、お客様の現場に合った 方法をご提案します。 【例】テストガイドライン策定、テスト設計レビュー、設計書確認 ※ガイオ・テクノロジー株式会社のテスト導入支援を支援しております。 テスト導入支援は単体テスト以外の内容もカバーしたサービスです。 単体テスト以外(設計や結合テスト)の工程も改善しなければソフトウェア品質が向上しない場合、お客様の現場に合った 方法をご提案します。 【例】テストガイドライン策定、テスト設計レビュー、設計書確認 ※ガイオ・テクノロジー株式会社のテスト導入支援を支援しております。

(31)

単体テスト以外(Android)のサービスについて

ご質問・ご相談・資料請求はこちらまで

[email protected]

Android OSの基礎知識を学ぶとともに、Androidアプリケーション開発の基本となるプログラミングモデルを講義と実習 から習得します。 Android OSの基礎知識を学ぶとともに、Androidアプリケーション開発の基本となるプログラミングモデルを講義と実習 から習得します。

Androidアプリケーション開発

初級編

Androidアプリケーション開発

応用編

Android開発

ポーティング編

Androidの中枢であるアプリケーションフレームワークの仕組みを理解するとともに、実際のAndroidアプリケーション開発 でよく発生する問題点の事例・解決策などを理解することで、より高度なAndroidアプリケーション開発のスキルを習得し ます。 Androidの中枢であるアプリケーションフレームワークの仕組みを理解するとともに、実際のAndroidアプリケーション開発 でよく発生する問題点の事例・解決策などを理解することで、より高度なAndroidアプリケーション開発のスキルを習得し ます。 ターゲットボード上のLinuxシステム上に、Android特有のドライバの構築と、ミドルウェア、Androidアプリケーション等の 搭載を行います。 またAndroidのチューニング技術なども習得する事により、実践的なAndroid技術者の育成が可能になります。 (企画:株式会社エンベデッド・システム 開発:日本システム開発株式会社) ターゲットボード上のLinuxシステム上に、Android特有のドライバの構築と、ミドルウェア、Androidアプリケーション等の 搭載を行います。 またAndroidのチューニング技術なども習得する事により、実践的なAndroid技術者の育成が可能になります。 (企画:株式会社エンベデッド・システム 開発:日本システム開発株式会社)

その他

必要スキル教育(Java,デザインパターン等)

株式会社豆蔵との連携により、Android開発に必要なその他技術要素の習得も可能です。 (Java, デザインパターン, UML等) 株式会社豆蔵との連携により、Android開発に必要なその他技術要素の習得も可能です。 (Java, デザインパターン, UML等)

(32)

参照

関連したドキュメント

地盤の破壊の進行性を無視することによる解析結果の誤差は、すべり面の総回転角度が大きいほ

Q-Flash Plus では、システムの電源が切れているとき(S5シャットダウン状態)に BIOS を更新する ことができます。最新の BIOS を USB

手動のレバーを押して津波がどのようにして起きるかを観察 することができます。シミュレーターの前には、 「地図で見る日本

熱が異品である場合(?)それの働きがあるから展体性にとっては遅充の破壊があることに基づいて妥当とさ  

あれば、その逸脱に対しては N400 が惹起され、 ELAN や P600 は惹起しないと 考えられる。もし、シカの認可処理に統語的処理と意味的処理の両方が関わっ

Q7 

 ・ ナンバープレートを破損、紛失したとき   ・ 住所、氏名、定置場等に変更があったとき  ・

 1号機では、これまでの調査により、真空破壊ライン ベローズおよびサンドクッションドレン配管の破断