ゾンビ黙示録を生き残った方法


偉大なテストケースを選択するのは非常に難しいです.アンデッドを召喚しない限り.

問題


ソフトウェアテストは、ほとんどの開発者のための新しい規律です.
品質保証エンジニアは、ユースケースの作成に最適な方法論を持っています.
その上、Test-Driven Development(TDD)技術は、開発者をテスト書く世界に押しつけました.( TDDがテスト手法ではないため、世界をテストしない).
しかし、まだ準備ができていません.


TDD個人旅行


2005年にTDDに戻ってきました.私はXUnit回帰、ドメイン発見と完全な報道と恋に落ちました.
TDDは信じられないほどのテクニックですが、テストするものを決めるのは面倒です.
私は数年の間、混沌とした方法でTDDテストを書きました.
私は、私がこれらの年が新しい開発者に若干の時間を惜しむことを望むと学んだ若干のものをまとめます.

解決策


テストデータに対するテストケースを区別する方法を学びます。


ほとんどのプログラマは、データとインスタンス化を愛し、抽象的な概念を扱う困難を持っている.
彼らは、関連するケースを選ぶ大きな絵が見つからないテストデータを作成するために急ぎます.
テストケースを表す正確なデータの選択は簡単でなければならない.反対は真実ではない.
Equivalence Partitioningは、正しい大使を選ぶためのテクニックです
すべての可能なケースを有限数の等価クラスに分割する.
各クラスの代表値のテストが他の値のテストと等価であると合理的に仮定できます.

テスト番号


あなたがTDD方法の作成順序を開発している場合はどのように問題に近づいて示しています.
最初のケースは理解しやすく、非常に低い結合であるべきです.
赤ちゃんの手順は徐々に我々は徐々にそれに対処することができます我々のテストの複雑さを増加する必要があります.初期の緑の光は貴重なフィードバックです.

選んでゾンビ


Zombie testingは以下の頭字語です:
Zゼロ
- 1
M -多数(またはより複雑な)
境界挙動
I -インターフェース定義
特別な行動
シンプルなシナリオ、シンプルなソリューション


電子メールメッセージを作成しましょう.
一度に一つの行動!
空のテストクラスから始めましょう.
TestCase subclass: #EmailMessageTest
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Zombies'
最初のテストは、我々の(Z)Eroです.私たちはTDDを働いているので、まだメールメッセージクラスを定義していません.
test01ZeroRecipients

    self deny: (EmailMessage forRecipients: Array new) isValid

