私はTDDを初めて使用しますが、RegExpは非常に特殊なケースです。それらをユニットテストする特別な方法はありますか、それとも通常の関数として扱うことができますか?
他のコードのチャンクと同じように、常にregexenをテストする必要があります。これらは、文字列を受け取ってブール値を返すか、値の配列を返す最も単純な関数です。
Regexenの単体テストを設計する際に考慮すべきいくつかの提案があります。これらは、単体テスト設計の厳格で迅速な処方箋ではありませんが、思考を形作るためのいくつかのガイドラインです。いつものように、テストのニーズと失敗のコストを、それらすべてを実装するために必要な時間とバランスをとって比較検討します。 (テストの「実装」は簡単な部分だと思います!:-])
考慮すべきポイント:
リストを返す正規表現については、次のことも覚えておいてください。
(?<name> thing1 ( thing2) )
)-この動作は、使用している正規表現エンジンによって異なる場合があります。非バックトラッキンググループなどの高度な機能を使用する場合は、その機能がどのように機能するかを完全に理解し、上記のガイドラインを使用して、それぞれに対して機能するサンプル文字列を作成してください。
正規表現ライブラリの実装によっては、グループのキャプチャ方法も異なる場合があります。 Perl 5には「オープンパレンオーダー」の順序があり、C#には名前付きグループなどを除いて部分的にそれがあります。フレーバーが何をするのかを正確に知るために、フレーバーを試してみてください。
次に、それらを他の単体テストと統合します。独自のモジュールで、または正規表現を含むモジュールと一緒に統合します。特に厄介なregexenの場合、使用するパターンとすべての機能が正しいことを確認するために、多くのテストが必要になる場合があります。正規表現がメソッドが実行している作業の大部分(またはほぼすべて)を構成している場合は、上記のアドバイスを使用して、正規表現ではなく、その関数をテストするための入力を作成します。そうすれば、後で正規表現がうまくいかないと判断した場合、または正規表現を分割したい場合は、インターフェイス(つまり、正規表現を呼び出すメソッド)を変更せずに、正規表現が提供する動作をキャプチャできます。
正規表現機能が正規表現のフレーバーでどのように機能するかを本当に知っている限り、それに対する適切なテストケースを開発できるはずです。機能がどのように機能するかを本当に、本当に、本当に理解していることを確認してください!
そこにたくさんの値を投げて、正しい結果が得られることを確認します(一致/不一致、または特定の置換値など)。
重要なのは、あなたが不思議うまくいくかどうかというコーナーケースがある場合は、それらを単体テストでキャプチャし、コメントで説明してくださいなぜうまくいくか。そうすれば、正規表現を変更したい他の誰かが、コーナーケースがまだ機能していることを確認でき、壊れた場合の修正方法についてのヒントが得られます。
おそらく、正規表現はクラスのメソッド内に含まれています。例えば:
public bool ValidateEmailAddress( string emailAddr )
{
// Validate the email address using regular expression.
return RegExProvider.Match( this.ValidEmailRegEx, emailAddr );
}
これで、このメソッドのテストを作成できます。重要なのは、正規表現が実装の詳細であるということです。テストではインターフェイスをテストする必要があります。この場合は、電子メールの検証メソッドにすぎません。
他のすべてのテストケースと同じように、期待される出力値を使用して入力値のセットを作成します。
また、無料の正規表現ツール Expresso を徹底的にお勧めします。これは、過去の苦痛の日々を救ってくれた素晴らしい正規表現エディター/デバッガーです。
この素晴らしいツールを誰も投稿していないなんて信じられません。
正規表現をテストできます。一致する必要のある文字列と一致しない文字列を含むテキストを定義します。すべて緑色の場合は問題ありません。たとえば、ナメクジと一致させるために作成したものは次のとおりです。 http://refiddle.com/by/callum-locke/slug-matcher
他の機能と同じように、常にテストします。一致する必要があると思われるものと一致し、一致してはならないものと一致しないことを確認してください。
最初にテストを作成し、各テストに合格するために必要な量の正規表現のみを作成することを検討してください。正規表現を拡張する必要がある場合は、失敗したテストを追加してください。
簡単な入出力テストで十分だと思います。時間が経ち、正規表現が失敗する場合が発生する場合は、修正中にこれらのケースもテストに追加することを忘れないでください。
反対の正規表現に対して正規表現をテストするのが好きです。可能なテストに対して両方を実行し、交差点が空であることを確認します。
選択した単体テストライブラリのフィクスチャを使用し、通常のTDDアプローチに従います。
テストランナーとしてのスポックのサンプルフィクスチャスタブは次のとおりです。
@Grab('org.spockframework:spock-core:1.3-groovy-2.5')
@GrabExclude('org.codehaus.groovy:groovy-nio')
@GrabExclude('org.codehaus.groovy:groovy-macro')
@GrabExclude('org.codehaus.groovy:groovy-sql')
@GrabExclude('org.codehaus.groovy:groovy-xml')
import spock.lang.Unroll
class RegexSpec extends spock.lang.Specification {
String REGEX = /[-+]?\d+(\.\d+)?([eE][-+]?\d+)?/
@Unroll
def 'matching example #example for case "#description" should yield #isMatchExpected'(String description, String example, Boolean isMatchExpected) {
expect:
isMatchExpected == (example ==~ REGEX)
where:
description | example || isMatchExpected
"empty string" | "" || false
"single non-digit" | "a" || false
"single digit" | "1" || true
"integer" | "123" || true
"integer, negative sign" | "-123" || true
"integer, positive sign" | "+123" || true
"float" | "123.12" || true
"float with exponent extension but no value" | "123.12e" || false
"float with exponent" | "123.12e12" || true
"float with uppercase exponent" | "123.12E12" || true
"float with non-integer exponent" | "123.12e12.12" || false
"float with exponent, positive sign" | "123.12e+12" || true
"float with exponent, negative sign" | "123.12e-12" || true
}
}
次のようなスタンドアロンのGroovyスクリプトとして実行できます。
groovy regex-test.groovy
免責事項:スニペットは、数週間前に書いた一連のブログ投稿から抜粋したものです。