Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ちょうどよい Rails E2E テスト/enough-good-rails-e2e-test

ちょうどよい Rails E2E テスト/enough-good-rails-e2e-test

Rails には system test (spec) と呼ばれる、Capybara を使った自動ブラウザテストの仕組みが備わっています。これはとても便利で強力なテストではありますが、けして万能ではありません。実行時間が長くなりがちですし、テストコート量も多くなりメンテナンスが大変です。

Ruby でのこのレイヤのテストの先駆けであろう Cucumber からの歴史を振り返りながら、「ちょうどよい」活用の度合いを考えたいと思います。

MOROHASHI Kyosuke

February 01, 2020
Tweet

More Decks by MOROHASHI Kyosuke

Other Decks in Programming

Transcript

  1. ͪΐ͏ͲΑ͍

    3BJMT&&ςετ

    #VSJ,BJHJ
    ॾڮګհ!NPSP

    View Slide

  2. ‣ ࣸਅ


    View Slide


  3. Kyosuke MOROHASHI
    @moro

    View Slide

  4. 4
    SMS?
    What's
    SMSってなにをやってる会社なの?

    View Slide


  5. https://twitter.com/sunaot/status/1002392476492038144

    View Slide


  6. 情報インフラを構築することで、⾼齢社会を

    取り巻く⼈びと、⾼齢社会で働く⽅や事業者の⽅、
    ⾼齢者ご⾃⾝やそのご家族などがイキイキと

    ⽣活できる社会の実現を⽬指しています。
    — https://www.bm-sms.co.jp/philosophy/

    View Slide

  7. 7
    &

    View Slide

  8. 吳䒭⠓爡ؒأ
    ٥
    ؒي
    ٥
    ؒأ
    匌❨鿪庥⼒蓎Ⱅ㕦⡝⿼♶⹛欵蓎Ⱅ㕦ةٙ٦
    https://www.bm-sms.co.jp
    ؒٝآص،䱰欽؟؎
    ز
    https://careers.bm-sms.co.jp/engineer/
    join us!

    View Slide

  9. ͪΐ͏ͲΑ͍

    3BJMT&&ςετ

    View Slide

  10. ‣ ͪΐ͏ͲΑ͍&&ςετͱ͸
    ‣ ͪΐ͏ͲΑ͘͢ΔͨΊͷ޻෉
    ‣ $VDVNCFSͷ͜ͱ
    ‣ ·ͱΊ

    View Slide

  11. ͪΐ͏ͲΑ͍&&ςετͱ͸

    View Slide

  12. ࣗಈςετॻ͍ͯ·͔͢

    View Slide

  13. ‣ 3BJMTతϢχοτςετ
    ‣ PS%#ʹ΋ґଘ͠ͳ͍ϩδοΫͷςετ

    ‣ ϦΫΤετςετ
    ‣ γεςϜςετ
    ‣ PS34QFDͷTQFD
    ‣ #%%͸ςετ͔ɺΈ͍ͨͳͷ࿩͸ࠓ೔͸ԣʹ͓͍͓͖ͯ·͢Ͷ
    ςετʹ΋৭Μͳछྨ͕͋Δ

    View Slide

  14. ‣ ࣮૷͢Δલ
    ‣ ࣮૷ͨ͋͠ͱ
    ‣ ͣͬͱલʹ࣮૷͞ΕͨίʔυʹςετΛ଍͍ͯ͠Δ
    ςετΛॻ͘λΠϛϯά

    View Slide

  15. ‣ ։ൃΛυϥΠϒ͍ͨ͠
    ‣ ॻ͍ͨίʔυ͕ಈ͔֬͘ೝ͍ͨ͠
    ‣ 1VMM3FRVFTU࡞Δͷʹඞਢͱ͍͏ϧʔϧͳͷͰ
    ςετΛॻ͘ͱ͖ͷؾ࣋ͪ

    View Slide

  16. ‣ ςετۦಈ։ൃɺͷςετ
    ‣ ۦಈυϥΠϒײ
    ‣ ઌʹ͔͚Ε͹͍͍͚ͲɺͦΕΛڧ͍͍ͨΘ͚Ͱ͸ͳ͍
    ‣ ͦͷͨΊͷͪΐ͏ͲΑ͍ͱ͜ΖΛ୳Δ
    ࠓ೔ͷʮςετͷ໨తʯ

    View Slide

  17. ʮͪΐ͏ͲΑ͍ʯͱ͸ 

    ʮ&&ςετʯͱ͸

    View Slide

  18. ‣ ։ൃΛυϥΠϒ͢Δ
    ‣ ॻ͍ͯͯർΕͳ͍
    ‣ ϓϩμΫτίʔυͷमਖ਼Λअຐ͠ͳ͍
    ͪΐ͏ͲΑ͍

    View Slide

  19. ‣ &OEᶃϒϥ΢β͔Βɺ&OEᶄಡΈॻ͖͞ΕΔ

    σʔλ·ͰΛશ෦ͭͳ࣮͛ͯߦ͢Δςετ
    ‣ ݫີͳΤϯυΛܾΊΔͷ͸೉͍͠ɻ֎෦αʔϏε࿈ܞͱ͔
    ‣ ֤ίϯϙʔωϯτ͕ɺ૊Έ߹Θͤͨͱ͖ʹ

    ͪΌΜͱಈ࡞͢Δ͔Λݕূ͢Δɻ
    ‣ 3BJMTతʹ͸ɺ4ZTUFN\5FTU 4QFD^͕֘౰͢Δɻ
    &&ΤϯυπʔΤϯυςετ

    View Slide

  20. ‣ ૊Έ߹Θͤͯಈ͘͜ͱΛݕূͰ͖Δ
    ‣ +4Ͱͭͬͨ͘6*͔Β+40/ϦΫΤετ͖͚ͨͲɺαʔόଆ3BJMTͷ૝ఆ͍ͯ͠Δ
    ߏ଄ͱҧͬͯͨɺͳͲΛݕग़Ͱ͖Δ
    ‣ ར༻ऀͷ໨ઢͰهड़ɾݕূͰ͖Δ
    ‣ ಺෦ߏ଄ʹґଘ͠ͳ͍
    ‣ ࣮૷͕ແ͍ঢ়ଶͰ΋ςετγφϦΦΛߟ͑ΒΕΔ
    &&ςετͷϝϦοτ

    View Slide

  21. ‣ ίʔυྔ͕ଟ͘ɺϝϯςφϯε͕େม
    ‣ ը໘ͷ%0.Λͪΐͬͱม͑Δͱେྔʹࣦഊ͢Δ
    ‣ ςετίʔυ͕େྔͰϝϯςφϯε͕ͭΒ͍
    ‣ ࣮ߦ͕࣌ؒ௕͘ͳΓ΍͍͢
    ‣ ಛʹ࣮ϒϥ΢βΛಈ͔͢λΠϓ
    &&ςετͷσϝϦοτ

    View Slide

  22. ͪΐ͏ͲΑ͍&&ςετ
    σϝϦοτͷӨڹΛݮΒͭͭ͠ɺ

    ϝϦοτΛڗडͰ͖ΔΑ͏ͳ&&ςετ

    View Slide

  23. ͪΐ͏ͲΑ͘͢ΔͨΊͷ޻෉

    View Slide

  24. ‣ ը໘ͷ%0.Λͪΐͬͱม͑Δͱେྔʹࣦഊ͢Δ
    ‣ ςετίʔυ͕େྔͰϝϯςφϯε͕ͭΒ͍
    bͪΐ͏ͲΑ͞`ΛݮͣΔσϝϦοτͨͪ

    View Slide

  25. ‣ 3BJMTʹ͸γεςϜςετͷ࢓૊Έ͕͋Δɻ
    ‣ 34QFDͰ΋΄΅ಉ͡ɺ4ZTUFN4QFD͕͋Δɻ
    ‣ όοΫΤϯυ͸$BQZCBSB
    ‣ ଞݴޠͰݴ͏1VQQFUFFS ͺ΃ͯ͌͋

    ͳͲʹ͍ۙ
    ‣ 4FMFOJVNΑΓߴϨϕϧ $BQZCBSBͷυϥΠόͱͯ͠4FMFOJVNΛ࢖͑Δ

    ಓ۩Λ஌Ζ͏

    View Slide

  26. ը໘ͷ%0.Λͪΐͬͱ
    ม͑Δͱେྔʹࣦഊ͢Δ

    View Slide

  27. ‣ ͜͏͍͏ͷʹɺσβΠϯ౎߹ͰEJWΛҰݸ଍͚ͩ͢Ͱ
    ΤϥʔʹͳΔɻ
    ঱ঢ়

    css = 'form.post-wrapper > input[name="user[nickname]"]'
    fill_in css, with: 'moro'

    View Slide

  28. ‣ $BQZCBSB͸ɺϥϕϧ΍ϓϨʔεϗϧμจݴ͔Β
    JOQVUΛ୳ͤΔɻ
    ιϦϡʔγϣϯར༻ऀͷ໨ઢʹཱͭ

    fill_in 'ニックネーム', with: 'moro'

    View Slide

  29. ‣ αʔϏεར༻ऀ͕໨ʹ͢Δ΋ͷ͸ϥϕϧ΍

    ϓϨʔεϗϧμจݴͰ͋Δ
    ‣ ໨ʹ͢Δ΋ͷ͕มΘͬͨΒςετ͢Δ߲໨΋มΘΔ
    ‣ ೲಘײ͋Γ·ͤΜ
    ‣ MBCFMͷGPSଐੑ͕͍ͭͯͳ͍ͳͲɺ6*ͷඍόάൃݟͰ͖ͯศར
    ‣ ܦݧ্ɺҙ֎ͱมΘΒͳ͍
    ϥϕϧςΩετมΘͬͨΒࣦഊ͠ͳ͍

    View Slide

  30. ςετίʔυ͕େྔͰɺ

    ϝϯςφϯε͕ͭΒ͍

    View Slide

  31. ‣ ࡉ͔͍ૢ࡞Λεςοϓͣͭهड़͢Δ͜ͱͰ൥ࡶʹͳΔ
    ঱ঢ়

    # ログインが必要なテストケースのたびにコピペされる
    visit signup_or_signin_path
    click_on '登録済みの方はログイン'
    fill_in 'メールアドレス', with: '[email protected]'
    fill_in 'パスワード', with: 'P@ssword00!'

    click_on 'ログイン'

    View Slide

  32. ‣ ߴϨϕϧͳϔϧύʔϝιουΛ༻ҙ͢Δɻ
    ‣ ʮϩάΠϯϑΥʔϜʹ஋ΛೖΕͯαϒϛοτʯ͔ΒʮϩάΠϯ͢Δʯͱ͍͏ؾ࣋ͪ
    ιϦϡʔγϣϯར༻ऀͷ໨ઢʹཱͭ

    def login_as(user)
    visit signup_or_singin_path
    click_on '登録済みの方はログイン'
    fill_in 'メールアドレス', with: user.auth.email
    fill_in 'パスワード', with: COMMON_TEST_PASSWORD

    click_on 'ログイン'
    end

    View Slide

  33. ‣ ·ͣ͸ؾܰʹநग़͠ɺίʔυͷ༷ࢠΛݟͳ͕Β੔ཧ͢Δ
    ‣ ·ͣ͸ɺಉ͡ςετέʔε಺ʹɺҙਤΛࠐΊ໊ͨલΛ͚ͭͯϝιουநग़͢Δɻ
    ‣ ಉ͡ϑΝΠϧͷଞͷςετέʔε͔Β΋࢖͍ͨ͘ͳͬͨΒɺݟ͑Δ

    είʔϓʹҠಈ͢Δɻ
    ‣ ߋʹଞͷϑΝΠϧ͔Β΋ࢀরͨ͘͠ͳͬͨΒɺڞ௨ϔϧύʔஔ͖৔ʹஔ͘ɻ
    ‣ $BQZCBSB"1*·ͱΊΔ͚ͩͰͳ͘ɺந৅Խͷ࿙ΕΛ

    ہॴԽ͢ΔͨΊʹ΋໾ཱͭ
    ͍ͭɺͲ͏΍ͬͯϔϧύʔϝιουʹ͢Δ͔

    View Slide

  34. ‣ ͱ͍͏Πϝʔδ͕͋Δ͕ɺҙ֎ͱͳ͍
    ‣ ݱࡏͷ࢓ࣄ3BJMTΞϓϦͰ΋AHJUHSFQTMFFQA͕݅ͩͬͨ
    ‣ $BQZCBSBͷߴϨϕϧϝιουΛ࢖͏ͱɺΫϦοΫର৅΍

    ݕূ͢ΔςΩετ͕ݱΕΔ·ͰࣗಈͰ଴ͬͯ͘ΕΔ
    ‣ DMJDL@PO΍IBT@DPOUFOUͳͲɺ$BQZCBSB"1*Λ࢖͏
    ‣ ೥ ݪจ೥
    ͷهࣄ͕ͩɺߟ͑ํ͸ࠓͰ΋௨༻͢Δ
    ‣ IUUQTQPTUEDDXSJUFSFMJBCMFBTZODISPOPVTJOUFHSBUJPOUFTUTXJUIDBQZCBSB
    ൪֎+4ඇಉظॲཧͷλΠϛϯάͰࣦഊ͠TMFFQ͢Δͷ͕ۤ௧

    View Slide

  35. ‣ ࣮ߦ͕͔͔࣌ؒΓ͗͢Δ
    ‣ ศར͗ͯ͢όϦσʔγϣϯͳͲ΋ςετ࢝͠Ίɺςετέʔε͕૿͑͗͢Δ
    ‣ ֎෦ϓϩηεͱ ϒϥ΢βͳͲ
    ͷ௨৴͕ൃੜ͢ΔͷͰͲ͏ͯ͠΋஗͍
    ‣ ϞσϧͷϢχοτςετͰͰ͖Δ΍ͭ͸ͦͬͪͰ΍ͬͨ΄͏͕͍͍Ͱ͢Ͷ
    ‣ σʔληοτΞοϓ͕େมʹͳΓ͕ͪɺͱ͔
    ‣ શ෦ͭͳ͛ΔͨΊɺσʔλҰࣜ·Δ͝ͱඞཁʹͳΓ͕ͪ
    ‣ ݸผͷืΔ࿩͸࠙਌ձͰ
    ͦΕҎ֎ʹ΋৭ʑେม͚ͩͲ

    View Slide

  36. &&ςετΛͪΐ͏ͲΑ͘׆༻͢ΔιϦϡʔγϣϯ
    ར༻ऀͷ໨ઢ͔Βݟͨ

    ಈ͖Λهड़͠ɺݕূ͢Δ

    View Slide

  37. $VDVNCFSͷ͜ͱ

    View Slide

  38. ‣ ࣗવݴޠͰ&&ςετΛهड़Ͱ͖ΔςεςΟϯά

    ϑϨʔϜϫʔΫɻ
    ‣ $BQZCBSBͷલ਎ɺ8FCSBUͱ͍͏ϥΠϒϥϦͰ

    ߴϨϕϧͳ)5.-ૢ࡞"1*͕͋ͬͨɻ
    ‣ ࣗવݴޠ͔Β$BQZCBSB8FCSBU"1*ૢ࡞ͷϚοϐϯά͸ɺ

    ࣗ෼Ͱهड़͢Δɻ
    $VDVNCFS

    View Slide


  39. View Slide


  40. #langage: ja
    フィーチャ: ログインしてユーザーを識別できる
    ユーザーとして、
    ログイン機能などで自分の情報を識別したい
    なぜなら、メッセージなどを「自分のもの」として区別したいからだ
    シナリオ: ユーザ登録してログインする
    前提 "新規ユーザー登録"ページを表示している
    もし "ログイン名"に"moro"と入力する
    かつ "Eメール"に"[email protected]"と入力する
    かつ "作成"ボタンをクリックする
    ならば "こんにちはmoroさん"と表示されていること
    Given('"{word}"に"{word}"と入力する') do |field, value|
    fill_in field, with: value
    end

    View Slide


  41. $VDVNCFSͷΑ͏ͳπʔϧ͸ࣗવݴޠ͔Βςετ
    ίʔυ΁ͷղऍͷ૚͕ඞཁʹͳΔͨΊɺؒ઀૚͕ͭ
    ૿͑ͯϝϯςφϯεੑ͕Լ͕Δͱ͍͏Πϝʔδ͕ຮ
    Ԇͨͨ͠Ίɺ$VDVNCFSΛ΍ΊͯY6OJUY4QFDͰ
    ʮड͚ೖΕςετʯΛॻ͘νʔϜ΋૿͑·ͨ͠ɻ
    ςετۦಈ։ൃʮ෇࿥$ʯΑΓ

    View Slide

  42. ‣ εςοϓఆٛΛ࡞ΔͷΛར༻ऀͷ໨ઢʹཱͭ

    ࢹ఺มߋͷ͖͔͚ͬʹͰ͖Δͱྑ͔ͬͨ
    ‣ ͜ͷҰ࿈ͷϑΥʔϜૢ࡞͸ɺͭ·ΓαʔϏεར༻ऀͱͯ͠ԿΛ͍ͯ͠Δͷ͔
    ‣ ॳظ͸ɺ$BQZCBSBϝιουʹରԠ͢Δཻ౓ͷεςοϓఆٛΛࣗಈੜ੒͠ɺ

    ࠞཚΛট͍ͨ ޙʹͳ͘ͳͬͨ

    ‣ Ұา໨Λମݧ͢Δʹ͸͍͍Μ͚ͩͲɻɻɻ
    $VDVNCFSΛࣱΜͰ

    View Slide


  43. #langage: ja
    ...
    シナリオ: 新規登録後につぶやくことができる
    前提 ユーザー"moro"として新規登録する
    もし "内容"に"ブリおいしいです。"と入力する
    ならば "ブリおいしいです。"と表示されていること
    かつ "つぶやき: 1件中1件"と表示されていること
    Given('ユーザー"{word}"として新規登録する') do |username|
    fill_in 'ログイン名', with: username
    fill_in 'Eメール', with: '#{username}@example.test'
    click_on '新規登録'
    end

    View Slide

  44. ‣ ೲ඼υΩϡϝϯτΛࣗಈੜ੒͢ΔπʔϧͰ͸ͳ͘
    ‣ ʮड͚ೖΕςετʯ
    ‣ ͋ͷࠒͷۭؾΈ͍ͨͳͷ͸࠙਌ձͰ
    ‣ ར༻ऀͷࢹ఺ʹཱͬͯ

    αΠτ΍αʔϏε΍ػೳͷ࢖͍ํΛهड़͢Δπʔϧ
    ‣ ͔͠΋ಈ͘
    &&ςετΛࣗಈԽͯ͠Կ͕͔ͨͬͨ͠ͷ͔

    View Slide

  45. ‣ (IFSLJOϑΥʔϚοτͰʮͳͥͳΒʯΛߟ͑Δ
    ‣ \XIP^ͱͯ͠ɺ\IPX^͍ͨ͠ɻͳͥͳΒ\XIZ^͔ͩΒͩ
    ‣ ϑΟʔνϟػೳ͕Ͱ͖ͨΒͲͷΑ͏ʹͳͬͯ

    ΄͍͔͠Λɺ೴಺͔Βग़ͯ͠ɺߟ͑Δ
    ‣ 5%%ͷࣗ෼͕࠷ॳͷϢʔβʔͷࢹ఺Λɺػೳશମʹద༻͢Δ
    ‣ ͦΕΛ΋ͱʹɺιϑτ΢ΣΞ։ൃऀҎ֎ͷεςʔΫϗϧ
    μʔͱ΋ߟ͑Λڞ༗͢Δ
    ࣮͸ಈ͔ͳͯ͘΋ྑ͔ͬͨ

    View Slide

  46. ‣ ιϑτ΢ΣΞͷৼΔ෣͍Λɺར༻ऀͷ໨ઢʹཱͬͯ
    هड़͢Δ͜ͱ
    ‣ ଟ༷ͳεςʔΫϗϧμʔͱձ࿩͢ΔͨΊɺ

    ͦͷ౔୆ͱͳΔڞ௨ޠኮΛ࡞Δ͜ͱ
    ‣ ౰࣌ಉ࣌ʹྲྀߦ͍ͬͯͨ%%%͔ΒʮϢϏΩλεݴޠʯͷ֓೦Λ༌ೖ

    ςετۦಈ։ൃʮ෇࿥$ʯ
    πʔϧ͕มΘͬͯ΋Ҿ͖ܧ͛Δͱ͍͍΋ͷ

    View Slide

  47. ‣ ར༻ऀͷ໨ઢ͔Βݟͨಈ͖Λهड़͠ɺݕূ͢Δ
    ‣ ར༻ऀͷϝϯλϧϞσϧʹ͍ۙɺߴϨϕϧͳ"1*

    ޠኮ
    Λҭ͍ͯͯ͘
    ‣ ׬શʹίʔυίʔυ͍ͯ͠Δ͔Β೉͠͞͸͋Δ΋ͷͷ
    ͳͷͰ4ZTUFN\5FTU 4QFD^Ͱ΋

    View Slide

  48. ࣗવݴޠޠኮͱίʔυޠኮΛ͚ۙͮͯΈͨྫ

    let(:user) { create(:user) }
    let(article) { create(:article) }
    scenario 'ヘッダメニューからマイページ行けてfav履歴に遷移できる' do
    user.fav(article)
    login_as(user)
    within('nav.header-nav') do
    click_on 'マイページ'
    end
    click_on 'お気に入りの記事'
    expect(page).to have_content(article.title)
    end

    View Slide

  49. ·ͱΊ

    View Slide

  50. ‣ &&ςετ͸ศརͰڧྗ͕ͩɺສೳͰ͸ͳ͍
    ‣ յΕ΍͍͢
    ‣ ίʔυྔ͕ଟ͘ͳΓ͕ͪ
    ‣ ͪΐ͏ͲΑ͍ͱ͜ΖΛ୳Γ͍ͨ
    ‣ ͦͷώϯτͱͳΔࢹ఺Λ͓࿩Ͱ͖ͯΔͱΑ͍ͷͰ͕͢
    ͖ΐ͏࿩ͨ͜͠ͱ

    View Slide

  51. ‣ ςετهड़ͷਫ४Λɺར༻ऀͷ໨ઢʹ͚ۙͮΔ
    ‣ ͳΔ΂͘ߴϨϕϧ"1*Λ࢖͏
    ‣ ࣗ෼Ͱ΋ޠኮΛҭͯΔ
    ‣ ఆܕॲཧΛ·ͱΊͯͨΓɺ௿Ϩϕϧ"1*΁ͷΞΫηεΛϥοϓͨ͠Γ
    ‣ ͦ͜ʹυϝΠϯͷޠኮͰ໊લΛ͚ͭΒΕΔͱྑ͍
    ͪΐ͏ͲΑ͍&&ςετ

    View Slide