engineers_blog11月4日に入社しましたエンジニアの越川です。本日は、私がコードを書く際に気をつけていることを書こうと思ったのですが、どう書くかに迷った末、ブログ記事駆動ハッカソンを行うことでそのプロセスで考えいたことなどを記事にすることにしました。私はコードを書く際におもてなしの心が大事だと思っています。おもてなしの心は最終的なアウトプットに触れるユーザーはもちろんのこと、チームメンバー、未来の自身へ向けた思いやりです。今回題材とするのは、KPTツールです。KPTは、日々の活動を振り返り「Keep」すべきこと「Problem」であること「Try」したいことを上げて、活動を振り返るために使われます。先日行われた「オレたちが目指す”最強のエンジニアドリブン”」を終えた後に振り返りでKPT使ったので、それをWebアプリにしてみます。今回のコードはすべて、ppworks/furikaeri/tree/v1.0.2に置いてあります。Try)から選択してissueを登録できるユーザーは登録したissueを削除できる最低限必要な機能はここまで。今回は、rspecでテストを書きます。featureテストにはcapybaraを使ってみましょう。以下のように最低限必要なgemを用意します。'capybara'endrspec/rspec-railsにあるように、rspecの設定ファイルをインストールします。rspec:installspec/spec_helper.rbとspec/rails_helper.rbが生成されるので、不要な箇所を消すとこんな感じになります。testを書く際に便利となる、amatsuda/database_rewinderを使い、データベースを綺麗にする設定を足します。endFactoryGirlを便利に使う設定を足すthoughtbot/factory_girlでダミーデータを用意します。テストの中で、FactoryGirl.createと書かずに、createと書けるようになり便利です。failures全てはここからです。最初のテストを書くまだ何もないので、トップページを作りましょう。トップページに「ふりかえり」と表示されることを確認します。なんてことないcontrollerとview、それとroutesを設定しましょう。'pages#top'endテストは以下のように書いてみました。featureでテストしたい機能を明記しますscenarioでどんな手続で何をexpect期待するのかを書くと分かりやすいと思います。このケースでは、/にアクセスすると、ふりかえりという文字列が表示されることを確認してます。failures無事通りました。開発の流れ準備はここまで、開発に移りましょう。Projectを作るProjectsControllerを作るIssueを作るIssuesControllerを作るという流れで作ってみます。falseオプションを追加したり、add_indexでインデックスを貼っておきます。endendテストはこんな感じ。endend単体テストでは、subject(対象)を意識して書くと分かりやすいです。何を対象に何をテストしたいのかを明確にします。ことを大切にしましょう。failuresいいですね。ここで今回、Project#keyは、ユニークであることが大事なので、その検証をしておきたいと思いました。end「ある振る舞いの結果、何かを期待する」場合には以下の様な記述が読みやすいかなーと思っております。:fugo).from(:piyo).to(:puni)end同じように、ある振る舞いの結果、あるエラーが発生するというテストは以下のようにかけるので、今回はエラがー起きないことをnot_toを使い記述しました。raise_error(RuntimeError)endテストにおけるnotは「ある事柄ではない」すべてがマッチするケースが通ってしまうので、慎重に使う必要があります。今回のケースでは例外が発生しないことだけを見ておきたいのであえて使いました。と良いかもしれません。failure見事にエラーが起きますね、なんせkeyの生成処理を書いていませんからね。このエラー、ちょっと気になるエラーだなと思いました。railsのレイヤーではなくdbのレイヤーにまで到達しのエラーとなっているので、もうちょい手前でチェックしたいですね。validationを追加します。trueendそうするとエラー内容が変わります。(required)>'railsのレイヤーで守ってくれている感が出ました。二重で守ることに関しては賛否両論があるかと思いますが、validationを書くことによるメリットとしてはrailsの分かりやすいメッセージを表示できるという点にあると思います。validatesに失敗すると、project.errorsの中身にエラーのメッセージが保存されるので、それをユーザーに表示する選択肢が生まれますね。end+end今回は、rubyの標準ライブラリを使いました。SecureRandom.hexでランダムな文字列を作ってくれます。failures久々のオールグリーン。作る地味な工夫としては、インスタンスの生成処理はなるべくbefore_actionにまとめて、アクションで行う処理にフォーカス出来るようにしています。endendviewはform処理はpartialを分けるという癖をつけておくと、新規と更新のformを共通化出来て便利です。デザインの都合上分かれるということもありうるので、そこは後でリファクタリングでオッケーでしょう。@project.nameroutesのポイントは、paramです。今回、projectのURLを/projects/xxxxxxxxという感じにしたいのでrailsのidを使いたくないのでresourcesが生成するルートにもkeyを使いたいのです。projects#show普段、:idとなるところが:keyになっていますよね。これで、contollerにて、実際は:idじゃないけどparams[:id]で受け取るみたいなつらいことが避けられます。モデルで#to_paramを定義しておくとURLヘルパーでもわざわざkeyを渡さないで済みます(いつもどおりproject_path(@project)みたいに書ける)。定義しておきましょう。endendテストはこんな感じで、featureテストなのでscenarioにて手続きを明記します。ポイントは、withinで見るDOMの範囲を絞ることでテストの範囲を明確にするところです。それと、変わりがちな文言よりもcssのclassなどでfindしている点です。この辺はデザイナーさんやコーダーさんとの連携が非常に重要となる点ですね。endendさて、テストを実行。model〜は端折ります。tryを示す事がポイントです。した処理はbrainspec/enumerizeを使うと便利です。endendダミーデータは、FactoryGirlのtraitを使うと、「ここではこういう条件のデータを使いたい」「こっちでは、こんな」というのが楽に扱えます。:keep)と使う感じです。endendテストはこんな。:backで戻るという点。endendviewはpartialだけの構成でprojectsから呼ぶイメージです。issuesのpartialsがどこにあるか?を探す際にviews/issuesから探すのは自然の流れです。いう気持ちを妨げないようにしたいです。:try)issuesはprojectに紐づくのでリソースをnestedに表します。endendテストの結果はこんな。failuresもっとテストしたいIssuesControllerのテストが足りないですね。keepしかカバーしていないので、他も書きます。endendproblemまで書いて気づきます。これはもしや更にコピペする予感。いうルールで進むのがお勧めです。3度目がくるぞ、という予感でDRYを意識しましょう。ここは、shared_examples_forでまとめると綺麗になります。endend今回はこのテストだけでの利用だったので同じファイル内に書きましたが、他のテストでも使う場合はspec/support配下に置くとよいですね。failures残りのテスト削除処理を忘れていました。shared_examples_forでスッキリと。endさて、それなりに機能が出揃いました。/xxxxxにしたいトップページにdemoプロジェクトを表示したいといった点を改善したいと思いました。その辺りは、ppworks/furikaeriにあげてあります。画面は?ここまでひと通りの実装をする際にウェブブラウザで確認することはありませんでした。コアな機能を実装する際にこのように最低限のテストを書きながら進めると、その後のUIの検討や機能調整の際にコアの部分を壊さないように勧めることが出来るようになります。sして頂くとよろしいかと思います。Buttonであなたのheroku環境へdeploy可能です。buttonからdeployされるコードは随時バージョンアップしていくかもしれないので、今回の記事時点でのコードは、ppworks/furikaeri/tree/v1.0.2のコードを御覧ください:)これは最低限の機能しか無いですし、画面のデザインもまだです。buttonを設定すると熱いですね。requestももちろん受付中です。