修司(293)308308件のシェア(そこそこ話題の記事)この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。テスト分類のひとつにブラックボックステストとホワイトボックステストがあります。ブラックボックステストとは、テスト対象の内部を意識せずに外部仕様のみからテストケースを構築していく手法です。ユニットテストであれば、テスト対象となるメソッドの実装(コード)を意識せず、メソッドのAPI仕様からテストケースを作成することになります。ホワイトボックステストでは、テスト対象の内部を意識し、どのような構造であるかを踏まえたテストケースを構築します。ユニットテストであれば、テスト対象となるメソッドの実装(コード)を意識し、分岐や繰り返しなどを考慮しつつテストケースを作成することになります。それともブラックボックステストでしょうか?「JUnit実践入門」では次のように記述しました。本書で扱うユニットテストは、テスト対象の内部ロジックを考慮して行うため、どちらかといえばホワイトボックステストに分類されます。内部ロジックに依存しすぎたユニットテストは、変更に対して脆くなるため、テスト対象の外部仕様からテストデータを選択したほうがよいという側面もあります。このため、ユニットテストは、ホワイトボックステストとブラックボックステストを組み合わせて行います。(P.27)Amazonでチェックする書籍では分量の関係から詳細な解説ができませんでしたので、少し掘り下げて解説したいかと思います。外部仕様からテストケースを作るワケユニットテストを実践する理由はたくさんあります。その中で、最も重要な理由は、安全なリファクタリングを行うことにあると言って良いでしょう。リファクタリングとは「ソフトウェア(メソッドやクラス)の外部的振る舞いを変えずに内部構造を変更すること」です。ユニットテストの対象となるクラスやメソッドは、何らかの責務を持つように設計されます。それらはどこか別のクラスやメソッドから利用されます。どこか別のクラスやメソッドから利用されるということは、勝手に振る舞いが変わったならば大変なことになります。このため、ユニットテストが浸透していない開発現場では、一度リリースしたコードには原則として変更を加えてはならない、一度リリースした後は外部ライブラリやJavaのバージョンを変更してはならない、といった悪習が残ることになります。それらの悪習は、ユニットテストがないならば仕方ありません。変更した時にどのような影響が出るか、全く解らないのです。ユニットテストを実践することにより、これらの不安は大きく減ります。少なくとも、クラスやメソッドに定義された仕様が変更されない限り、その動作が保証されるわけです。そのテストが成功している限り、内部の実装を自由に変更できることになります。このため、ユニットテストでは、どれだけ外部仕様を網羅するように実装され、外部仕様を保証するかが重要なファクターとなります。どの程度まで保証したらば良いかは、そのクラスやメソッドがどの程度公開されるかに依存します。外部ライブラリとして公開されるAPIなのか、プロジェクト内でのみ公開されるAPIなのかなどでも変わってくるでしょう。FizzBuzzで外部仕様を考えるユニットテストの主たる目的は安全なリファクタリングです。したがって、外部仕様を元にブラックボックステストを行う事が理想と言えます。現実としては内部ロジックを考慮して行うことが行うことが多いと言えます。テスト駆動開発(TDD)を実践したり、TDD的なプログラミングを行っている場合は顕著になります。ここで、みんな大好きFizzBuzzを例にしましょう。FizzBuzzでは、整数が3の倍数の時にFizz、5の倍数の時にBuzz、3と5の公倍数の時にFizzBuzz、それ以外の時にその整数を表示していくプログラムです。このプログラムを、ちょっと大袈裟に、設計するならば、整数と出力する文字列の変換部分が最も重要な処理となるということが解ります。変換部分は次のようなメソッドとなります(実装はあえて省略)。}このFizzBuzzシステムの最重要APIは、安全なリファクタリングのためにも、ユニットテストを書かなければなりません。ここでユニットテストに慣れていないと、どこからどれだけテストすればいいの?という問題にぶちあたります。テスト駆動開発とホワイトボックステストテスト駆動開発のこころ((c)@t-wada)は、「小さく、ひとつづつ」です。外部仕様を満たすテストデータをひつつ選択し、それを満たすように実装・テストします。簡単に、適当な値でFizzでもBuzzでもFizzBuzzでもないテストケースを考えましょう。そこで入力値として1を選択し、文字列1が取得できることが満たせればいいと考え、テストケースに落とし込みます。}これのテストケースを満たすように、最小限の実装で実装するのがテスト駆動開発です。プロダクションコードはこのようになります。it)という手法です。次に、Fizzが返る入力値として3、Buzzが返る入力値として5、FizzBuzzが返る入力値として15と選択していき、仮実装も本来有るべき実装にすれば次のようになります。}}内部ロジックを考慮するユニットテストFizzBuzzをステップバイステップで、ユニットテストを行っていくと、テストケースの追加と分岐(if文)の追加が連動していることが解ります。言い換えれば、外部仕様に対する内部ロジックを追加し、それに対するテストケースを同時に作っているのです。実は、テスト駆動開発の最も効果的な点はこの仕組みにあります。処理(分岐や繰り返し)を実装した後にテストケースを考えようとしても、どうしても漏れが生じたり、そもそも面倒になってくるのです。1つ1つ倒しながら進んでいくことで、確実にユニットテストで守られたプロダクションコードを作ることができるわけです。if文が追加されたら、それに対応するテストケースが必要、って考えれば当然ですよね。これって、テストの分類から考えると、どちらかといえばホワイトボックステストです。ブラックボックステストの観点からすれば、内部実装は他の会社に任せるなどして、テストケースだけを黙々として書くイメージでしょうか。テスト駆動開発を行っていたとしても外部仕様が増えたからテストケースを追加...と考える事もできますが、プログラマとしてはif文を追加したんだからテストも書かないと!と考える方が自然です。さあ、リファクタリングの時間だ!テスト駆動開発を行っていたにせよ、行っていなかったにせよユニットテストは充分に行われています。現状では、パフォーマンスが悪いとクレームがついたため、判定回数を減らすように修正しようとなりました。}可読性は悪くなりましたが、判定効率はあがったはずです。ここでユニットテストを実行し、成功する事を確認出来れば、外部的な振る舞いに影響を与えていないことが解ります。ここで内部実装とテストコードの対応を確認してみます。すると、初期バージョンでは、テストケースと内部実装がほぼ1対1に対応していたのですが、リファクタリング後のコードでどの分岐とどのテストケースが対応するかは解りにくくなりました。最初から複雑なロジックで書かれた内部実装があり、それに対するユニットテストを書くという状況であれば、ユニットテストはブラックボックステストになるでしょう。テスト駆動開発を採用している時のように、実装とテストをほぼ同時に行い、リファクタリングはユニットテストのある状況で行うならば、はじめはホワイトボックステスト的となります。その方が簡単で楽にテストを書くことができますね。ホワイトボックステストは内部実装に大きく影響されるため、正しいのか正しくないのか良くわからないプログラムや、複雑すぎて理解ができないプログラムに行うと危険です。シンプルにひとつづつ内部実装を増やしていくテスト駆動開発と組み合わせると非常に強力なテスト手法となります。外部仕様と内部実装とテストコードがすべて対応している状況を作り、最後にリファクタリングを行うのがベストプラクティスでしょう。複雑すぎるスパゲティなシステムや、エンドトゥエンドのテストでは、内部実装を考慮するよりも外部仕様のみに着目し、ブラックボックステストとして、テストケースを組み立ててください。これはコスト的な観点が一番大きいですが、効率よく、価値のあるテストを行うために必要となるでしょう。ホワイトボックステストとブラックボックステストはそれぞれの特徴を生かして、上手に使いわけてください。弊社はホワイト企業です。2,937,905札幌の猫大好きエンジニア。著書に「JUnit実践入門」。趣味はロードバイクやスノーボードなど。Developers.IOでは、ユニットテスト・AWS・Ansibleの話題などを書いています。リモート】クラスメソッドの会社説明会を開催しますクラスメソッドでは、AWS・AI・ビッグデータ・モバイルなどの技術職や営業のメンバーとして一緒にお仕事をする仲間を大募集しています。#cmdevio新型コロナウイルスの感染拡大を受け、本イベントを延期させていただくことになりました(開催時期未定)。お申し込みいただいた皆様には大変申し訳ございませんが、何卒ご理解いただけますようよろしくお願いいたします。AWSについてライトに色んな情報交換をしましょう。カフェ店長のオカノです。今日はオフィスに用があるので、通勤ラッシュを避けて出社しました。この子は新メンバーのさめくんです。在宅勤務が推奨されているのでオフィスが閑散としており、すこしさみしそうです。本が出ていたので読んでみたところよかったので紹介させていただきます。使いたいときの注意点を書きました。新井成一64最近Sphinxつかってドキュメントを書いてるのですがなかなかイケています。臼田佳祐295ワークフロー自動化OSSのn8nをAWS環境で建てて検証してみました。非常に期待できるサービスです。Fargateの勉強をしています。使ってみたい方は参考にしてください。洋介255SnowflakeがAWSの東京リージョン上で稼働するようになりました。データを日本に置けます。芳賀健232こんにちは!猫様の忠実なるしもべ、芳賀健です。Tokyoで開催されました。カフェ店長のオカノです。クラスメソッド株式会社が運営するAWS・iOS・HTML5に関する技術情報サイトです。