$30 off During Our Annual Pro Sale. View Details »

入門プロパティベーステスト/learning-property-based-testing

 入門プロパティベーステスト/learning-property-based-testing

ユニットテスト新着トピック3選!イチからわかるイマドキのテスト
https://trident-qa.connpass.com/event/314818/

での発表資料です。

Yasuhiro Kiwada

May 22, 2024
Tweet

Other Decks in Programming

Transcript

  1. © 2024 NTT TechnoCross Corporation 3 自己紹介 NTT研究所からの受託開発を 中心に、Web情報収集システ ム、モバイルアプリ、生体情

    報収集・分析システムなどの 開発に携わったあと、現在は 社内へのテスト自動化支援、 研修講師などの業務に従事し ている。趣味はベネズエラ音 楽。 Photo by Tomohide Ono
  2. © 2024 NTT TechnoCross Corporation 4 NTTテクノクロスについて 持続可能な社会の実現に向けて、NTT研究所の技術を軸に、 世の中の先端技術やサービスを掛け合わせ、お客様に価値を提供していく ミッション

    NTT研究所と世界の先進技術を融合し、 お客様と未来を共創し続けるソフトウェアリーディングカンパニー ビジョン 行動指針 CROSS:Challenge・Respect・Open・Synergy・Smile
  3. © 2024 NTT TechnoCross Corporation 5 LatteArt • NTT ソフトウェアイノベ-ションセンタが提供するOSS

    • NTTテクノクロスもコントリビュートしています • E2Eテストの記録・可視化・分析を支援 • アジリティの高い効率的なテストを提供 • ご利用・コントリビュートお待ちしています • https://github.com/latteart-org/latteart
  4. © 2024 NTT TechnoCross Corporation 9 プロパティベーステストとは • 自動テストの手法の一つ •

    「システムの満たすべき挙動」を形式化したものを プロパティと呼ぶ • コードで表現されたプロパティに対し、その条件を 満たす入力を自動生成して大量に与え、想定してい ない挙動をしないかを検証する • HaskellのQuickCheckが代表的。関数型言語のコ ミュニティで発展してきた
  5. © 2024 NTT TechnoCross Corporation 10 プロパティベーステストのフレームワーク フレームワーク 言語 fast-check

    JavaScript/TypeScript Hypothesis Python jqwik Java rapid Go PropCheck Ruby ※今日の発表は、fast-checkでサンプルコードを作成しています • 関数型に限った手法ではない • 様々な言語で、フレームワークが出揃ってきている
  6. © 2024 NTT TechnoCross Corporation 14 事例ベースの問題 • 「事例の適切さ」に左右されてしまう •

    もちろん、こういうテストがあれば問題なかった • 問題を検出するテストケースのために必要なもの • 知識 • 経験 • 勘 • 運
  7. © 2024 NTT TechnoCross Corporation 15 プロパティベースのアプローチ • プロパティで問題をとらえる •

    プログラムが満たすべき挙動 • ジェネレータで入力を生成する • 大量のランダムな入力を生成できる多彩なエンジン • 事後条件を検証する • 想定されたあらゆる入力に対して、事後条件を満すならば、 そのプログラムは正しい
  8. © 2024 NTT TechnoCross Corporation 17 プロパティベーステストのコードの挙動 • fc.array(fc.integer())で整数のランダム配列を生成 •

    デフォルトの設定では100個 • それら全てに対して、事後条件を検証 • 「ソートされている」ならば、次の値は常に前の値より大 きい • 事後条件を満さなければ失敗し、レポートを出力
  9. © 2024 NTT TechnoCross Corporation 18 プロパティベーステストのメリット • 満たすべき挙動を形式化してとらえることで問題に 集中できる

    • 事例の適切さ、事例の抜け漏れ、個人差などを考慮 する必要が減る • 問題を検出するテストケースのために必要なもの • 知識 • 経験 • 勘 • 運
  10. © 2024 NTT TechnoCross Corporation 19 複雑な例(ステートフルプロパティテスト) • 状態に依存したテスト •

    同じ入力でも結果が異なる • 状態の種類や組みあわせが多くなると複雑になりがち • 例: 書籍の貸し出しシステム 「在庫あり」の状態 「在庫なし」の状態 「実践プロパティベーステスト」貸して 貸し出し中です 「実践プロパティベーステスト」貸して
  11. © 2024 NTT TechnoCross Corporation 20 書籍の貸し出しシステムのテストケース • 「まだシステムに登録されていない本を追加する」に期待されるのは「成功」 •

    「すでにシステムに登録されている本を追加する」に期待されるのは「成功」 • 「すでにシステムに登録されている本の在庫を1冊追加する」期待されるのは「成功」 • 「まだシステムに登録されていない本の在庫を1冊追加する」に期待されるのは「エラー」 • 「システムに登録されていて利用可能な在庫がある本を貸し出し」に期待されるのは「在庫が1冊減る」 • 「システムに登録されているが利用可能な在庫がない本を貸し出しする」に期待されるのは「貸出不能のエラー」 • 「システムに登録されていない本を貸し出しする」に期待されるのは「エラー」 • 「システムに登録されている本を返却する」に期待されるのは「在庫を戻す」 • 「システムに登録されていない本を返却する」に期待されるのは「在庫がないというエラー」 • 「システムに登録されていて利用可能な在庫が減っていない本を返却する」に期待されるのも「エラー」 • 「ISBNで本を検索する」に対し「その本がシステムに登録されていない場合」に期待されるのは「失敗」 • 「著者名で本を検索する」に対し、「著者名の一部または全体と一致する本が少なくとも1つ登録されている」に期待され るのは「成功」 • 「書名で検索する」に対し「書名の一部または全部に一致する本が少なくとも1つ登録されている」に期待されるのは「成 功」 • 「タイトルまたは著者名で検索する」に対し「一致するものがない」に期待されるのは「空の結果」 ※ 「実践プロパティベーステスト」10.4 節より引用
  12. © 2024 NTT TechnoCross Corporation 21 事例ベースの場合必要なもの • 各状態のテストデータ •

    各状態を作るための手続き • 各状態に対応した入力と出力の事例 テーブルAにテストデータ入れて テーブルBにテストデータ入れて テストを実行して DB消して テーブルAにテストデータ入れて テーブルBにテストデータ入れて テストを実行して DB消して
  13. © 2024 NTT TechnoCross Corporation 22 プロパティベースの場合必要なもの • モデル •

    検証対象のシステムの状態/挙動を簡潔に表現したもの • コマンド • モデルと実システムの状態にもとづいた操作 • 事前条件と事後条件を検証 • ジェネレータ • ランダムなデータでコマンドを実行して状態を作り出す 様々な入力を 自動投入 入力に応じて状態は 変っていく 各状態ごとに、モデル と実システムを比較し 検証する
  14. © 2024 NTT TechnoCross Corporation 23 モデル化のアプローチ • 実システムとそのモデルの挙動を比較することでシ ステムの正しさを検証する

    • 実システム(高性能だが複雑でバグがあるかもしれない) • モデル(簡潔な実装だが正しく動く) • 内部実装は複雑だが、外からみた振舞いは同じで、 簡潔に表現できる場合に向いている
  15. © 2024 NTT TechnoCross Corporation 24 モデル化の例 • 書籍のリポジトリシステム getBookById(1)

    { “title”: “実践プロパティベーステスト”, “author”: “Fred Hebert”, “ISBN”: “978-4-908686-18-4” } getBookById(1) { “title”: “実践プロパティベーステスト”, “author”: “Fred Hebert”, “ISBN”: “978-4-908686-18-4” } RDBMS HashMap<number, string> 実システム モデル • システムにとって重要な性質を持つ • 永続性 • トランザクション • 一方で複雑さをはらむ • SQL • レコード=>JSON変換 • 貧弱だが振舞いとしては十分 • 簡潔で正しく動く
  16. © 2024 NTT TechnoCross Corporation 25 コマンド • 実システム、モデル両方への操作を行う •

    操作によって状態が変化する • 事前条件 • 状態を満しているなら操作実行 • 事後条件 • 操作実行後に実システムとモデルが同じか検証
  17. © 2024 NTT TechnoCross Corporation 28 ステートフルプロパティテストのメリット • 「状態を作る明示的な操作」が不要 •

    状態はジェネレータとコマンドにより、おのずと作られる • 「予期せぬ状態に陥るバグ」を検出できる • 手続き的に状態を作るテストだと「変な状態」は作りにく い
  18. © 2024 NTT TechnoCross Corporation 29 プロパティベーステストの弱点 • 「満たすべき挙動を形式化」がそもそも難しい •

    「事後条件」をコード化していくと、モデルと本実 装が限りなく同じになっていく • なにをテストしているのか分らないことに • それを避けるために「簡潔だが正しく動くモデル」が重要 • エラーの原因が特定しにくい場合がある • ランダム生成の入力に対する予期せぬエラー
  19. © 2024 NTT TechnoCross Corporation 30 事例ベースのユニットテストとの関係 • 排他的な関係ではない •

    プロパティベーステストを極めればユニットテストは不要、 ではない • 互いに補う関係 • ランダムな生成があてにならないケースでは事例のテスト を組み合せることでより強固になる • ユ ニ ッ ト テ ス ト (Checking) と 探 索 的 テ ス ト (Exploring)の中間的な位置付け • https://speakerdeck.com/twada/intro-to-property- based-testing
  20. © 2024 NTT TechnoCross Corporation 31 まとめ • プロパティベーステストは、単体レベルの検証にも、 システムの結合レベルの検証にも使える

    • システムが満すべき挙動を形式化してとらえ、問題 を検出することができる • 自動的に大量の入力を与えることで人手では作りに くい状態やテストケースをカバーできる • 従来のユニットテストと排他的な関係ではなく、互 いに補う合う関係である