これの要点は、Fail Fastです。
コードがなく、コードに応じてテスト分岐プレフィックスであるかどうかを示すプレフィックスの例もありません。これだけです:
- 089-100 =>テストブランチ
- 10B、10C =>テストブランチ
- <088 =>おそらく実際のブランチ
- > 100 =>おそらく実際のブランチ
コードが数字と文字列を許可しているという事実は、少し奇妙です。もちろん、10Bと10Cは16進数と見なすことができますが、プレフィックスがすべて16進数として扱われる場合、10Bと10Cはテスト範囲外になり、実際の分岐として扱われます。
これは、プレフィックスが文字列として保存されているが、場合によっては数字として扱われることを意味します。以下に、この動作を再現する最も単純なコードを示します(説明のためにC#を使用)。
bool IsTest(string strPrefix) {
int iPrefix;
if(int.TryParse(strPrefix, out iPrefix))
return iPrefix >= 89 && iPrefix <= 100;
return true; //here is the problem
}
英語では、文字列が数字で、89〜100の場合、テストです。数値でない場合は、テストです。それ以外の場合は、テストではありません。
コードがこのパターンに従う場合、コードがデプロイされた時点で単体テストでこれを検出することはできませんでした。ユニットテストの例を次に示します。
assert.isFalse(IsTest("088"))
assert.isTrue(IsTest("089"))
assert.isTrue(IsTest("095"))
assert.isTrue(IsTest("100"))
assert.isFalse(IsTest("101"))
assert.isTrue(IsTest("10B")) // <--- business rule change
単体テストでは、「10B」をテストブランチとして扱う必要があることが示されています。上記のユーザー@ gnasher729は、ビジネスルールが変更され、それが上記の最後のアサーションが示すものであると言います。ある時点で、アサートはに切り替わるべきisFalse
でしたが、それは起こりませんでした。単体テストは開発時およびビルド時に実行されますが、その後は実行されません。
ここでの教訓は何ですか? コードには、予期しない入力を受け取ったことを知らせる何らかの方法が必要です。このコードを記述する別の方法は、プレフィックスが数字であることを期待することを強調しています。
// Alternative A
bool TryGetIsTest(string strPrefix, out bool isTest) {
int iPrefix;
if(int.TryParse(strPrefix, out iPrefix)) {
isTest = iPrefix >= 89 && iPrefix <= 100;
return true;
}
isTest = true; //this is just some value that won't be read
return false;
}
C#を知らない人の場合、戻り値は、コードが指定された文字列のプレフィックスを解析できたかどうかを示します。戻り値がtrueの場合、呼び出しコードはisTest out変数を使用して、ブランチプレフィックスがテストプレフィックスかどうかを確認できます。戻り値がfalseの場合、呼び出しコードは、指定されたプレフィックスが予期されていないことを報告する必要があり、isTest out変数は無意味であり、無視する必要があります。
例外で大丈夫なら、代わりにこれを行うことができます:
// Alternative B
bool IsTest(string strPrefix) {
int iPrefix = int.Parse(strPrefix);
return iPrefix >= 89 && iPrefix <= 100;
}
この代替方法はより簡単です。この場合、呼び出し元のコードは例外をキャッチする必要があります。いずれの場合も、コードは、整数に変換できないstrPrefixを予期していないことを呼び出し元に報告する何らかの方法を備えている必要があります。このようにして、コードは迅速に失敗し、銀行はSECの細かい当惑なしに問題を迅速に見つけることができます。