賢治(143)138138件のシェア(ちょっぴり話題の記事)この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。はじめにおばんです、シリーズとして続けられるかもわからないのに、タイトルに「その1」とかつけてしまいがちな田中です。今回の記事は、TDDを書きながら学習していくための内容になっています。対象読者は以下の通りです。「TDDってなんか難しそう...」とか、「テスト最初に書くんでしょ?」などなど思ってるそこのあなたに向けて、判断する前にとりあえず書いてみようよ!という想いから書いています。(あとは布教とか、自分がマサカリを受けて成長するために)このシリーズで紹介するコードはGitHubに公開しているので、参考にしてみてください。扱う問題に関わることを記載します。要件と仕様の確認は大事なので。トランプ課題の大項目はポーカーですが、まずはトランプの定義から見ていきましょう。(※文章は先述した問題が記載されているサイトを引用しています。)トランプは、日本ではカードを使用した室内用の玩具を指すために用いられている用語で、もっぱら4種各13枚の計52枚(+α)を1セットとするタイプのものを指して言うことが多い。"J♥"実装したいことをTODOリストに書き下す問題はよく読めたでしょうか?それでは次に進みます。今回の問題で重要な部分は以下の三文です。取得してくださいこれをTODOリストに書き起こすと以下のようになります。Cardのインスタンスから文字列表記(notation)を取得するTDDを行う際にはこのTODOリストを作ることも大切な手法の一つだと、私は考えています。TODOリストを書くことで、やるべきことを忘れずに目の前のことに集中でき、その仕事が終わったかどうかを確認することができます。プログラマは往々にして様々な気がかりを抱え込みがちです。今まさにソースコードを書き進めている間でも「ここはこうしたほうが良かったな...」とか、「今取り掛かっている部分と少し違う部分にバグを発見してしまった」なんてことがよくあります。そんなときはTODOリストを活用しましょう。TODOリストに懸念点を書きこんでおくことで、見つけてしまった問題を一旦忘れて、今解決しようとしている問題に集中することができます。プログラミングにまつわる不安や恐怖をどうコントロールするかということもTDDの関心事の一つです。TODOリストを活用することは、目先のものごとを整理し、不安や恐怖に立ち向かうための、フォースの暗黒面に立ち向かうための一つのツールです。issueを利用している方も多いかと思います。「TODOリストってissueでよいのかな?」と思われる方もいるかもしれません。チームや組織によってはその運用も当てはまるかもしれませんが、私はissueとは別にTODOリストを活用しています。私が普段触れるissueはユーザーストーリーを元に作られており、TODOよりももっと大きな粒度であることが多いからです。私の認識ではTODOリストはissueとは別で、それをより小さく噛み砕いたものだと認識しています。レッド、グリーン、リファクタリング次はTDDの最も重要な基本で、奥義でもあるレッド、グリーン、リファクタリングについて解説します。この段階の終了時点ではテストケースが書かれ、失敗している状態。この段階の終了時点では動作する汚い実装を書いている状態。このときはどんな汚い手を使っても、とにかくテストが通る状態を作ることに専念する。この段階の終了時点では実装が綺麗になっている状態。先のグリーンではとにかくテストが通る状態を作ることに専念したため、汚い実装になっているはずです。テスト対象が決まった値を返しているものを一般化したり、重複を除去したり、責務を正しく分散・凝縮させたりします。レッドになるテストを書く。テストを実行し、レッドになることが確認できたらグリーンになるように実装を書き換える、とにかく早く。レッドからグリーンにするステップの踏み方(手順)については後ほど解説します。自動テストを書くとき、グリーンの状態でストップしがちではないでしょうか?TDDではリファクタリングが重要になります。(これはTDDに限った話ではありませんが、)グリーンであることを担保できているのであれば、それはリファクタリングのチャンスです。テストによって動作が保証されているのであれば、どんなに中の実装をいじろうと問題はないはずです。グリーンな状態のテストは新たな実装や、既存部分の書き換えのための足場/補助輪になってくれます。これは先に述べたように、不安や恐怖のコントロールにつながります。長く喋りすぎました、座学はもういいからさっさとコードを書いていきましょう!QuickとNimbleをインストールした状態で、以下のようにPlayingCardsSpec.swiftをテストグループ内に作りましょう。この状態からスタートしていきます。}}これでテストを書いていく用意ができました。TODOリストを振り返ると、以下のような項目がありました。TODOはどこから手をつけてもよいですが、今回は文字列表記の前にそもそものCardの定義とインスタンスが必要であることが明白なので、「Cardを定義して、インスタンスを作成する」から取り掛かりましょう。Cardのインスタンスから文字列表記(notation)を取得すると、その前に気づいたことが二つあります。Initializerとして定義したり、例外を投げるような実装にはしないでしょう。今回のTODO項目に挙げるべきことでもなかったかもしれません。ふたつ目には、仕様の見落としがありました。Cardはそのインスタンスを作成できるだけでなく、SuitとRankを持ちます。TODOリストに「Cardを定義してインスタンスを作成する」の子要素として「CardはSuitを持つ」と「CardはRankを持つ」という項目を追加した方が良さそうです。これで一つ目の気づいたことに挙げた、「TODO項目に挙げるべきことでもなかった」という考えを否定して意味を持たせることができました。Cardのインスタンスから文字列表記(notation)を取得するレッド作業に取り掛かる前にTODOを見直したところで、まずはレッドの状態のテストを作成します。テストケースの定義は、Cardのインスタンスを作成したときに、SuitとRankが意図したものになっているかどうかという観点で作っていきましょう。こんな感じでどうでしょうか。}}一つのテストケースに複数のアサーション(ここではエクスペクテーションですが)を書いてしまう、アサーションルーレットアンチパターンに抵触しています。一つのテストケースに複数のアサーションを書いてしまうと、もしアサーションの評価が失敗だったときにどれが失敗したのかがわかりにくいという問題です。コメントでまとめさせていただきました。アンチパターンなので良くはありませんが、ひとまずは置いておきましょう。置いておこうと判断した理由は、このテストの価値がそんなに高いものではなくて、のちのち無くしてしまうだろうなと考えているからです。上で説明したアサーションルーレットアンチパターンについてですが、XCTAssert系で検査を行う場合は全てのアサーションに対して検査が行われるため、これが問題にならないことがわかりました。これはQuickを用いた場合も同様の挙動であることが確認できました。_)mここでテストを実行してみましょう。以下のエラーが出たら成功です!おめでとうございます!レッドなのにおめでとうも、不思議な感覚かもしれませんね。使用されているちなみに動的型付き言語の場合は変数やクラスが未定義の場合はテスト実行時にそれが判明するため、それがレッドだとわかりやすいかもしれません。今出ているコンパイルエラーはどうでしょうか。そもそもテストが実行できないので、レッドにすらなれない前の段階のような気もしますが、コンパイルエラーもレッドの一種と見て問題ありません。グリーンレッド、グリーン、リファクタリングのレッドの段階をふむことができたので、次は早急にグリーンにしましょう!はい急いで急いで!今出ているエラーはCardが未定義のために出ているエラーでしたので、Cardを作っていきましょう。{}}これでテストが通るはずです。通りましたか?おめでとうございます!あなたの実装とテストが確かなものであることが世界に認められた瞬間です!!!この実装に対して「いやそもそもsuitとrankベタ書きじゃん...」などの疑問を持たれる方もいらっしゃるかもしれませんが、グリーンの段階ではとにかく早くテストを通すことを最優先に考えます。このように期待値通りの値をベタ書きするテクニックを「仮実装」と言います。よくないところは次のリファクタリングの段階で直していきましょう。「そもそも仮実装なんて意味があるのか?最初からinitで変数に代入するコードを書けばいいじゃないか!TDDはやっぱり無駄に小さくステップを踏む必要があって、時間がかかるやり方だったんだ!」お待ちくださいお客様、そうではございません。TDDで大切なのは小さいステップを踏み続けられるようになることです。今回は小さなステップを踏むとどれくらい細かになるかということを紹介するためにあえて丁寧に説明しています。実際日々のコーディングではここまで細かく区切る必要が、必ずしもあるわけではありません。頭の中のコードを実装に落としても構いません。これは、期待通りの値をベタ書きして徐々に変数を書き換えていく仮実装と対比して、「明白な実装」といいます。TDDでは仮実装と明白な実装を使い分けてコードを書いていきます。使い分ける基準は自分がこれから書くコードに対する自信の度合いです。「自信」の反対語として「不安」がありますが、先述したように不安をコントロールすることもTDDの関心事の一つです。仮実装というテクニックがあるのは、不安をコントロールするためです。勇気をもって大きなステップを踏んでみて、もし失敗したら小さなステップに切り替えればいい。適切な使い分けで、不安を乗り越えていきましょう。リファクタリングみなさんお待ちかねのリファクタリングタイムです!もーーー、汚いところが目についてしょうがないと感じていた方は多かったんじゃないでしょうか!僕もその一人です!直していきますよ!!すぐに見てとれる修正点もありますが、その前に一つ気になることがあります。テストケースを追加して検証してみましょう。}}テストを実行してみたら二つのエラーが検出できました。しまった!そういえばさっきCardのsuitとrankは仮実装として、.heartと.jをベタ書きで代入していたことを忘れていた!どこのことを言ってるかというと、ここです。.jsuitとrankを決めうちではなく一般化する必要が出てきました。先に作っておいたinit内でsuitとrankを代入するようにしましょう。}}これでテストを実行すれば、定義した二つのテストがグリーンになるはずです。実装が妥当であることを示すために今回はテストケースを追加しました。ジャックのインスタンスを作成できることしか保証できていませんでした。「Cardを定義して、インスタンスを作成する」というTODO項目を達成させるために、「他のSuitとRankでCardのインスタンスを作成しても、インスタンスはそのSuitとRankを持つか」という観点が抜けていたことが問題でした。このように複数のテストケースから実装の一般化を促すテクニックを三角測量といいます。三角測量はTDDの範疇を超えて、テストケースに対する観察眼が必要なテクニックだと私は考えます。『テスト駆動開発』の言葉を借りるならば、「どのように設計すればよいかアイデアが浮かばないときに、少し異なる角度から問題について考える機会をあたえてくれる」テクニックです。注意して言っておきたいのは、三角測量は「仮実装していた部分を確認するためのテクニック」ではないということです。お疲れ様ついでにもう一つ思い出したことがありました。Swiftのstructには、定義したプロパティが未初期化だった場合、initを省略できる言語仕様がありました。省略できるものは省略しましょう。Rank}実装の書き換えを行なったら必ずテストを実行するようにしましょう。テストは通りましたか?通った、よかった、私のSwiftの言語仕様の理解に間違いはなかったようです。次のリファクタリングポイントは私の確認ミスだったので素直に謝ります、ごめんなさい。問題文の一文を見てください。kingと命名した方が正しい命名のように思えてきました。oneにおいては誤解があることに気がつきました。threeというのはカードに書かれた数字のことであり、aceが1を意味するかというのは別の問題で、ポーカー/大富豪/七並べなどのゲームのルールがaceをどう解釈するかによって変わりそうです。テストを書き換えていきましょう。}}書き換えが終わったらテストを実行しましょう。以下のエラーが出るはずです。持たないjackとqueenはCard.Rankのメンバーに含まれていないと、コンパイラが真っ赤になってまで怒ってくれました。レッドになることを確認したら実装を書き換えていきましょう。Rank}ここまでのリファクタリングはこんなところではないでしょうか。レッド、リーン、リファクタリングのグリーンの段階よりもずっと良いコードになりました!TODOリストを更新しましょう。Cardのインスタンスから文字列表記(notation)を取得する文字列表記についてはまた次回見ていきます。長くなりましたが、この記事で学んだことを振り返りましょう。この記事で学んだことの振り返り目の前の実装に集中するためにTODOリストを使うことは効果的TDDの関心事の一つに、プログラミングにまつわる不安や恐怖をどうコントロールするかという話があるレッド/グリーン/リファクタリングでTDDの1サイクル。リファクタリングを必ず行なって、動作する綺麗な実装を手に入れる必要があるTODOリストはどこから手をつけても良いTODOリストは都度精査し、足りない項目に気付いたら追加するコンパイルエラーもレッドの一種であるレッドを素早くグリーンに変えるために期待値通りの値をベタ書きするテクニックを「仮実装」という頭の中のコードをすぐ実装に落とし込むことを「明白な実装」というTDDで大切なのは小さなステップを踏み続けられるようになること仮実装と明白な実装は自分がこれから書くコードに対する自信の度合いで使い分ける複数のテストケースから実装の一般化を促すテクニックを「三角測量」というSwiftのstructには、定義したプロパティが未初期化だった場合、initを省略できる言語仕様がある問題文はよく読もうRankが何を意味するかはゲームのルールによって変わりそうだ。Rank}まとめテスト駆動開発について、実際にコードを書きつつ、コードと考えを付き合わせながら紹介してみました。完全に『テスト駆動開発』の第一部に影響されました。世の中にあるTDDについて紹介した記事や文献はSwiftで書かれたものが少ないように思いました。無いわけではありませんが、Javaなどの歴史ある言語ほどは無いと思ったため、この記事を書いてみました。Swiftをすでに習得している人がTDDを始めるときのきっかけになり、同時にTDDがどういったものか感じていただければ幸いです。はじめの一歩は難しいものではない。TDDの難しさは、「どういったテストケースが必要か」、「コンポーネントをどう設計すれば良いテストができるか」などのテクニックや戦術を同時に学ばなければいけないために複雑になるところにあると思っています。TDD自体にも、ステップの歩幅の調節を見極める難しさがあります。一気にうまくできるわけではないので、それこそTDDのコツコツ感と同じで少しずつ学んでいけば良いのだと思っています。2017の19日目の記事として今回の記事を追加させていただきました。1,438,632ダンボールの人。最近はJavaScriptやってます。〜ログ収集、監視、分析を触って体感しよう!〜」を開催しますお申し込み受付は終了しました。ありがとうございました。今後セミナーのお知らせを受け取りたい方は、こちらからご登録をお願いします。CAFEのサービスが「LINEアプリ」として利用できるようになりました。これまではLINEのトークから利用する形でしたが、LINEサービス内から利用できるようになりました。これまでより便利に、シームレスにご利用いただけます。Cafe300件のシェア(そこそこ話題の記事)インフラ未経験の私が内定から入社までに読んだ技術書11冊ブログ記事2020年01月16日Yui300インフラ未経験で入社した私がインフラを勉強するために読んだ技術書11冊を感想とともにまとめました。平野重利123Pythonで、標準入力を変換して標準出力に出すCLIプログラムのテンプレートをご紹介します。菊池修治47こんにちは、菊池です。勉強会#1に登壇しました。サーバのみならずネットワーク機器の仮想化も年々進んでいます。スペックに縛られないこととか、展開のしやすさとか初期考慮点が少なくなるのは嬉しいです。武田隆志1098このエントリは、2018年、2019年に公開したAWS全サービスまとめの2020年版です。これまではいくつかに分割して公開していましたが、1エントリにまとめてほしいという要望をもらっていたため、今年は1エントリに集約してみました。CAFEのサービスが「LINEアプリ」として利用できるようになりました。これまではLINEのトークから利用する形でしたが、LINEサービス内から利用できるようになりました。これまでより便利に、シームレスにご利用いただけます。Cafe300件のシェア(そこそこ話題の記事)インフラ未経験の私が内定から入社までに読んだ技術書11冊ブログ記事2020年01月16日Yui300インフラ未経験で入社した私がインフラを勉強するために読んだ技術書11冊を感想とともにまとめました。悠紀235ShifterはWordPress環境をサーバーレスで立ち上げ、静的なサイトを生成することができるサービスです。FAQサイトをサクッと作ってみました。Takumi227こんにちは。DA事業本部の春田です。クラスメソッド株式会社が運営するAWS・iOS・HTML5に関する技術情報サイトです。