Henrik Knibergの蚘事「ATDD from Trenches」の翻蚳ATDD with Advanced

オリゞナル www.infoq.com/articles/atdd-from-the-trenches



高床なATDD



初心者向けの受け入れテストによる開発


画像



この状況にあったこずがある堎合



次に、この蚘事は、レガシヌコヌドを䜿甚した既存のプロゞェクトで受け入れテスト受け入れテスト駆動型開発を介しお開発を開始する方法の具䜓䟋です。 それは技術的負債の問題を解決する 1぀の方法を説明したす。

これは実際のプロゞェクトの䟋であり、すべおの欠陥ず欠点がありたすが、本の掗緎された挔習ではありたせん。 それで、ベレヌ垜を着甚しおください。 掟手なサヌドパヌティラむブラリ通垞は悪甚されるこずなくなしで、JavaずJUnitを䜿甚したす。

譊告これが唯䞀の正しい方法であるず䞻匵しおいるのではなく、他にも倚くのATDD「スタむル」がありたす。 たた、この蚘事では、新しく革新的で実瞟のあるアプロヌチや経隓に぀いおはあたり觊れおおらず、ここでは盎接説明したす。



やりたかったこず


数日前、 webwhiteboard.comのパスワヌド保護を開始したした 私のプロゞェクトは趣味です。 ナヌザヌは長い間、仮想ホワむトボヌドをパスワヌドで保護する機胜を远加するこずを求めおきたので、今こそそれを行うずきです。

蚀葉では簡単に聞こえたすが、実際には、蚭蚈にかなりの数の倉曎を加える必芁がありたす。 これたで、webwhiteboards.comはナヌザヌ名やパスワヌドなしで匿名ナヌザヌによっお䜿甚されおいるず想定されおきたした。 ボヌドをパスワヌドで保護できるのは誰ですか 誰が圌女にアクセスできたすか パスワヌドを忘れたらどうなりたすか シンプルでありながら、かなり信頌できる方法でこれを実装する方法は

webwhiteboardコヌドは、単䜓テストず統合テストで十分にカバヌされおいたす。

ただし、受け入れテスト、぀たり゚ンドナヌザヌの芳点からすべおのレむダヌを通過するテストは完党に存圚したせん。



デザむンを怜蚎する


webwhiteboardの蚭蚈の䞻な目暙はシンプルです。パスワヌドを入力する必芁性を最小限に抑え、アカりントを䜜成するのではなく、他の刺激物を枛らすこずです。 そこで、パスワヌドで保護されたボヌドに2぀の制限を蚭定したした。





実装アプロヌチ


倚くの䞍確実性がありたす。 実装方法は蚀うたでもなく、これがどのように機胜するかは知りたせんでした。 ここに私がやろうず決めたものがありたすATDD自䜓



これらの手順は䜕床も繰り返されたす。 各ステップで、前のステップに戻る必芁がありたすこれはかなり頻繁に行いたした。



ステップ1提案されたプロセスを文曞化する


機胜が準備ができおいるず想像しおください。 たるで倩䜿が倩から降りおきお、私が寝おいる間にあらゆるこずをしたかのように。 本圓であるには䜙りにも良い音 䜜業が既に行われたこずを確認するにはどうすればよいですか 最初に確認するシナリオはどれですか これを入手したしょう

  1. 新しいボヌドを䜜成しおいたす
  2. パスワヌドを蚭定したす
  3. ゞョヌがボヌドを開こうずしおいたす。システムはパスワヌドを芁求したす
  4. ゞョヌが間違ったパスワヌドを入力し、アクセスが拒吊されたした
  5. ゞョヌは再詊行し、正しいパスワヌドを入力しおアクセスしたす。 「ゞョヌ」は私だけであり、別のブラりザからのものであるこずを理解する必芁がありたす。


この短いテストスクリプトを曞いた埌、考慮する必芁がある代替シナリオが他にもたくさんあるこずに気付きたした。 しかし、これが䞻なシナリオであり、機胜させるこずができれば、倧きな䞀歩を螏み出すこずになりたす。



ステップ2起動受け入れテストに倉換する


それほど単玔ではありたせん。 他の受け入れテストはありたせんので、どこから始めたすか 新しい機胜は、認蚌を担圓する倖郚コンポヌネントず察話したす最初はJanrainを䜿甚するこずにしたした。 たた、デヌタベヌスず、ポップアップダむアログ、トヌクン、ペヌゞトランゞションなどを含む耇雑なWebスタッフが倚数存圚したす。 うわ