name test01ZeroRecipients is composed by
  • 多くのテストフレームワークにおける接頭辞テスト義務.(強制)
  • シーケンシャル順序(学習/テスト手順をインクリメンタルに示す).(オプション)
  • ゼロ/1/多くのゾンビを表すために.(オプション)
  • 機能的な説明(必須)
  • 我々は否定を開始します(偽を主張する)最初のメールは有効です.(受信者がないので).
    (否定することは、2つのネガティブを読んで、避けるのをより明確ではないと主張することと等しいです).
    最初のテストを実行します.
    電子メールクラスが定義されていません
    Object subclass: #EmailMessage
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'TDD-Zombies'
    
    受取人: (コンストラクタ)
    forRecipients: recipients 
    
        ^self new initializeForRecipients: recipients 
    
    コンストラクタはインスタンスを作成し、本質を初期化します(アンチパターンsettersとnoからmutationはありません).
    プライベート初期化子
    initializeForRecipients: emailRecipients 
    
        recipients := emailRecipients.
    
    Initializerプライベート属性を設定します.
    これはisvalidの最初の(十分な)実装です.
    isValid
         ^false 
    
    isvalidはfalseにハードコード化されます.
    これはTDD値の一つです.最も簡単な解決策はハードコード化されるべきです.
    最初のテストパス!
    行きましょう.
    test02OneRecipient
    
        self assert: (EmailMessage forRecipients: (Array with: '[email protected]')) isValid.
    
    
    前の手順でfalseにハードコード化したので、テストは動作しません.
    isValidの実装を変更します.
    isValid
         ^recipients notEmpty 
    
    この状態はより一般的です.今テスト01とTEST 02作業!
    Test 02に新しいプロトコルを加えましょう.それは異なるテストケースでなければなりません、しかし、我々はテスト2をオーバーロードします.
    test02OneRecipient
    
        self assert: (EmailMessage forRecipients: (Array with: '[email protected]')) isValid.
        self assert: (EmailMessage forRecipients: (Array with: '[email protected]')) plain = 'to: [email protected]'.
    
    
    プレーンメッセージは、電子メールからプレーンテキストを返します.実装しましょう.
    plain
         ^'to: ' , recipients first.
    
    最初の受信者を持つヘッダー.ハードコーディング.
    ( ZO )テストができます.何のためにも行きましょう.
    test03ManyRecipients
    
        | message |
        message := (EmailMessage forRecipients:
     (Array with: '[email protected]' with: '[email protected]' with: '[email protected]')).
    
        self assert: message plain = 'to: [email protected],[email protected],[email protected]'.
        self assert: message isValid
    
    
    この時点でそれを作るよりも偽にするのは難しいです.これは、ハードコード化の代わりにリファクションをしてジェネリックソリューションを作るヒントです.
    多くは3要素のコレクションで表されます.iSvalidは動作しますが、プレーンではありません.
    plain
         ^(recipients inject: 'to: ' into: [:plainText :address | plainText, address ,' ,' ]) allButLast         
    
    このイディオムは、受信者(プライベート属性、getters)を繰り返し、コンマ(挿入)を挿入し、最後の1つを削除します.我々には爆発がないので.
    3テスト作業!(ZOM)
    我々は(b)寄り添いに取り組むべきだ.
    test04BoundaryRecipients
    
        | recipients |
        recipients := OrderedCollection new.
        1 to: 10 do: [:index | recipients add: ('john', index asString, '@example.com')].
    
        self deny: (EmailMessage forRecipients: recipients) isValid
    
    我々は10種類のメール[email protected][email protected]、…を作成します.[email protected] .
    私たちは10は、この運動のための受取人サイズの任意の上限値を決定します.
    10受信者とのメッセージは有効ではありません.
    isValid
         ^recipients notEmpty and: [recipients size < 10] 
    
    この状態は、下限と上位のものをチェックします.以下のようになります.
    isValid
         ^recipients size between: 1 and: 9  
    
    以来、我々はいつでも実装を変更することができます完全なカバレッジを持っている!
    中でゾンビ.( i ) nterfacesチェックの時間です.
    test05InterfaceDefinition
    
        self should: [ EmailMessage forRecipients: 1 ] raise: Exception
    
    私たちは、我々のインターフェースに違反する整数でメッセージを作成しようとするので、それは例外を上げなければなりません.
    forRecipients: recipients 
    
        recipients do: [:eachAddress | 
            eachAddress isString
                ifFalse: [ self error: (eachAddress , ' is not a valid recipient')]].
    
        ^self new initializeForRecipients: recipients 
    
    作成時にアドレスを検証します.無効なオブジェクトはここにありません!
    ここのゾンビ!方法についてはxceptional行動?
    test06ExceptionalBehavior
    
        self should: [EmailMessage forRecipients: (Array with: '[email protected]' with: '[email protected]')] raise: Exception
    
    重複はドメインによって無効です.彼らをチェックしましょう!
    forRecipients: recipients 
    
    recipients do: [:eachAddress | 
        eachAddress isString
            ifFalse: [ self error: (eachAddress , ' is not a valid recipient')]].
        (recipients asSet size = recipients size)
            ifFalse: [self error: 'Duplicates'].
    
        ^self new initializeForRecipients: recipients 
    
    我々の受信者をセットにマッピングして、両方のサイズをチェックしている複製をチェックします.ではなく、最もパフォーマンスの方法.
    私たちは例を働かせて、早めの最適化を避ける必要があります.すべてのテストを実行すると、コードを最適化できます.


    読みやすさは?方法は醜い.TDDステップ3をしましょう:リファクタ.
    forRecipients: recipients 
    
         self assertAllAddressesAreValid: recipients.
         self assertThereAreNoDuplicates: recipients.        
        ^self new initializeForRecipients: recipients 
    
    それはよりよい!
    最後のテスト!十分なシナリオ.
    この小さな部分では、必要がありません.教育目的のために1つの冗長な方法を追加できます.
    test07SimpleScenarios
    
        self assert: (EmailMessage forRecipients: (Array with: '[email protected]')) plain =     'to: [email protected]'
    
    そしてそれです.
    我々は、TDDと自信を持って構築されたモデルがあります.フルカバレッジとゴールドメッキ!
  • 空のコンストラクタなし

  • モデルは、不正な
  • です
  • ノーセッター
  • ノーゲッター
  • のない偶然のIFS

  • ノーヌル


  • 結論


    これらのヒントを使用すると、非常に基本的なテストを書くことができます.
    それはTDDに十分でしょう.
    TDDは品質保証プロセスを交換しません、そして、QAエンジニアは互いから学ぶために開発者と一緒に働きます.
    ソフトウェアの開発は、人間と共同作業です.
    一緒に楽しみましょう!

    クレジット


    Yohann LIBOTUnsplashによる写真