例:Webアプリケーションでフォームの機能テストを実行しながら、さまざまな種類のランダムな入力値を入力してフィールドをテストします。
一般に、Webアプリケーションのユーザーは、実際にはフィールドにランダムな値を入力しません。
では、本番環境でこの種の問題が発生する可能性がはるかに低い場合に、バグにつながる可能性がある/できない可能性があるすべてのテストケースを組み込むことの使用法は何ですか?
注:上記の例はサンプルケースにすぎません。このような問題は、あらゆる種類の機能/モジュールで発生する可能性があります。
この質問をするのは、標準的なプラクティスが従うべきかどうか、それが製品、ドメイン、およびその他すべての要因に完全に依存しているかどうかを知るためだけです。
Webアプリケーションのフィールドにランダムな値を入力しない場合がありますが、それを行う人々は確かにいます。
偶然ランダムに入力する人もいれば、意図的にアプリケーションを壊そうとする人もいます。どちらの場合も、アプリケーションがクラッシュしたり、その他の望ましくない動作が発生したりすることは望ましくありません。
最初のタイプのユーザーの場合、それは彼らに悪い経験を与え、彼らを遠ざけるかもしれないので、あなたはそれを望まないでしょう。
2番目のタイプのユーザーの場合、通常、彼らには立派な意図がなく、アクセスできないはずの情報へのアクセスを許可したり、正規のユーザーのアクセスを拒否したりすることを許可したくないあなたのサービスに。
テストの標準的な方法は、良い天気のケースが機能することだけでなく、異常なEdgeケースを調査して潜在的な問題を見つけ、攻撃者がシステムに簡単にアクセスできないことを確認することです。アプリケーションがすでにランダム入力でクラッシュしている場合、特別に細工された入力を使用して攻撃者ができることを知りたくありません。
偶然または故意に、ユーザーがソフトウェアを「バカ」にしないとは限りません。ユーザーが誤って間違ったボタンを押したり、猫がキーボードの上を歩いたり、システムが誤動作したり、悪意のあるソフトウェアによってコンピュータが乗っ取られたりする可能性があります。
さらに、ユーザー自身が悪意を持っている可能性があり、意図的にソフトウェアを破壊する方法を模索しているため、ソフトウェアを悪用して悪用する方法を見つけることができます。悪用できないバグを見つけたとしても、QAの手順が不足していることを知っていれば、何かを見つけて攻撃できるものがないかシステムを調査する可能性があります。
テストに関する限り、ランダムな入力から保護することは有用ですが、テスト入力を完全にランダムに選択する(つまり、ユースケースやEdgeケースに特別な配慮をしない)のは無意味なものです。テストの目的は、雇用主/クライアント/ユーザーの要件と期待に対してソリューションを検証することです。これは、すべてのEdgeケースと境界条件、およびユーザーの期待されるワークフローに適合しない「縮退」ケースを対象とすることに焦点を当てる必要があることを意味します。
もちろん、後で修正する価値がないと判断したバグを明らかにするテストを実行することもできます。これは、さまざまな理由で発生する可能性があります。ユーザーへの影響に比べて、バグを修正するのに費用がかかりすぎたり、誰も使用していない機能でバグを発見したり、すでにシステムにバグが定着している可能性があります。ユーザーはそれを機能として扱っています。
または、バグの修正に時間を費やすことの商業的メリットがない、「エキスパート」ユーザーのオーディエンスが非常に限定されたカスタムソフトウェアを作成している可能性があります。これらのユーザーはバグのあるソフトウェア(たとえば、診断ツール)内部のITチームが使用しているため、収益が得られないため、たまにクラッシュしても、修正に必要な時間を支払う必要はないでしょう。代わりに、ITチームにバグに対処するように伝えます) 。
ただし、これらのバグについて知っている場合にのみ、これらの決定を行うことができます。たとえば、ユーザーがデータベース全体をワイプする悪意のある入力を入力する可能性があります。このシナリオに対して明示的に保護およびテストしていない場合、これが発生するかどうかを確認する方法はありません。システムに未発見のバグが残るリスクは、これらのバグの1つが現実世界で明らかになり、ユーザーに大きな影響を与える場合、潜在的に実際の問題に自分をさらし続けていることを意味します。
したがって、バグを修正するかどうかの決定には、ソフトウェアの所有者(通常は給与を支払う人)からの入力が必要になる場合がありますが、バグをテストするかどうか、およびどのケースをテストするかについての決定は、エンジニアリング上の問題であり、見積もりとプロジェクト計画に織り込んでいます。目標は、時間/お金/リソースの制約を考えれば、合理的に可能な限り完全なカバレッジに近いものにすることです。
考慮すべき要素がいくつかあります。これらのポイントを説明するために、タスクが使用できるディスク容量の観点から、ユーザーが特定のタスクに定義されたクォータのコンテキストでパーセンテージを入力する必要があるフィールドの例を使用します。 0%は、タスクがディスクに何も書き込むことができないことを意味します。 100%は、タスクがすべてのディスク領域をいっぱいにできることを意味します。中間の値は、それらが意味することを意味します。
開発者として、あなたはおそらく許容値が[0、1、2、3、⋯99、100]であり、それ以外はすべてばかげていると考えているでしょう。ユーザーがこれらの「ばかげた」値をまだ入力できる理由を見てみましょう。
%^
ユーザーが値56を入力していたが、誤って押した Shift 入力中(たとえば、フランス語のキーボードでは、 Shift 数字を入力するために、ユーザーは常にフランス語のキーボードとQWERTYを切り替えていました。
同じように、数値を取得できます。数値の前後またはその間にあります。
56q
ここでは、ユーザーはおそらく数字を入力しており、次のフィールドに移動するためのタブが続きます。押す代わりに ⇆ 、ユーザーが隣接キーを押した。
空の入力がおそらく最も一般的です。ユーザーは、フィールドがオプションであると想像したか、このフィールドに何を入力するかわからなかった。
56.5
ユーザーは、浮動小数点値は許容できると考えました。ユーザーが間違っており、アプリケーションは整数値のみが受け入れられる理由、または初期要件が間違っていた理由を丁寧に説明する必要があり、ユーザーに浮動小数点値を入力させるのは理にかなっています。
none
ユーザーは、タスクが取ることができるスペースを要求されたときに、アプリは数値を期待していると誤解しました。これは、不十分なユーザーインターフェイスを示している可能性があります。たとえば、「タスクに必要なディスク容量はどれくらいですか」とユーザーに尋ねます。 「なし%」はあまり意味がないため、この種の入力への招待は、パーセント記号が続くフィールドはその種の入力をあまり受け取りません。
150
ユーザーは、この場合のパーセンテージの意味を誤解しています。たぶん、ユーザーはタスクが現在使用されているスペースの150%を使用できることを伝えたかったので、2 TBのディスクで100 GBが使用されている場合、タスクは150 GBを使用できます。繰り返しになりますが、ユーザーインターフェースの改善が役立ちます。たとえば、パーセント記号が付加された裸の入力フィールドの代わりに、次のようにすることができます。
[____] % of disk space (2 TB)
ユーザーが入力を開始すると、その場でテキストが次のように変更されます。
[5___] % of disk space (102.4 GB of 2 TB)
大きな数値または浮動小数点数は、異なる方法で表すことができます。たとえば、1234.56という数字は、1,234.56
のように書くことができます。文化に応じて、同じ数のテキスト表現は異なります。フランス語では、同じ番号は1 234,56
のように表記されます。ほら、期待しないコンマとスペース。
特定のロケールを使用する特定の形式を常に期待すると、遅かれ早かれ問題が発生します。国によってユーザーは、数字、日付、時刻などを書く習慣が異なるためです。
Twenty-four
普通の人間はコンピュータと同じようには考えていません。 「24」は、PCからの通知とは関係なく、実際の数です。
(1)ほとんどのシステムはこのタイプの入力をまったく処理しませんが、(2)ほとんどすべてのユーザーは完全な文字で書かれた数字を入力することを想像しませんが、そのような入力が愚かであることを意味しません。 About Face 3で、Alan Cooperは、そのような入力を処理しないことは、コンピュータが人間に、そして理想的にはインターフェースに適応できないことを示していると指摘しましたこれらの入力を正しく処理できる必要があります。
私がアランクーパーの本に追加しなければならない唯一のことは、多くの場合、数字が誤って数字で書かれていることです。コンピュータがユーザーに間違いをすることを期待している(そして、正しく書き込むユーザーを容認しない)という事実は厄介です。
5????
Unicodeには独自の驚きがあります。同じに見える文字も同じではありません。納得できませんか?ブラウザの開発者ツールに"5????" === "56"
をコピーして貼り付け、 Enter。
これらの文字列が等しくない理由は、Unicode文字????
が文字6
と同じではないためです。これは、怒っている顧客が電話をかけて、アプリが機能していないことを伝え、合法に見える入力のスクリーンショットを提供し、アプリが入力が無効であると主張する状況を作成します。
なぜ誰かが数字のように見えるユニコード文字を入力するのですか?ユーザーが意図せずに文字を入力することはないと思いますが、別のソースからのコピーと貼り付けが原因である可能性があり、実際にはユーザーがUnicode文字を含む文字列のコピーと貼り付けを行った場合、画面に表示されます。
これらは、基本的な数値入力フィールドの場合です。日付や住所など、より複雑なフォームで何を処理する必要があるか想像してもらいます。
私の答えは、あなたが「ばかげた」入力と呼んでいるものに焦点を当てています。テストは、ハッピーパスをチェックすることではありません。また、悪意のあるユーザーが意図的に奇妙なものを入力し、それを壊そうとしたときに、アプリが壊れないことを確認することも重要です。つまり、パーセンテージを求める場合、ユーザーが1,000,000文字を含む文字列、負の数、または bobby table で応答したときに何が起こるかをテストする必要もあります。
これがなぜ重要であるかを説明する良い答えがたくさんありますが、アプリケーションを慎重に保護する方法についてのアドバイスはあまりありません。 「標準的な方法」は、クライアントとサーバーの両方でrobust input validation、を使用することです。意味のない入力は簡単に防御できます。その特定のコンテキストで意味をなさないものはすべて拒否します。たとえば、社会保障番号はダッシュと数字のみで構成されています。ユーザーが社会保障番号フィールドに入力したもの以外は安全に拒否できます。
作成するすべてのアプリケーションで実行する必要がある2種類のテストがあり、それぞれに異なる目的があります。自分のアプリケーションで行うテストは肯定的なテスト;その目的は、プログラムが機能することを証明することです。テスターがアプリケーションでさらに行うテストis negative Testing;その目的は、プログラムが機能しないことを証明することです。なぜこれが必要なのですか?あなたは自分のソフトウェアをテストするのに最適な人ではないからです。結局のところ、あなたはそのことを書いたので、明らかにそれはすでに機能していますよね?
入力検証を作成する場合、検証が機能することを証明するために肯定的なテストを採用します。テスターはランダムな入力を使用して、機能しないことを証明しようとします。ランダム入力の問題空間は本質的に無制限であることに注意してください。目標は、考えられるすべての順列をテストすることではなく、無効な入力を拒否することで問題のスペースを制限することです。
また、プログラムに入力を提供するのはエンドユーザーだけではないことにも注意してください。作成するすべてのクラスには独自のAPIと有効な入力と見なされるものに対する独自の制約があるため、堅牢な検証(つまり「コードコントラクト」)もクラスにとって重要です。考えられるのは、ソフトウェアを強化して、予期しない動作が発生しないか、可能な限り最大限に存在しないようにすることです。
最後に、ワークフローは重要です。ユーザーが意味のない何かを入力したのではなく、アプリケーションで予期しない順序でアプリケーションが実行されたため、アプリケーションがフォールオーバーするのを見てきました。アプリケーションはこの可能性を認識し、予期しないワークフローを適切に処理するか、ユーザーに指定された順序で操作を実行するよう要求する必要があります。
通常、「ランダム」値はランダムではありません。 「未知の未知」であるEdgeケースをキャプチャしようとしています。
たとえば、#文字がアプリをクラッシュさせるとします。あなたはこれを事前に知らないので、あらゆる可能な入力に対してテストケースを書くことは不可能でしょう。しかし、"¬!"£$%^&*()_+-=[]{};'#:@~,./<>?|\"
のテストを記述して、それが壊れるかどうかを確認できます
私はかつてプログラムを書いて、それを60人の学生と一緒にラボでライブテストしました。私は60のコンピュータ画面の後ろに立っていて、彼らがそれを使うのを見ました。彼らがやったばかげたことの量は、髪を上げることでした。彼らの「創造力」を見て汗だくになりました。彼らは、一人の個人が一生のうちに空想することができるよりもはるかに多くのことをしました。もちろん、そのうちの1人はそれを壊しました。
その後、私はアプローチに従います:if "a very specific use case" do, else show error
複数のユースケースがある場合は、それらを厳密に定義し、上記を連鎖させます。
あなたが説明しているのは ファジングまたはファズテスト :システムでランダムで無効な入力をスローし、何が起こるかを確認します。ユーザーがそうすることを期待するので、これをしません。 あなたはそれをあなた自身の仮定とバイアスを公開するために行いますあなたのシステムのエッジを強調して何を見るか起こります。
人間が書いた通常のテスト入力には、仮定とバイアスが伴います。 これらのバイアスは、特定のクラスのバグがテストでは発見されない可能性があります。
たとえば、入力のほとんどがASCIIセーフのUnicodeの範囲内にある場合、コード内の文字エンコーディングに関する仮定は行われません。または、それが常に特定のサイズを下回っている可能性があるため、固定サイズのフィールドまたはバッファにヒットしません。あるいは、ユーザー入力がシェルに供給されたり、安全でない方法でクエリを構築したりするために使用されることを明らかにする、驚くべき方法で解釈される特殊文字があるかもしれません。または、多すぎる「ハッピーパス」テストがあり、エラー処理を実行するための十分な試行がない場合。
ファジングには、入力に関するそのような先入観はありません。 「有効な」入力のあらゆる可能な組み合わせでシステムを残酷に行使します。 Unicode、ASCII、大きな、小さな、そしてたくさんのエラー。あなたのシステムはそれらすべてに優雅に反応するはずです。クラッシュすることはありません。ユーザーは、何が問題で、どのように修正するかについて、ある種の賢明なメッセージを常に受け取る必要があります。ガベージイン/ガベージアウトではなく、ガベージイン/エラーアウトです。
「実際のユーザーはそれを行わない」ために結果として生じる爆発を却下するかもしれませんが、それは演習の要点を逃します。 ファジングは、可能な入力に関するバイアスを排除する安価な方法です。これは、すべてを投げる安価な方法ですユーザーがシステムで実行しようとする奇妙なこと。エンジニアとしてのあなたの仕事は、システムが適切に故障することを保証することです。
さらに、ファジング「入力」はユーザーだけのものではありません。サードパーティサービスへのAPIクエリの結果である可能性がありますが、それがめちゃくちゃな結果の送信を開始した場合はどうなりますか?あなたのシステムはそれをどのように扱いますか?適切なシステムは、コンポーネントが不良になったことを管理者に警告する必要があります。不適切なシステムは、不適切なクエリを静かに拒否するか、悪いことに、それを適切なデータとして受け入れます。
最後に、一部のユーザーは悪意があります。システムをファズテストしない場合、他の誰かがテストします。彼らはあなたのシステムの端によくある間違いを探り、それらをセキュリティホールとして使用しようとします。ファズテストはこれをある程度シミュレーションでき、問題が発生する前に発見されたセキュリティホールに対処できます。
高品質の製品を作成することを目的としている場合は、ユーザーが物理的に送信できる可能性のあるあらゆるタイプの入力をテストします。それ以外の場合は、誰かがテストの必要性を感じなかった1つのタイプの入力を送信する日を待っているだけです。
私が働いていた地方自治体で新しいeオークションソフトウェアの大規模なデモンストレーションを行っているときに、マネージャーは(確かにいたずらで)、負の値でオークションに入札した場合に何が起こるかを確認する必要があると感じました。驚いたことに、オークションソフトウェアはこの無意味な入札とオークションプロセス全体の停止を許しました。示されている種類のオークションでは、マイナスの金額を送信することはできません。
集まった調達および財務担当者の大規模なグループの一部は、無意味な値を送信したことで私のマネージャーに不快に感じました。しかし、私を含む他の人たちは、そのような明白なタイプの無効な入力をテストして拒否することに失敗したことで、ソフトウェア開発者に悩まされていました。他のタイプの無効な入力(コードインジェクションの試み、データベーステーブルでは表現できないエキゾチックな文字など)をそらすのにソフトウェアがどれほど弱いに違いなかったかしか想像できません。
それは私次第だったので、ソフトウェアを返却し、目的に適さないと判断しました。弱いソフトウェア製品と強いソフトウェア製品の違いは、それが受けたテストのレベルです。
例:Webアプリケーションでフォームの機能テストを実行しながら、さまざまな種類のランダムな入力値を入力してフィールドをテストします。
はい。これはテストの一種ですが、機能テストではありません。これはストレステストと呼ばれるものです。システムに圧力をかけて、それが処理できるかどうかを確認する行為です。
では、本番環境でこの種の問題が発生する可能性がはるかに低い場合に、バグにつながる可能性がある/できない可能性があるすべてのテストケースを組み込むことの用途は何ですか?
stressソフトウェアをテストしているとき、ソフトウェアの限界の境界を発見しようとしています。
テストは本質的に完全な方法です。使用制限、限界点を発見する必要がある場合、すべての論理ブランチをチェックするか、部分的な障害がシステム全体にどのように影響するかを確認します。
すべての機能テストに合格することはできますが、stressテストは失敗します。
この質問をするのは、従うべき標準的なプラクティスがあるかどうか、それが製品、ドメイン、およびその他すべての要因に完全に依存しているかどうかを知るためだけです。
はい、これは標準的な方法です。
ソフトウェアのテストは、期待される動作について質問することであり、すべてのテストに合格すると、ソフトウェアが意図したとおりに動作することを伝えます。これが、更新を展開するための適切な前提条件をテストが作成する理由です。
ストレステストでは、明確な特定の合格または不合格の指標は提供されません。結果はより有益です。それはあなたのシステムが何を処理できるかをあなたに知らせ、あなたはその情報から決定を下します。
開発の次の段階に進むために合格する必要があるストレステストの特定の目標を定義できます。これらは品質保証プロセスの一部として含めることができますが、環境の変化によってストレステストの結果が変わる可能性があります。したがって、人々はストレステストを異なる回で実行して、システムが変化する条件をどのように処理するかを確認します。
つまり、新しいバージョンのソフトウェアを展開するたびにストレステストを実行するだけではなく、すべてが後でストレステストに合格するということです。