埌戻りする時です。 「受け入れテストの曞き方」の問題を解決する前に、「既存のコヌドで受け入れテストを曞く方法」のより単玔な問題を解決する必芁がありたすか

この質問に答えるために、最初にシステムに既に存圚するシナリオの「最も単玔なシナリオ」のテストを䜜成したす。



ステップ2.1最も簡単な自動受け入れテストを䜜成する


私が始めたスクリプトは次のずおりです。

  1. 存圚しないボヌドを開いおみおください
  2. 圌女が芋えないこずを確認しおください


そのようなテストを曞く方法は どのフレヌムワヌクで どんなツヌル ナヌザヌむンタヌフェむスを䜿甚しおテストする必芁がありたすか テストにクラむアントコヌドを含めるか、サヌビスを盎接呌び出す必芁がありたすか

たくさんの質問。 トリックそれらに答えないでください すべおがすでに魔法のように行われおいるこずをふりをしお、擬䌌コヌドのテストを曞くだけです。 䟋

public class AcceptanceTest { @Test public void openWhiteboardThatDoesntExist() { //1.     //2. ,       } }
      
      





私はそれを起動し、合栌したした やった ええず、でも埅っおください、これは間違っおいたす TDD䞉角圢の最初のステップ「赀-緑-リファクタリング」は赀です。 そのため、この芁件がただ実装されおいないこずを蚌明するために、たずテストをフォヌルさせる必芁がありたす。



おそらく、実際のコヌドを曞くこずから始めたしょう。 それでも、擬䌌コヌドは正しい方向ぞの䞀歩を螏み出すのに圹立ちたした。



ステップ2.2最も簡単な自動受け入れテストを赀にする


これを行うために、AcceptanceTestClientクラスを思い付き、すべおの問題を魔法のように解決し、受け入れテストを実行するための優れた高レベルのむンタヌフェむスを提䟛するふりをしたした。 䜿い方は次のずおりです。

client.openWhiteboard "xyz";

assertFalseclient.hasWhiteboard;

このコヌドを曞いたら、テストスクリプトに最適なむンタヌフェむスを実際に思い぀きたした。 テストには、擬䌌コヌドにあったのずほが同じ数のコヌド行が必芁です。

次に、Eclipseホットキヌを䜿甚しお、空のAcceptanceTestClientクラスず必芁なメ゜ッドを自動的に生成したした。

 public class AcceptanceTestClient { public void openWhiteboard(String string) { // TODO Auto-generated method stub } public boolean hasWhiteboard() { // TODO Auto-generated method stub return false; } }
      
      





テストクラスは次のようになりたす。

 public class AcceptanceTest { AcceptanceTestClient client; @Test public void openWhiteboardThatDoesntExist() { //1.     client.openWhiteboard("xyz"); //2. ,       assertFalse(client.hasWhiteboard()); } }
      
      





テストは開始されたすが、クラッシュしたすクラむアントがnullであるため。 いいね

私は䜕を達成したしたか あたり蚀わないでください。 しかし、これは始たりです。 これで、受け入れテストのヘルパヌクラスの胚芜-AcceptanceTestClientができたした。



ステップ2.3 最も簡単な自動受け入れテストをグリヌンにする


次のステップは、受け入れテストを緑にするこずです。



今、私ははるかに簡単な問題を解決する必芁がありたす。 認蚌に぀いおも、耇数のナヌザヌに぀いおも、そのようなこずに぀いおも気にする必芁はありたせん。 これらのシナリオのテストは埌で远加できたす。

AcceptanceTestClientに関しおは、その実装はかなり暙準的でした-停のモックデヌタベヌスこのためのコヌドは既にありたしたずメモリ内のwebwhiteboardシステム党䜓のバヌゞョンを起動したす。

これはセットアップがどのように芋えるかです



画像をクリックするず拡倧したす

技術的詳现Web WhiteboardはGWTGoogle Web Toolkitを䜿甚したす。 すべおがJavaで蚘述されおいたすが、GWTはクラむアントコヌドを自動的にjavascriptに倉換し、RPCリモヌトプロシヌゞャコヌル呌び出しを魔法のように挿入しお、非同期クラむアントサヌバヌ盞互䜜甚の実装の䜎レベルの詳现をすべお隠したす。

受け入れテストを開始する前に、システムを盎接「閉じ」お、すべおのフレヌムワヌク、倖郚コンポヌネント、およびネットワヌク盞互䜜甚を切り取りたす。



画像をクリックするず拡倧したす

そこで、実際のクラむアントコヌドず同じようにwebwhiteboardサヌビスず通信するAcceptanceTestClientを䜜成したす。 違いはカヌテンの埌ろに隠れおいたす。



たた、AcceptanceTestClientの構成は、実際のmongoデヌタベヌスクラりドNoSQLデヌタベヌスをRAMにデヌタを保存する停物に眮き換えたす。

すべおの䟝存関係をスプヌフィングする䞻な理由は、環境を簡玠化し、テストを高速化し、テストがすべおのコンポヌネントおよびネットワヌク接続から独立しおビゞネスロゞックをカバヌするこずを確認するためです。

この蚭定はすべお耇雑すぎるように思えるかもしれたせんが、実際には、たった3行のコヌドで構成される1぀のinitメ゜ッドにすぎたせん。

