Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RWC2025 Ninja-testing with smart playlist
Search
seki at druby.org
November 07, 2025
3
170
RWC2025 Ninja-testing with smart playlist
RWC2025
本日のおすすめテストの作り方
~忍者式テストのテスト抽出アルゴリズム~
seki at druby.org
November 07, 2025
Tweet
Share
More Decks by seki at druby.org
See All by seki at druby.org
XP, Testing and ninja testing ZOZ5
m_seki
3
1.1k
XP, Testing and ninja testing
m_seki
3
790
RWC 2024 DICOM & ISO/IEC 2022
m_seki
0
510
ERB, ancient and future
m_seki
3
940
ERB Hacks
m_seki
1
1.5k
わりこまれるはなし
m_seki
0
950
ぼくのかんがえたさいきょうのけいやくによるプログラミング
m_seki
2
1.4k
Learn Ractor
m_seki
1
2.8k
How many copies did you buy the first print?
m_seki
1
1.1k
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.5k
Writing Fast Ruby
sferik
630
62k
Statistics for Hackers
jakevdp
799
220k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.2k
Raft: Consensus for Rubyists
vanstee
140
7.2k
Why Our Code Smells
bkeepers
PRO
340
57k
We Have a Design System, Now What?
morganepeng
54
7.9k
Product Roadmaps are Hard
iamctodd
PRO
55
11k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
658
61k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
The Art of Programming - Codeland 2020
erikaheidi
56
14k
Transcript
OJOKBUFTUJOHDPN ຊͷ͓͢͢Ίςετͷ࡞Γํ ~ ऀࣜςετͷςετநग़ΞϧΰϦζϜ ~
"HFOEB ✦ ऀࣜςετͷ͓͞Β͍ ✦ ຊͷ͓͢͢Ίςετͷ࡞Γํ ऀࣜςετʹ͍ͭͯͪ͜ΒͷεϥΠυΛݟͯͶ👉IUUQTTQFBLFSEFDLDPNN@TFLJ[
ࣗݾհ ࢲͨͪ9ઢ$5ஔʹࡌ͢ΔιϑτΣΞΛ91Ͱ։ൃ͍ͯ͠·͢ ؔকढ़ϓϩάϥϚ ਂ୩ඒςελʔ ͜ͷ9ઢ$5ը૾ࢲͨͪͷ։ൃͨ͠ஔͰࡱӨͨ͠ࢲͨͪͷதʢਓؒυοΫͷ࠶ݕࠪͰࡱͬͯΒͬͨΑʂʣ
3VCZ8PSME$POGFSFODFʹΑͤͯ ✦ ࢲͨͪͷνʔϜͷ׆ಈͷத৺ʹɺ3VCZͷνέοτγεςϜ͕͋Γ·͠ ͨɻऀࣜςετ͜ͷνέοτγεςϜͷ͏͑ʹΓཱ͓ͬͯΓɺࢲͨͪͷ ؒ3VCZͱͱʹ͋ͬͨͷͰ͢ɻ ϏδωεͷͰ͢ʂʂ
ऀࣜςετ5%%ͷࣗવͳ֦ு ✦ ςετۦಈ։ൃʢ5%%ʣΛड͚ೖΕςετͷϨϕϧͰߦ͏ϓϥΫςΟε ✤ Y6OJUΛͬͨ5%%ͷΑ͏ʹɺड͚ೖΕςετ͔Β͡ΊΔ։ൃ ✤ ςετίʔυʹಋ͔ΕͯϓϩάϥϜΛ։ൃ͢ΔΑ͏ʹɺड͚ೖΕςετʹಋ͔ΕͯετʔϦʔΛ࣮ݱ͢Δ ✤ ετʔϦʔ͕૿͑ΔͨͼʹɺͦΕ·Ͱʹ࡞ͬͨͯ͢ͷετʔϦʔͷड͚ೖΕςετΛΓ͢ ऀ͕ຖ͢Δຑͷ্Λඈͼӽ͑Δमߦʹ༝དྷɻ໊લʮςετʯͰ͕͢ςετ͚ͩͰͳ͘ɺιϑτΣΞ։ൃશମͷ׆ಈͰ͢ɻ
➢ テスト駆動開発(TDD)を受け入れテストのレベルで行うプラクティス ⚫ xUnitを使ったTDDのように、受け入れテストからはじめる開発 ⚫ テストコードに導かれてプログラムを開発するように、受け入れテストに導かれてストー リーを実現する ⚫ ストーリーが増えるたびに、それまでに作ったすべてのストーリーの受け入れテストをやり 直す 忍者式テスト 11 September 2023 名前は「テスト」ですがテストだけでなく、ソフトウェア開発全体の活動です
ʲਤղʳऀࣜςετ ࣮ࡍͷ։ൃͰΠςϨʔγϣϯͰෳͷετʔϦʔΛѻ͍ͬͯΔ 【図解】忍者式テスト 15 September 2023 実際の開発では1イテレーションで複数のストーリーを扱っている Day1 V1
Story1 Day2 V2 Day3 V3 Story2 Story3
͍ͨΜͳ͜ͱʹͳΓ·͢ ͰΔΜͩΑ たいへんなことになります Day n+1 Vn+1 Story n+1 Day
n+2 Vn+2 Day n+3 Vn+3 Story n+2 Story n+3 Day n Vn Day n+ Vn+4 Story n+4
ऀࣜςετͷςετΛ୳͢ςετ ιϑτΣΞͷςετͱͳʹ͔ ✦ ؾʹೖΒͳ͍͜ͱΛ୳ͯ͠ɺͬͱྑ͘͢ΔͨΊʹςετ͢Δ ✤ ͏·͍ͬͨ͘ςετɺͱ͍͏ͷ৽͍͠Λݟ͚ͭΒΕͨςετ ✤ ࣦഊͨ͠ςετɺͱ͍͏ͷͳʹ͕ݟ͔ͭΒͳ͔ͬͨςετ Λݟ͚ͭΔͨΊʹखಈͰςετ͠·͢ʂʂʢࣗಈςετͰΒͳ͍Λݟ͚ͭΔͷ͍͠ʣ
ΤϥʔΛൃݟ͢ΔతͰϓϩάϥϜΛ࣮ߦ͢Δաఔ͕ ςετͰ͋Δɽ ιϑτΣΞͷ৴པੑQ
͍ͨΜͳ͜ͱʹͳΓ·͢ ͰΔΜͩΑ たいへんなことになります Day n+1 Vn+1 Story n+1 Day
n+2 Vn+2 Day n+3 Vn+3 Story n+2 Story n+3 Day n Vn Day n+ Vn+4 Story n+4
نͱ͖߹͏ ✦ ۙͷมߋૣ͔֬͘Ί͍ͨʗͯ͢ͷςετέʔεΛ͔֬Ί͍ͨ ✦ ҰͰͳ͘ɺ͋ΔظؒͰςετέʔεΛͯ͢ճ͢࡞ઓʹΓସ͑ͨ ✦ ·ΜΜͳ͘ɺ͔ͭɺޮՌͷߴ͍ςετέʔεΛநग़͢ΔΞϧΰϦζϜͷ։ൃ ✤ ৽͍͠ετʔϦʔɺमਖ਼͔ͨ͠ΓͷνέοτͷςετέʔεΛ࠷༏ઌ ✤
લճͷςετ݁Ռ͕ύεͨ͠ςετέʔεͷग़ݱසΛঃʑʹམͱ͢ ✤ ։ൃͷঢ়گʹԠͯ͡ػೳ͝ͱʹग़ݱසΛௐ ✤ ͋ΔظؒͰݟΔͱɺͯ͢ͷςετέʔε͕࣮ߦͰ͖Δ ✦ ΞϧΰϦζϜʹΑΓநग़ͨ͠ࠓͷςετεΠʔτˠʮຊͷ͓͢͢Ίςετʯ ✤ ҰʹͰ͖ͦ͏ͳྔͷςετέʔε͔͠දࣔ͠ͳ͍ʢྔʹѹ͞Εͳ͍Α͏ʹ͢Δʣ 👏ͬͱຊฤ͕͡·Γ·͢Αʂ
本日のおすすめテストの作り方 11 アイデア 実装 チケットシステムへの組み込み 今 日 は こ れ
!
アイデアの背景 21世紀の初めの話だよ! 12 ストリーミング以前の音楽の聴き方 全ての音楽ライブラリを持ち歩く! 毎日ライブラリが増えるとたいへんなことになる 新しい曲がなかなか聴けない(シャッフル再生) ライブラリが端末の容量を超えてしまう スマートプレイリストの工夫で解決してた 💿
💿 💿
これは! めっちゃ似てる! 13 テストスイートの生成に使えるのでは? ある期間で全曲再生するスマートプレイリスト ある期間で全部テストするテストスイート
毎日一回再生したい 基本編 14
毎日一回再生するプレイリスト スマートプレイリストは検索条件に従って動的にプレイリストが変化する 15 最後に再生した日が1日以内でない曲
毎日一回再生するプレイリスト 1日に同じ曲を何度も聴かない! 16 再生 するとリストから消えて、次の日に復活する 🕙 🕚 🕐 🕑
🕒 🕓 🕔 🕙 🕚 🕐 🕑 🕒 🕓 🕔 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈
毎日一回再生テストしたい 17 音楽の「再生」を「テスト」に置き換えてみます!
毎日一回テストするテストスイート 18 最後にテストした日が1日以内でないテストを集めれば 良い 「1日」を「ある期間」に拡張してみよう
ある期間で全部再生したい 19
ある期間で全部再生するプレイリスト 20 最後に再生した日がn日以内でない曲 再生したらしばらくお休み
ある期間で全部再生するプレイリスト 一度聴いた曲はしばらく再生されなくていい感じ! 21
㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 㽈 再生したらしばらくお休み
ある期間で全部テストしたい その日のおすすめが終わらなくても次の日には優先して現れるので気にしない 22 一度テストしたらある期間お休みするテストスイート 期間はチームがこなせるテストの量で調整する ギリギリよりちょっと多いくらいにする その日にテストできなかったら次の日に繰り越し
さらに細かくチューニングしたい 23 新規/修正直後のチケットを最優先 テストする頻度を調整する テーマごとのテストスイート(運用の工夫)
新規/修正直後のチケットを最優先 iTunesにはテスト結果がNGはないので、テストスイート生成用の特別な処理のこと 24 以下は休ませる期間に関係なくテストスイートに入れる 新規 = テストの履歴がない 修正直後 = 最後のテスト結果がNGのもの
テストする頻度を調整する レートによって休ませる期間を増減します 25 テストごとに★レートを設定する ★★☆☆☆ 自然に毎日さわる機能 (例)起動終了とか ★☆☆☆☆ 準備が大変→頻繁にはやりたくない (例)ディスクフルの用意とか
★★★★★ なんとなくあやしいから毎日試したい そういう機能あるでしょ?
テーマごとのテストスイート 26 機能、バージョン、機種など、テーマごとにテストス イートがあるとうれしい 関連するテストが続くので集中でき、問題を探索しやす い 開発状況に応じて注目点の時間配分を加減できる テーマを「テスト分類」と呼びタグで管理してる
実装 休ませるテストの判定をするメソッドと、それを呼ぶ並べ替えのふたつ 27 休ませるテストの判定 並べ替え def idle_period?(item) return false unless
item.last_result period = [300, 90, 28, 14, 7, 1].fetch(item.test_rate) item.last_date > Time.now - period * 24 * 60 *60 end ... list.delete_if { |item| idle_period?(item) }.sort_by { |item| [item.last_result ? 1 : 0, item.last_date, item.name] }.first(25)
休ませるテストの判定 trueだと休みだよ 28 最後のテストが設定された期間より新しいものは休み 最後の結果がNGのものは休ませない def idle_period?(item) return false unless
item.last_result period = [300, 90, 28, 14, 7, 1].fetch(item.test_rate) item.last_date > Time.now - period * 24 * 60 *60 end
休ませるテストの判定 trueだと休みだよ 29 最後のテストが設定された期間より新しいものは休み 最後の結果がNGのものは休ませない def idle_period?(item) return false unless
item.last_result period = [300, 90, 28, 14, 7, 1].fetch(item.test_rate) item.last_date > Time.now - period * 24 * 60 *60 end
並べ替え 30 休ませるテストを取り除く 最後のテストの実施が古い順に並べてN件選ぶ list.delete_if { |item| idle_period?(item) }.sort_by {
|item| [item.last_result ? 1 : 0, item.last_date, item.name] }.first(25)
並べ替え 31 休ませるテストを取り除く 最後のテストの実施が古い順に並べてN件選ぶ list.delete_if { |item| idle_period?(item) }.sort_by {
|item| [item.last_result ? 1 : 0, item.last_date, item.name] }.first(25)
並べ替え 32 休ませるテストを取り除く 最後のテストの実施が古い順に並べてN件選ぶ list.delete_if { |item| idle_period?(item) }.sort_by {
|item| [item.last_result ? 1 : 0, # 最後の結果がNGを優先 item.last_date, # 最後の実施日が古いものを優先 item.name] # 安定ソートのために名前順 }.first(25)
完成! テストケースごとの結果の履歴は各自準備してください!レートや分類のタグ付けはオプションだよ 33 あなたのチケットシステムに組み込もう! def idle_period?(item) return false unless item.last_result
period = [300, 90, 28, 14, 7, 1].fetch(item.test_rate) item.last_date > Time.now - period * 24 * 60 *60 end ... list.delete_if { |item| idle_period?(item) }.sort_by { |item| [item.last_result ? 1 : 0, item.last_date, item.name] }.first(25)
RWiki チケットシステムへの組み込み 34 自 慢
RWiki 20世紀製 35 ERB, dRubyのサンプルとして書いたWiki インメモリOODB 書式はRD(Ruby Document format)
チケットの例 36 1ページが1チケットに相当する テスト分類、レートも書いてある
リンクを利用したタグ付け 37 チケットからテスト分類へリンクする 逆リンクの集合を使ってテストスイートを作る 機能A チケット 機能B バージョン2 バージョン3
テストと履歴 38 チケットにはテストが書いてある テストした日と結果も記録
おまけ(履歴のすごいやつ) 2003年のチケットのテストが不要になっていることに2019年に気づいた例👉 39 2003年のチケットが見直されたりする たまにテストがNGになる 仕様が陳腐化するケースが多い 新しい仕様が過去の仕様を上書きする 実装の変化によりテストする意味がなくなる テスト通り動くけど意味のなさを検出!
Pageから属性を取得する仕組み YAMLが登場する前、せまい界隈でRDdataというアイデアがあったような 40 RDtoolでRDを変換する過程でDOM木が生成される。 DOM木をパターンマッチして属性リストを作る
テストスイート生成ツールの抜粋 ツールはRWikiと別のプロセスだよ 41 index = rwiki['test-v1'] # タグのページを取得 list =
index.rev_links.map {|name| # 逆リンクでmap rwiki[name].prop(:story) # propを集める } # さっき説明した選択と並び替え処理 rwiki['sorted-test-v1'].src = rd # テストスイートの # ページを作成
RWikiのObjectを外から使う 青いところがRWikiのObjectへの参照、赤いところがRMI 42 dRubyがちゃんと実用になっててすごい! RWiki ツール index = rwiki['test-v1'] #
タグのページを取得 list = index.rev_links.map {|name| # 逆リンクでmap rwiki[name].prop(:story) # propを集める } # さっき説明した選択と並び替え処理 rwiki['sorted-test-v1'].src = rd # テストスイートの # ページを作成
さて検証の時間です miwa719による解説です 43 自慢はここまで 本日のおすすめテストはうまくいってる? 20年分のテストの記録で確かめてみましょう
ςετ࣮ࢪͷهʢʣ /(ͷΑ͘ݟ͑ΔΑ͏ʹڧௐ͍ͯ͠·͢ テスト実施の記録(20年分) 57 営業日 チケット番号 September 2023 NGの点はよく見えるように強調しています
0,ςετέʔεͱͦͷपลΛ୳ࡧ͕ͯ͠ݟ͔ͭΒͳ͔ͬͨͷ /(ςετέʔε͕௨Βͳ͍͚ͩͰͳ͘ɺ༷௨Γ͚ͩͲ͍ͮΒ͍ɺ༷͕৽ ͍༷͠ʹΑ্ͬͯॻ͖͞Εͯ͠·ͬͨɺख৮ΓʢͪΒ͖ͭɺΘ͔ͣͳԆʣʹ ҧײ͕͋ΔͳͲɺؾʹೖΒͳ͍ͷશ͕ͯ/(ɻڱٛͷόάগͳ͍
ςετ࣮ࢪͷهʢʣ テスト実施の記録(20年分) 57 営業日 チケット番号 September 2023 NGの点はよく見えるように強調しています ॳظͷࠒຖͯ͢ͷνέοτΛςετ͍ͯͨ͠ͷͰۭന͕ͳ͍
👆 ͜ͷลΓ͔Βʮຊͷ͓͢͢ΊςετʯΛӡ༻
ςετ࣮ࢪͷهʢʣ テスト実施の記録(20年分) 57 営業日 チケット番号 September 2023 NGの点はよく見えるように強調しています લͷνέοτఆظతʹςετ͞Ε͍ͯΔ
ςετ࣮ࢪͷهʢʣ ʢΞϧΰϦζϜͱผʹɺऑ͍෦νέοτՃ͞ΕΔͷͰࣗવͱςετέʔεް͘ͳΔʣ テスト実施の記録(20年分) 57 営業日 チケット番号 September 2023 NGの点はよく見えるように強調しています
৽͍͠ɾमਖ਼͔ͨ͠ΓͷνέοτͷςετέʔεΛ࠷༏ઌ ͜ͷΑ͏ͳνέοτ৽ͨͳ͕ൃݟ͞Εࠩ͠͞ΕΔ͜ͱ͕ଟ͍ ։ൃதʹٞΛਚͯ͘͠ɺຊΛ৮Δ͜ͱͰͬͱΑ͍༷ʹؾ͍ͮͯ͠ ·͏
ςετ࣮ࢪͷهʢʣ テスト実施の記録(20年分) 57 営業日 チケット番号 September 2023 NGの点はよく見えるように強調しています ͜ͷۭനଳ࣍ੈͷʹγϑτͨ࣌͠ظ
ࣄۀܭըʹैͬͯςετͷྗΛௐͨ͠ ͦͷޙɺঃʑʹ·ΜΜͳ͘ςετ͢ΔΑ͏ʹճ෮
͏·͘Ͱ͖ͯΔͷʁ ✦ ͏·͘Ͱ͖ͯͨʂ👏
ऀࣜςετΛࢧ͑Δʮຊͷ͓͢͢Ίςετͷ࡞ΓํʯΛࣗຫ͠·ͨ͠🥷ɹίʔϧυεϦʔϓલͷ࠷ޙͷߨԋͰͨ͠ ຊͷ͓͢͢Ίςετͷ࡞Γํ ʔEpisode MATSUEʔ Ninja testing ZO/Z5 Anniversary