 public class AcceptanceTest { AcceptanceTestClient client; @Before public void initClient() { WhiteboardStorage fakeStorage = new FakeWhiteboardStorage(); WhiteboardService service = new WhiteboardServiceImpl(fakeStorage); client = new AcceptanceTestClient(service); } @Test public void openWhiteboardThatDoesntExist() { client.openWhiteboard("xyz"); assertFalse(client.hasWhiteboard()); } }
      
      





WhiteboardServiceImplは、webwhiteboardサヌビスの真の実装です。

AcceptanceTestClientコンストラクタヌがWhiteboardServiceのむンスタンス䟝存性泚入蚭蚈パタヌンを受け入れるようになりたした。 これにより、远加の副次効果が埗られたす。぀たり、構成を気にしたせん。 同じAcceptanceTestClientクラスを䜿甚しお、実際のベヌスで構成されたWhiteboardServiceのむンスタンスを枡すだけで、実際のシステムをテストできたす。

 public class AcceptanceTestClient { private final WhiteboardService service; private WhiteboardEnvelope envelope; public AcceptanceTestClient(WhiteboardService service) { this.service = service; } public void openWhiteboard(String whiteboardId) { boolean createIfMissing = false; this.envelope = service.getWhiteboard(whiteboardId, createIfMissing); } public boolean hasWhiteboard() { return envelope != null; } }
      
      





芁玄するず、AcceptanceTestClientは実際のwebwhiteboard Webクラむアントのように動䜜するず同時に、受け入れテスト甚の高レベルのむンタヌフェむスを提䟛したす。

「盎接呌び出すこずができるWhiteboardServiceが既にあるのに、なぜAcceptanceTestClientが必芁なのか」ず尋ねるこずができたす。 これには2぀の理由がありたす。



この蚘事はwebwhiteboardデバむスに関するものではないため、AcceptanceTestClient実装の詳现に぀いおはもう説明したせん。 AcceptanceTestClientは、受け入れテストのニヌズず、サヌビスむンタヌフェむスずの察話の実装の䜎レベルの詳现を結び付けおいるず蚀えば十分です。 実際のクラむアントコヌドは、サヌビスずの察話方法のヒントずなるため、簡単に蚘述できたした。

いずれにせよ、今では最も簡単な受け入れテストに合栌しおいたす

 @Test public void openWhiteboardThatDoesntExist() { myClient.openWhiteboard("xyz"); assertFalse(myClient.hasWhiteboard()); }
      
      





次のステップは少し敎理するこずです。



実際、私はただこのコヌドが1行も曞かれおいたせんこの機胜は既に存圚し、機胜しおいるため。これはテストフレヌムワヌクのコヌドに過ぎたせん。 それにもかかわらず、私はそれをクリヌンアップし、重耇を取り陀き、メ゜ッドによりわかりやすい名前を付けるなど、数分を費やしたした。

最埌に、完党性のために、たた簡単だったので、別のテストを远加したしたo

 @Test public void createNewWhiteboard() { client.createNewWhiteboard(); assertTrue(client.hasWhiteboard()); }
      
      





ほら、テストフレヌムワヌクがありたす そしお、ファッショナブルなサヌドパヌティラむブラリはありたせん。 JavaずJunitのみ。



ステップ2.4パスワヌド保護の受け入れテストを曞く


次に、パスワヌドテストを远加したす。

擬䌌コヌドを䜿甚しお、テストの「仕様」を説明するこずから始めたす。

 @Test public void passwordProtect() { //1.     //2.     //3.     ,     //4.          //5.   ,       }
      
      







そしお今、以前ず同様に、AcceptanceTestClientクラスに必芁なものがすべお揃っおいるふりをしお、テストコヌドを曞いおいたす。 この手法は非垞に䟿利です。

 @Test public void passwordProtect() { //1.     myClient.createNewWhiteboard(); String whiteboardId = myClient.getCurrentWhiteboardId(); //2.      myClient.protectWhiteboard("bigsecret"); //3.     ,     try { joesClient.openWhiteboard(whiteboardId); fail("Expected WhiteboardProtectedException"); } catch (WhiteboardProtectedException err) { //  } assertFalse(joesClient.hasWhiteboard()); //4.          try { joesClient.openProtectedWhiteboard(whiteboardId, "wildguess"); fail("Expected WhiteboardProtectedException"); } catch (WhiteboardProtectedException err) { //  } assertFalse(joesClient.hasWhiteboard()); //5.   ,       joesClient.openProtectedWhiteboard(whiteboardId, "bigsecret"); assertTrue(joesClient.hasWhiteboard()); }
      
      





このコヌドを曞くのにほんの数分を費やしたした。曞いたずきに必芁なものを思い぀いたからです。 これらのメ゜ッドは、AcceptanceTestClientクラスにはほずんどありたせんただ。

コヌドを曞いおいる間、私はすでにいく぀かの決定をしなければなりたせんでした。 考えすぎる必芁はありたせん。最初に思い぀いたこずを実行するだけです。 最高のものは善の敵であり、今私が望むのは、十分に良い結果、぀たり、実行できお萜ちるテストを取埗するこずです。 その埌、テストが緑色になったら、コヌドをリファクタリングし、その蚭蚈を改善する方法に぀いおより慎重に考えたす。

特にこれらのひどいtry / catchステヌトメントをリファクタリングするために、すぐにコヌドを組み合わせ始めたいずいう誘惑がありたす。 しかし、TDDの法則の1぀は、リファクタリングを開始する前にテストをグリヌンにするこずです。リファクタリングするず、テストによっお保護されたす。 そこで、コヌドのコヌミングを延期するこずにしたした。



ステップ3-受け入れテストを実行しおフォヌルする


テストの䞉角圢に続いお、次のステップはテストを開始しお倱敗させるこずです。



空のメ゜ッドを䜜成するために、Eclipseホットキヌを再床䜿甚したす。 玠晎らしい。 テストを実行しお、出来䞊がり、赀だ



ステップ4受け入れテストをグリヌンにする


次に、補品コヌドを䜜成する必芁がありたす。 システムにいく぀かの新しい゚ンティティを远加しおいたす。 远加したコヌドは非垞に重芁な堎合があるため、単䜓テストでカバヌする必芁がありたした。 TDDでこれを行いたした。 これはATDDず同じですが、小芏暡です。

これがATDDずTDDの連携方法です。 ATDDを倖偎のルヌプず考えおください。



新しい機胜のレベルで受け入れテストを蚘述する各サむクルに察しお、クラスおよびメ゜ッドのレベルでナニットテストを蚘述するいく぀かのサむクルを行いたす。



そのため、高いレベルでは受け入れテストをグリヌン数時間かかる堎合がありたすにするこずに集䞭しおいたすが、䜎いレベルでは、たずえば次のナニットテストであるレッドこれは通垞、数分かかりたす。

筋金入りの「革匵りTDD」ではありたせん。 「少なくずも、単䜓テストず補品コヌドが䞀緒にチェックされおいるこずを確認しおください」に䌌おいたす。 そしお、そのようなチェックは1時間に数回行われたす。 「TDDスタむル」ず呌ぶこずができたすo。



ステップ5コヌドをクリヌンアップする


通垞、受け入れテストが緑色になったら、クリヌニングを実行したす。 これを決しお節玄しないでください 食埌に皿を掗う方法に぀いおです-すぐにそれをするのが最善です。



私は補品コヌドだけでなく、テストコヌドもクリヌニングしおいたす。 たずえば、汚いtry-catchをヘルパヌメ゜ッドずしお匷調衚瀺し、クリヌンできれいなテストメ゜ッドを取埗したした。

 @Test public void passwordProtect() { myClient.createNewWhiteboard(); String whiteboardId = myClient.getCurrentWhiteboardId(); myClient.protectWhiteboard("bigsecret"); assertCantOpenWhiteboard(joesClient, whiteboardId); assertCantOpenWhiteboard(joesClient, whiteboardId, "wildguess"); joesClient.openProtectedWhiteboard(whiteboardId, "bigsecret"); assertTrue(joesClient.hasWhiteboard()); }
      
      





私の目暙は、受け入れテストを短く、簡朔で読みやすくしお、コメントが冗長になるようにするこずです。 最初の擬䌌コヌドずコメントはテンプレヌトずしおのみ機胜したす-「これは、コヌドがどれほどきれいであるかです」 コメントを削陀するず勝利感が埗られ、ボヌナスずしおこの方法はさらに短くなりたす



次は


繰り返したす。 最初の動䜜テストを取埗するずすぐに、ただ足りないものに぀いお考えたした。 たずえば、冒頭で、ログむンしたナヌザヌのみがパスワヌドでボヌドを保護できるず蚀いたした。 そこで、これにテストを远加し、赀、緑、そしおコヌドをきれいにしたした。 などなど。

以䞋は、この機胜のために行ったテストの完党なリストです今のずころ



バグを芋぀けたり、新しい䜿甚シナリオを思い぀いた堎合は、埌でいく぀かのテストを远加したす。

党䜓ずしお、コヌディングには玄2日かかりたした。 ほずんどの堎合、以前に䜜成したコヌドずデザむンに戻るために費やしたしたが、この蚘事を読んでいるずきのように盎線的ではありたせんでした。



手動テストはどうですか


もちろん、グリヌン受け入れテストを受け取った埌、倚くの手動テストを行いたした。 しかし、自動受け入れテストは基本的な機胜ず倚くの特殊なケヌスの䞡方をカバヌしおいるため、より䞻芳的で研究的なテストに集䞭できたす。 党䜓的なナヌザヌ゚クスペリ゚ンスはどうですか この䞀連のアクションには意味がありたすか わかりやすいですか 説明テキストを远加する方が良いでしょうか 矎的な芳点からデザむンは良いですか デザむン賞を受賞する぀もりはありたせんが、蚘念碑的ないものも欲しくありたせん。

匷力な䞀連の自動受け入れテストにより、退屈な単調な手動テスト「サルテスト」が排陀され、より興味深く有意矩なタむプの手動テストのための時間が解攟されたす。

理想的には、最初から自動受け入れテストを開始する必芁があるため、ある皋床技術的な負債を返枈したした。



キヌポむント


この䟋がお圹に立おば幞いです 圌はかなり兞型的な状況を瀺しおいたす-「新しい機胜を远加したいので、自動受け入れテストを䜜成するのはいいこずですが、プロゞェクトにはただ受け入れテストがありたせん。どのフレヌムワヌクを䜿甚し、どこから始めるべきかわかりたせん」。

私はこのテンプレヌトが倧奜きで、䜕床も地面から降りるこずができたした。 芁玄するず

  1. 本圓に䟿利なヘルパヌクラス私の堎合はAcceptanceTestClientにカプセル化された優れたフレヌムワヌクを既に持っおいるふりをしたす。
  2. 珟圚すでに動䜜しおいるものたずえば、単にアプリケヌションを開くなどに぀いお、非垞に簡単な受け入れテストを䜜成したす。 このテストを䜿甚しお、AcceptanceTestClientのようなクラスず、関連するテストバむンディング実際のデヌタベヌスや他の倖郚サヌビスのなりすたしなどを蚘述したす。
  3. 新しい機胜の受け入れテストを䜜成したす。 実行したすが、クラッシュしたす。
  4. テストを緑色にしたす。 コヌドを曞くずきは、倚少耇雑なコヌドの単䜓テストを曞いおください。
  5. リファクタリング。 そしお、メトリックを改善するために、さらにいく぀かの単䜓テストを䜜成するか、その逆の堎合-䞍芁なテストたたはコヌドを削陀したす。 コヌドを猫の卵ず同じくらいきれいにしおください


これを行うず、最も困難な障壁を克服できたす。 ATDDの䜿甚を開始したした



著者に぀いお




Henrik Knibergはストックホルムのクリスプのアゞャむル/リヌンコンサルタントで、䞻にSpotifyで働いおいたす。 圌は、人気の著曞「 Scrum and XP from the Trenches 」、「 Kanban and Scrum、䞡方を最倧限に掻甚する 」で説明されおいるように、゜フトりェア開発の技術的偎面ず人間的偎面の䞡方で䌁業の成功を支揎しおいたす。そしお「 溝からの傟き 」。



アレキサンダヌ・アンドロノフ@ alex4Zero、アントン・ベノズィク@bevzuk、ドミトリヌ・パブロフによる翻蚳

スマヌトステップグルヌプ 。



All Articles