テスト
2025年5月30日
浅海智晴
クラウドアプリケーションのための
オブジェクト指向分析設計講座
第47回
ケース・スタディ
SimpleModeling2021
• オブジェクト指向分析設計での共通範囲
• UML/UP
• 本講座で使用するUMLプロファイル
• プロファイル:SimpleModeling2021 (SM2021)
• オブジェクト指向分析設計の基本からの拡張部を明確化
• アジャイル開発
• Communication
• Embrace Change
• Travel Light
• Scaling
• Component-Based Development
• クラウド・アプリケーション
• モデル駆動開発
SM2021
Travel Light
Embrace Change
Cloud
Model-Driven
Scaling
CBD
Testability
Serviceability
• 非機能要件
• Testability
• Serviceability
第1部 基本編の構成(1)
• 概論 [第1回]
• 開発プロセス [第2回]
• 基本モデル [第3回]
• 静的モデル(1) [第4回]
• 静的モデル(2) [第5回]
• 動的モデル [第6回]
• 協調モデル [第7回]
• 関数モデル [第8回]
• 物理モデル [第9回]
• 作業分野 [第10回]
• ビジネス・モデリング [第11回]
• 要求 [第12回]
• 要求/ユースケース [第13回]
• 要求/シナリオ [第14回]
• 分析 [第15回]
• 分析/コンポーネント分析 [第16回]
• 分析/イベント駆動 [第17回]
• 作業分野
• 設計 [第18回]
• 設計/アーキテクチャ設計 [第19回]
• 設計/コンポーネント設計(1) [第20回]
• 設計/コンポーネント設計(2) [第21回]
• 設計/コンポーネント設計(3) [第22回]
• 設計/ドメイン設計(1) [第23回]
• 設計/ドメイン設計(2) [第24回]
• 設計/ドメイン設計(3) [第25回]
• 設計/ドメイン設計(4) [第26回]
• 設計/ドメイン設計(5) [第27回]
• 設計/原理 [第28回]
• 設計/ UX/UI設計 [第29回]
• 実装(1) [第30回]
• 実装(2) [第31回]
• 実装(3) [第32回]
• テスト [第33回]
第1部 基本編の構成(2)
• アプリケーション・アーキテクチャ [第34回]
• Cloud Native CBD [第35回]
• ドメイン・サブシステム [第36回]
• アプリケーション・サブシステム [第37回]
• プレゼンテーション・サブシステム [第38回]
• Cloud Native Component Framework [第39回]
• ケーススタディ[第40回]
• ビジネス・モデル [第41回]
• 要求モデル [第42回]
• 要求モデル/BDD [第43回]
• 分析モデル [第44回]
• 設計モデル [第45回]
• 実装 [第46回]
• テスト [第47回]
本講座のアプローチ
• オブジェクト指向分析設計の基本を確認
• UML + UP(Unified Process)
• CBD (Component-Based Development)
• 最新技術でアップデート
• クラウド・コンピューティング
• イベント駆動、分散・並列
• ビッグデータ、AI、IoT
• コンテナ
• 関数型
• OFP(Object-Functional Programming), Reactive Streams
• ルール, AI
• DevOps
• アジャイル開発
• DX (Digital Transformation)
第25回 アプリケーション・アーキテクチャ
第2回 開発プロセス
第9回 物理モデル
第11回 ビジネス・モデリング
第2部 クラウド・アプリケーション編
第21回 設計/ドメイン設計
第20回 設計/コンポーネント設計
第2部 クラウド・アプリケーション編
原理 (Principle)
• Agile Software Development [ASD]
• SRP (The Single Responsibility Principle)
• OCP (The Open-Close Principle)
• LSP (The Liskov Substitution Principle)
• …
• GRASP (General Responsibility Assignment Software Patterns or principles)
• Low Coupling
• High Cohesion
• …
• Writing Effective Use Cases [WEUC]
• Scope
• …
パターン (Pattern)
• Design Patterns [DP]
• Observer, Strategy, …
• Domain Driven Design [DDD]
• Ubiquitous Language, Intention-
Revealing Interfaces, …
• Analysis Patterns [AP]
• Party, Quantity, …
• Pattern-Oriented Software
Architecture [POSA]
• Layers, Pipes and Filters, …
• Patterns of Enterprise
Application Architecture [PEAA]
• Unit of Work, Data Transfer Object,
…
• Enterprise Integration Patterns
[EIP]
• Message Bus, Aggregator, …
• Patterns for Effective Use
Cases [PEUC]
• CompleteSingleGoal,
VerbPhraseName, …
• AntiPatterns [AnP]
• Stovepipe System, Analysis
Paralysis, …
内容
• テスト
• Solo開発向けのテストについて検討
• プラクティス
• Evolve Cloud Native CBD
• User Environment Lite
• CI/CD Pipeline
ケーススタディ
• ブック・カフェPieris Booksの販売システム
• 新刊・古本などの書籍に加えてアクセサリーや日用品などのセ
レクト商品を販売
• もともと新刊・古本の販売も行うブックカフェでしたが、新し
くアクセサリーや日用品のセレクト商品販売を併設することに
した
• セレクト商品は見本品の展示を基本と考えており、見本品に対
してECでオーダをする方式を主に考えている
• 見本品はECサイトでの販売も行う
再掲 第40回 ケーススタディ
開発体制
• 背景
• オブジェクト指向分析設計に興味を持つ関係者がいない環境
• クラウド・アプリケーション開発、アジャイル開発、
• 自分一人でアジャイル開発によるオブジェクト指向開発を進める
• 登場人物
• A(私) : バックエンド開発
• 開発プロセスをマスターして、より大きな規模の開発につなげたい
• Uさん:フロントエンド開発
• 手練れのUIエンジニア。モデリングには興味がなくプログラミング中心で開発を行う
• Bさん:ブック・カフェPieris Booksの店長
• ビジネスでやりたいことは明確にもっているが、ビジネス・モデリング的なアプロー
チには興味がない
再掲 第40回 ケーススタディ
テスト
作業分野とモデルの関係 第10回 作業分野
再掲
PracticeのActivity
(マイ開発プロセス版改2)
テストの方法論
• 関数モデル [第8回]
• Object-Functional Programming
• 作業分野/実装(1) [第30回]
• DevOps, CBD, TDD, CI/CDパイプライン
• 作業分野/実装(2) [第31回]
• 設計の成果物、実装のポイント、TDD
• 作業分野/実装(3) [第32回]
• CI/CDパイプライン、マイクロサービス、UI、ドキュメント
• 作業分野/テスト [第33回]
• CI/CDパイプライン、マイクロサービス、UI、ドキュメント
• ケーススタディ/要求モデル/BDD [第43回]
• BDD
実装までの流れ
第46回 ケーススタディ/実装
再掲
テストの方針
• テストの効率化
• Sole開発なので効果の低いテスト・ケースは作らない
• 仕様とテストの融合
• BDD/TDD
• Macherを定義してテストを宣言的に記述する語彙を充実させる
• FP (Functional Programming)
• 基本品質向上
• テスト・ケース開発量の低減
• Testable
• DI, Effect
• Testable
• CI/CD Pipeline
• CBD
• Contract, DI, Autonomy
• FP
プラクティス
プラクティス
• Use case lite
• Test a Use-case slice
• User Environment Lite
• Evolve Documents
• CI/CD Pipeline
• Ensure CI/CD Pipeline to Test
テストの枠組み
テストの位置つけ
• QA (Quality Assurance)
• ソフトウェア・システムの品質を確保
• テスト計画・テスト実行
• 伝統的な枠組み
• 動く仕様書
• 「テスト」の位置つけを変える技術革新
• TDD/BDD
• CI/CDパイプライン
• オブジェクト指向技術
• CBD
• シナリオ分析
• Scala DSL(Domain Specific Language)でさらに使いやすくなった
Travel Light
Embrace Change
第33回 作業分野/テスト
再掲
品質向上
• バグが出にくい仕組み
• 静的型付け純粋関数型言語
• 直観主義命題論理の範囲で証明
• 代数的メカニズム
• Monad/Monoid
• Effect
• 非同期・並列・並行・分散
• テスト
• テスト・ケースの設計技法
• Lint
• Effect
• Side Effect
• 非同期・並列・並行・分散
仕様とテストの関係
第33回 作業分野/テスト
再掲
テストの作り過ぎ問題
• 機能追加、仕様変更が発生した場合の追随の工数が問題となる
• テスト・ケースのエラーが多すぎる場合、テスト・ケース毎破
棄して作り直しすることも
• テスト・ケースの開発工数が無駄になる
テストの作り過ぎ問題・対策1
• ライフサイクル毎にテストの厚みを変える
• UI層
• 更新頻度:高
• 自動テストの量:小
• アプリケーション層
• 更新頻度:中
• 自動テストの量:中
• ドメイン層
• 更新頻度:低
• 自動テストの量:多
テストの作り過ぎ問題・対策2
• テスト・ケースを(大量に)作らないでよい状況を整備
• CI/CDパイプライン
• 静的テスト
• コンパイル/Lint
• 生成AIによるレビュー
• Functional Programming
• 並列・並行・分散
• Property-Baesd Testing
• Typeclass Laws
Testable
テスト容易性 (Testability)
• コンポーネントのテストのしやすさ
• 他のコンポーネントとの依存性をできるだけ排除する
• インタフェース(提供、要求)を通してアクセス
• コンポーネントの作成はDI(Dependency Injection)を可能にす
る
• クライアントの実行文脈は実行コンテキスト経由で取得するよ
うにする
• 認証情報、時間
• コンポーネントの内部情報がテスト・プログラムから取得でき
るようにする
再掲 第21回 設計/コンポーネント設計 (2)
DI (Dependency Injection)
• DIによって実行文脈を変えることができる構造になっていることが
重要
• 対象
• カスタマイズ情報
• 外部サービス
• 実行コンテキスト
• 実現方法
• DIフレームワーク (e.g. Google Guice)
• 暗黙パラメタ
• FP
• Readerモナド
• Tagless final
実行コンテキスト (Execution Context)
• コンポーネントの実行文脈を切り替えるメカニズム
• コンポーネントのユニットテストにも必要
• スコープ
• セッション・コンテキスト
• アプリケーション・コンテキスト
• システム・コンテキスト
• 機能
• 認証済みプリンシパル
• トランザクション
• UnitOfWork
• 時間
• 日時、タイムゾーン
• 国際化
• ロケール、メッセージ、通貨
再掲 第5回 静的モデル(2)
本講座用の仮想のコンポーネント・フレームワー
クが提供する実行コンテキストを用いる予定
仕様とテストの融合
仕様とテストの融合
• BDD
• システムの振る舞いをシナリオ・ベースのテスト・ケースとして記述
• ケース・スタディではUse case sliceをBDDで記述することで、ユースケー
スによる要求仕様とテスト・ケースを融合させている
• Sprint backlogにエントリすることでプロジェクト管理とも統合
• TDD
• プログラムの外部仕様をテスト・ケースとして記述
• ケース・スタディでは分析モデルのバウンダリ・オブジェクトの振る舞いを
TDDで記述
• Sprint backlogにエントリすることでプロジェクト管理とも統合
• CI/CD Pipeline
• BDD, TDDによるテスト・ケースをCI/CD Pipelineに組み込むことで、常に
仕様に準拠した状態であることが担保される
ScalaTest
• Scalaのテスティング・フレームワーク
• ScalaのDSL機能を用いてテストを宣言的に記述できる
• テストと仕様の融合
• Matcher
• テスト用のボキャブラリを定義
• テストを手続ではなく宣言で記述するための仕組み
class ReservationServiceSpec extends AnyFreeSpec
with Matchers
with GivenWhenThen
with ReservationMatchers {
"ReservationService" - {
"reserveメソッド" - {
"予約の追加" - {
"現在時刻より後ろの有効な予約時間を予約" in {
Given("テスト用に作成したReservationServiceを使用")
val service = ReservationService.createForTest()
When("運用時間内の時間")
val dt = "2024-01-15T10:00:00+JST"
Then("テスト対象時刻で実行コンテキストを用意")
given ExecutionContext = ExecutionContext.createWithCurrentDateTime(dt)
And("現在時刻より後ろの有効な予約時間で予約")
ReservationServiceSpec.sbt (1/2) 再掲 第31回 設計/実装(2)
val rid = ResourceId("id1234")
val uid = UserId("user789")
val start = LocalDateTime.of(2024, 1, 15, 11, 00)
val end = LocalDateTime.of(2024, 1, 15, 12, 00)
val interval = Interval.openUpper(start, end)
val cmd = ReserveCommand(rid, uid, interval)
service.reserve(cmd) should successReserve(cmd)
}
}
}
}
}
ReservationServiceSpec.sbt (2/2) 再掲 第31回 設計/実装(2)
Property-Based Testing
• 仕様(性質:Property)を記述し、自動生成される多様な入力に対
して常に成り立つか検証
• 大量、多様なパラメタを組み合わせたテストを自動化
• 境界値や意外なケースを自動で発見
• 仕様記述に近いテストが書ける
• Example-Based Testing
• 実例のパラメタに対応する振る舞いを記述
class CounterPropertySpec extends AnyWordSpec with should.Matchers with
ScalaCheckDrivenPropertyChecks:
"Counter" should {
val nonNegativeInts = Gen.listOf(Gen.choose(0, 10000))
"Property-Based TestingでCounterのfoldMap動作をテストする" in
forAll(nonNegativeInts) { (xs: List[Int]) =>
val c: Counter = xs.foldMap(Counter.apply)
c.c should be(xs.sum)
}
}
Property-basedテスティングによるテスト
テストデータの特性を定義
Property−basedテスティングの実行
BDD (Behavior-Driven Development)スタイルのテスト
Travel Light
第16回 テスト
再掲 第8回 関数モデル
Typeclass Law
• 型クラスに対する法則を定義して、型クラスインスタンスが法
則に準拠していることを自動テストできる
• Property-Based Testingと法則の定義を組み合わせて自動テストを実
現
• ScalaCheck
• Property-Based Testingのテスティング・フレームワーク
• ScalaTestに組み込んで使うことができる
• cats-discipline
• Lawを構造化、再利用可能にする仕組み
class CounterLawSpec extends AnyFunSuite with FunSuiteDiscipline with Configuration:
lazy val counterGen: Gen[Counter] = Gen.choose(0, 10000).map(Counter.apply)
implicit lazy val counterArbitrary: Arbitrary[Counter] = Arbitrary(counterGen)
checkAll("Counter", MonoidTests[Counter].monoid)
Monoid法則のテスト
Monoid法則のテストを一括して行う
型クラスの規則のテスト用トレイト
再掲 第8回 関数モデル
Functional Programming
関数型プログラミングの特性
• 副作用なし
• Side-Effect-Free Functions [DDD]
• 参照透過性(Referential transparency)
• 同じ入力に対して必ず同じ値を返す
• 置換モデル
• 「等価による置換」の繰り返しで式の評価を行う
• 合成可能性(Composable)
• 細粒度のマイクロ・フレームワーク上でアルゴリズムの部品化・再利用
• DSL(Domain Specific Language)メタ言語
• Declarative Style [DDD]
第8回 関数モデル
再掲
FPとテスト
• Effect
• Tagless Final
• Property-Based Testing
• Typeclass Laws
• DI
Effect
• (実務的には)関数の参照透過性を阻害する要因
• 副作用(side-effect)
• 非決定性
• 非同期・並列・並行・分散
• 時間
• 乱数
• エラー
• Effectとして参照透過性を破る要素を分離することで、関数の
ロジックのテストが容易になる
• Effect Polymorphism
• 参照透過性が保たれるので、関数の実行結果が必ず同じになりテスト
可能になる
Tagless Final
• タグ付きADTを使わず(Tagless)、抽象的な型クラスでDSLを直
接記述する最終形式(Final)の抽象構文エンコーディング手法
• 抽象操作定義(Algebra)を型クラスで定義
• 目的毎のインタプリター(Interpreter)を型クラスインスタンスとして
作成
• プログラム(Program)は型クラスを用いてビジネス・ロジックを記述
• Effectの利用にTagless Finalを用いることで、Effectをビジネ
ス・ロジックから分離して参照透過性を保つことができる
Tagありの例:Free Monad
trait Console[F[_]] {
def println(msg: String): F[Unit]
def readLine: F[String]
}
def program[F[_]: Monad](console: Console[F]): F[Unit] =
for {
_ <- console.println("What is your name?")
name <- console.readLine
_ <- console.println(s"Hello, $name!")
} yield ()
val consoleForIO = new Console[IO] {
def println(msg: String): IO[Unit] = IO(scala.Console.println(msg))
def readLine: IO[String] = IO(scala.io.StdIn.readLine())
}
val prog = program(consoleForIO)
val r = prog.unsafeRunSync()
Tagless Finalの例
抽象操作(Algebra)を型クラスで記述
抽象操作(Algebra)を使用したロジックを記述
抽象操作(Algebra)の型クラスをIOモナドで実現
IOモナドによる抽象操作(Algebra)の型クラスインスタンスによりプログラムを実体化
プログラムの実現・この処理だけ参照透過性の範囲外
DI (Dependency Injection)
• Functional ProgrammingでのDI技術
• 関数単位でDIができるのでTestabilityが向上
• 部分適用
• カリー化するとより意図が明確になる
• 暗黙パラメタ
• Environment, Configuration, Execution ContextをDI
• Readerモナド/ReaderTモナド・トランスフォーマ
• ReaderWriterState/ReaderWriterStateT
• Environment, Configuration, Execution ContextをDI
• モナド・トランスフォーマ
• Effect
• Tagless Final
• Effect polymorphism
• EffectをDI
• 非同期、並列、並行、分散
ReaderWriterStateT&EitherT&Freeモナドは例外状
態、DSL、文脈情報伝達、情報追記、状態遷移の5つ
の機能を持つマイクロフレームワークとなっている
第27回 ドメイン設計(5)
再掲
まとめ
• ケーススタディ
• ブック・カフェPieris Booksの販売システム
• プラクティス/アクティビティ
• Use case lite : Test a Use-case slice
• User Environment Lite : Evolve Documents
• CI/CD Pipeline : Ensure CI/CD Pipeline to Test
• Testable
• 仕様とテストの融合
• FP (Functional Programming)
参考文献
• The Unified Modeling Language Reference Manual, 2nd
(Rumbaugh他, 2004)
• The Unified Modeling Language User Guide, 2nd (Booch他,
2004)
• The Unified Software Development Process (Jacobson他,
1999)
• The Object Constraint Language, 2nd (Warmer他, 2003)
• UML 2 and the Unified Process: Practical Object-Oriented
Analysis and Design (Arlow他, 2005)
• OMG Unified Modeling Language Version 2.5 (OMG, 2015)
• 上流工程UMLモデリング (浅海, 2008)
• The Essentials of Modern Software Engineering: Free the
Practices from the Method Prisons! (Jacobson他, 2019)
• ソフトウェア・テストの技法 第2版 (マイヤーズ他,
2006)
• 【この1冊でよくわかる】ソフトウェアテストの教科書
[増補改訂 第2版](布施 他, 2021)
• 知識ゼロから学ぶソフトウェアテスト 第3版 アジャイ
ル・AI時代の必携教科書 (高橋, 2023)
• ソフトウェア品質を高める開発者テスト 改訂版 アジャ
イル時代の実践的・効率的でスムーズなテストのやり方
(高橋, 2022)
• Extreme Programming Explained: Embrace Change 2nd
(Beck, 2004)
• Specification by Example: How Successful Teams Deliver the
Right Software (Adzic, 2011)
• BDD in Action: Behavior-Driven Development for the whole
software lifecycle (Smart, 2014)

ケーススタディ/テスト 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第47回】

  • 1.
  • 2.
    SimpleModeling2021 • オブジェクト指向分析設計での共通範囲 • UML/UP •本講座で使用するUMLプロファイル • プロファイル:SimpleModeling2021 (SM2021) • オブジェクト指向分析設計の基本からの拡張部を明確化 • アジャイル開発 • Communication • Embrace Change • Travel Light • Scaling • Component-Based Development • クラウド・アプリケーション • モデル駆動開発 SM2021 Travel Light Embrace Change Cloud Model-Driven Scaling CBD Testability Serviceability • 非機能要件 • Testability • Serviceability
  • 3.
    第1部 基本編の構成(1) • 概論[第1回] • 開発プロセス [第2回] • 基本モデル [第3回] • 静的モデル(1) [第4回] • 静的モデル(2) [第5回] • 動的モデル [第6回] • 協調モデル [第7回] • 関数モデル [第8回] • 物理モデル [第9回] • 作業分野 [第10回] • ビジネス・モデリング [第11回] • 要求 [第12回] • 要求/ユースケース [第13回] • 要求/シナリオ [第14回] • 分析 [第15回] • 分析/コンポーネント分析 [第16回] • 分析/イベント駆動 [第17回] • 作業分野 • 設計 [第18回] • 設計/アーキテクチャ設計 [第19回] • 設計/コンポーネント設計(1) [第20回] • 設計/コンポーネント設計(2) [第21回] • 設計/コンポーネント設計(3) [第22回] • 設計/ドメイン設計(1) [第23回] • 設計/ドメイン設計(2) [第24回] • 設計/ドメイン設計(3) [第25回] • 設計/ドメイン設計(4) [第26回] • 設計/ドメイン設計(5) [第27回] • 設計/原理 [第28回] • 設計/ UX/UI設計 [第29回] • 実装(1) [第30回] • 実装(2) [第31回] • 実装(3) [第32回] • テスト [第33回]
  • 4.
    第1部 基本編の構成(2) • アプリケーション・アーキテクチャ[第34回] • Cloud Native CBD [第35回] • ドメイン・サブシステム [第36回] • アプリケーション・サブシステム [第37回] • プレゼンテーション・サブシステム [第38回] • Cloud Native Component Framework [第39回] • ケーススタディ[第40回] • ビジネス・モデル [第41回] • 要求モデル [第42回] • 要求モデル/BDD [第43回] • 分析モデル [第44回] • 設計モデル [第45回] • 実装 [第46回] • テスト [第47回]
  • 5.
    本講座のアプローチ • オブジェクト指向分析設計の基本を確認 • UML+ UP(Unified Process) • CBD (Component-Based Development) • 最新技術でアップデート • クラウド・コンピューティング • イベント駆動、分散・並列 • ビッグデータ、AI、IoT • コンテナ • 関数型 • OFP(Object-Functional Programming), Reactive Streams • ルール, AI • DevOps • アジャイル開発 • DX (Digital Transformation) 第25回 アプリケーション・アーキテクチャ 第2回 開発プロセス 第9回 物理モデル 第11回 ビジネス・モデリング 第2部 クラウド・アプリケーション編 第21回 設計/ドメイン設計 第20回 設計/コンポーネント設計 第2部 クラウド・アプリケーション編
  • 6.
    原理 (Principle) • AgileSoftware Development [ASD] • SRP (The Single Responsibility Principle) • OCP (The Open-Close Principle) • LSP (The Liskov Substitution Principle) • … • GRASP (General Responsibility Assignment Software Patterns or principles) • Low Coupling • High Cohesion • … • Writing Effective Use Cases [WEUC] • Scope • …
  • 7.
    パターン (Pattern) • DesignPatterns [DP] • Observer, Strategy, … • Domain Driven Design [DDD] • Ubiquitous Language, Intention- Revealing Interfaces, … • Analysis Patterns [AP] • Party, Quantity, … • Pattern-Oriented Software Architecture [POSA] • Layers, Pipes and Filters, … • Patterns of Enterprise Application Architecture [PEAA] • Unit of Work, Data Transfer Object, … • Enterprise Integration Patterns [EIP] • Message Bus, Aggregator, … • Patterns for Effective Use Cases [PEUC] • CompleteSingleGoal, VerbPhraseName, … • AntiPatterns [AnP] • Stovepipe System, Analysis Paralysis, …
  • 8.
    内容 • テスト • Solo開発向けのテストについて検討 •プラクティス • Evolve Cloud Native CBD • User Environment Lite • CI/CD Pipeline
  • 9.
    ケーススタディ • ブック・カフェPieris Booksの販売システム •新刊・古本などの書籍に加えてアクセサリーや日用品などのセ レクト商品を販売 • もともと新刊・古本の販売も行うブックカフェでしたが、新し くアクセサリーや日用品のセレクト商品販売を併設することに した • セレクト商品は見本品の展示を基本と考えており、見本品に対 してECでオーダをする方式を主に考えている • 見本品はECサイトでの販売も行う 再掲 第40回 ケーススタディ
  • 10.
    開発体制 • 背景 • オブジェクト指向分析設計に興味を持つ関係者がいない環境 •クラウド・アプリケーション開発、アジャイル開発、 • 自分一人でアジャイル開発によるオブジェクト指向開発を進める • 登場人物 • A(私) : バックエンド開発 • 開発プロセスをマスターして、より大きな規模の開発につなげたい • Uさん:フロントエンド開発 • 手練れのUIエンジニア。モデリングには興味がなくプログラミング中心で開発を行う • Bさん:ブック・カフェPieris Booksの店長 • ビジネスでやりたいことは明確にもっているが、ビジネス・モデリング的なアプロー チには興味がない 再掲 第40回 ケーススタディ
  • 11.
  • 12.
  • 13.
  • 14.
    テストの方法論 • 関数モデル [第8回] •Object-Functional Programming • 作業分野/実装(1) [第30回] • DevOps, CBD, TDD, CI/CDパイプライン • 作業分野/実装(2) [第31回] • 設計の成果物、実装のポイント、TDD • 作業分野/実装(3) [第32回] • CI/CDパイプライン、マイクロサービス、UI、ドキュメント • 作業分野/テスト [第33回] • CI/CDパイプライン、マイクロサービス、UI、ドキュメント • ケーススタディ/要求モデル/BDD [第43回] • BDD
  • 15.
  • 16.
    テストの方針 • テストの効率化 • Sole開発なので効果の低いテスト・ケースは作らない •仕様とテストの融合 • BDD/TDD • Macherを定義してテストを宣言的に記述する語彙を充実させる • FP (Functional Programming) • 基本品質向上 • テスト・ケース開発量の低減 • Testable • DI, Effect • Testable • CI/CD Pipeline • CBD • Contract, DI, Autonomy • FP
  • 17.
  • 18.
    プラクティス • Use caselite • Test a Use-case slice • User Environment Lite • Evolve Documents • CI/CD Pipeline • Ensure CI/CD Pipeline to Test
  • 19.
  • 20.
    テストの位置つけ • QA (QualityAssurance) • ソフトウェア・システムの品質を確保 • テスト計画・テスト実行 • 伝統的な枠組み • 動く仕様書 • 「テスト」の位置つけを変える技術革新 • TDD/BDD • CI/CDパイプライン • オブジェクト指向技術 • CBD • シナリオ分析 • Scala DSL(Domain Specific Language)でさらに使いやすくなった Travel Light Embrace Change 第33回 作業分野/テスト 再掲
  • 21.
    品質向上 • バグが出にくい仕組み • 静的型付け純粋関数型言語 •直観主義命題論理の範囲で証明 • 代数的メカニズム • Monad/Monoid • Effect • 非同期・並列・並行・分散 • テスト • テスト・ケースの設計技法 • Lint • Effect • Side Effect • 非同期・並列・並行・分散
  • 22.
  • 23.
  • 24.
    テストの作り過ぎ問題・対策1 • ライフサイクル毎にテストの厚みを変える • UI層 •更新頻度:高 • 自動テストの量:小 • アプリケーション層 • 更新頻度:中 • 自動テストの量:中 • ドメイン層 • 更新頻度:低 • 自動テストの量:多
  • 25.
    テストの作り過ぎ問題・対策2 • テスト・ケースを(大量に)作らないでよい状況を整備 • CI/CDパイプライン •静的テスト • コンパイル/Lint • 生成AIによるレビュー • Functional Programming • 並列・並行・分散 • Property-Baesd Testing • Typeclass Laws
  • 26.
  • 27.
    テスト容易性 (Testability) • コンポーネントのテストのしやすさ •他のコンポーネントとの依存性をできるだけ排除する • インタフェース(提供、要求)を通してアクセス • コンポーネントの作成はDI(Dependency Injection)を可能にす る • クライアントの実行文脈は実行コンテキスト経由で取得するよ うにする • 認証情報、時間 • コンポーネントの内部情報がテスト・プログラムから取得でき るようにする 再掲 第21回 設計/コンポーネント設計 (2)
  • 28.
    DI (Dependency Injection) •DIによって実行文脈を変えることができる構造になっていることが 重要 • 対象 • カスタマイズ情報 • 外部サービス • 実行コンテキスト • 実現方法 • DIフレームワーク (e.g. Google Guice) • 暗黙パラメタ • FP • Readerモナド • Tagless final
  • 29.
    実行コンテキスト (Execution Context) •コンポーネントの実行文脈を切り替えるメカニズム • コンポーネントのユニットテストにも必要 • スコープ • セッション・コンテキスト • アプリケーション・コンテキスト • システム・コンテキスト • 機能 • 認証済みプリンシパル • トランザクション • UnitOfWork • 時間 • 日時、タイムゾーン • 国際化 • ロケール、メッセージ、通貨 再掲 第5回 静的モデル(2) 本講座用の仮想のコンポーネント・フレームワー クが提供する実行コンテキストを用いる予定
  • 30.
  • 31.
    仕様とテストの融合 • BDD • システムの振る舞いをシナリオ・ベースのテスト・ケースとして記述 •ケース・スタディではUse case sliceをBDDで記述することで、ユースケー スによる要求仕様とテスト・ケースを融合させている • Sprint backlogにエントリすることでプロジェクト管理とも統合 • TDD • プログラムの外部仕様をテスト・ケースとして記述 • ケース・スタディでは分析モデルのバウンダリ・オブジェクトの振る舞いを TDDで記述 • Sprint backlogにエントリすることでプロジェクト管理とも統合 • CI/CD Pipeline • BDD, TDDによるテスト・ケースをCI/CD Pipelineに組み込むことで、常に 仕様に準拠した状態であることが担保される
  • 32.
    ScalaTest • Scalaのテスティング・フレームワーク • ScalaのDSL機能を用いてテストを宣言的に記述できる •テストと仕様の融合 • Matcher • テスト用のボキャブラリを定義 • テストを手続ではなく宣言で記述するための仕組み
  • 33.
    class ReservationServiceSpec extendsAnyFreeSpec with Matchers with GivenWhenThen with ReservationMatchers { "ReservationService" - { "reserveメソッド" - { "予約の追加" - { "現在時刻より後ろの有効な予約時間を予約" in { Given("テスト用に作成したReservationServiceを使用") val service = ReservationService.createForTest() When("運用時間内の時間") val dt = "2024-01-15T10:00:00+JST" Then("テスト対象時刻で実行コンテキストを用意") given ExecutionContext = ExecutionContext.createWithCurrentDateTime(dt) And("現在時刻より後ろの有効な予約時間で予約") ReservationServiceSpec.sbt (1/2) 再掲 第31回 設計/実装(2)
  • 34.
    val rid =ResourceId("id1234") val uid = UserId("user789") val start = LocalDateTime.of(2024, 1, 15, 11, 00) val end = LocalDateTime.of(2024, 1, 15, 12, 00) val interval = Interval.openUpper(start, end) val cmd = ReserveCommand(rid, uid, interval) service.reserve(cmd) should successReserve(cmd) } } } } } ReservationServiceSpec.sbt (2/2) 再掲 第31回 設計/実装(2)
  • 35.
    Property-Based Testing • 仕様(性質:Property)を記述し、自動生成される多様な入力に対 して常に成り立つか検証 •大量、多様なパラメタを組み合わせたテストを自動化 • 境界値や意外なケースを自動で発見 • 仕様記述に近いテストが書ける • Example-Based Testing • 実例のパラメタに対応する振る舞いを記述
  • 36.
    class CounterPropertySpec extendsAnyWordSpec with should.Matchers with ScalaCheckDrivenPropertyChecks: "Counter" should { val nonNegativeInts = Gen.listOf(Gen.choose(0, 10000)) "Property-Based TestingでCounterのfoldMap動作をテストする" in forAll(nonNegativeInts) { (xs: List[Int]) => val c: Counter = xs.foldMap(Counter.apply) c.c should be(xs.sum) } } Property-basedテスティングによるテスト テストデータの特性を定義 Property−basedテスティングの実行 BDD (Behavior-Driven Development)スタイルのテスト Travel Light 第16回 テスト 再掲 第8回 関数モデル
  • 37.
    Typeclass Law • 型クラスに対する法則を定義して、型クラスインスタンスが法 則に準拠していることを自動テストできる •Property-Based Testingと法則の定義を組み合わせて自動テストを実 現 • ScalaCheck • Property-Based Testingのテスティング・フレームワーク • ScalaTestに組み込んで使うことができる • cats-discipline • Lawを構造化、再利用可能にする仕組み
  • 38.
    class CounterLawSpec extendsAnyFunSuite with FunSuiteDiscipline with Configuration: lazy val counterGen: Gen[Counter] = Gen.choose(0, 10000).map(Counter.apply) implicit lazy val counterArbitrary: Arbitrary[Counter] = Arbitrary(counterGen) checkAll("Counter", MonoidTests[Counter].monoid) Monoid法則のテスト Monoid法則のテストを一括して行う 型クラスの規則のテスト用トレイト 再掲 第8回 関数モデル
  • 39.
  • 40.
    関数型プログラミングの特性 • 副作用なし • Side-Effect-FreeFunctions [DDD] • 参照透過性(Referential transparency) • 同じ入力に対して必ず同じ値を返す • 置換モデル • 「等価による置換」の繰り返しで式の評価を行う • 合成可能性(Composable) • 細粒度のマイクロ・フレームワーク上でアルゴリズムの部品化・再利用 • DSL(Domain Specific Language)メタ言語 • Declarative Style [DDD] 第8回 関数モデル 再掲
  • 41.
    FPとテスト • Effect • TaglessFinal • Property-Based Testing • Typeclass Laws • DI
  • 42.
    Effect • (実務的には)関数の参照透過性を阻害する要因 • 副作用(side-effect) •非決定性 • 非同期・並列・並行・分散 • 時間 • 乱数 • エラー • Effectとして参照透過性を破る要素を分離することで、関数の ロジックのテストが容易になる • Effect Polymorphism • 参照透過性が保たれるので、関数の実行結果が必ず同じになりテスト 可能になる
  • 43.
    Tagless Final • タグ付きADTを使わず(Tagless)、抽象的な型クラスでDSLを直 接記述する最終形式(Final)の抽象構文エンコーディング手法 •抽象操作定義(Algebra)を型クラスで定義 • 目的毎のインタプリター(Interpreter)を型クラスインスタンスとして 作成 • プログラム(Program)は型クラスを用いてビジネス・ロジックを記述 • Effectの利用にTagless Finalを用いることで、Effectをビジネ ス・ロジックから分離して参照透過性を保つことができる Tagありの例:Free Monad
  • 44.
    trait Console[F[_]] { defprintln(msg: String): F[Unit] def readLine: F[String] } def program[F[_]: Monad](console: Console[F]): F[Unit] = for { _ <- console.println("What is your name?") name <- console.readLine _ <- console.println(s"Hello, $name!") } yield () val consoleForIO = new Console[IO] { def println(msg: String): IO[Unit] = IO(scala.Console.println(msg)) def readLine: IO[String] = IO(scala.io.StdIn.readLine()) } val prog = program(consoleForIO) val r = prog.unsafeRunSync() Tagless Finalの例 抽象操作(Algebra)を型クラスで記述 抽象操作(Algebra)を使用したロジックを記述 抽象操作(Algebra)の型クラスをIOモナドで実現 IOモナドによる抽象操作(Algebra)の型クラスインスタンスによりプログラムを実体化 プログラムの実現・この処理だけ参照透過性の範囲外
  • 45.
    DI (Dependency Injection) •Functional ProgrammingでのDI技術 • 関数単位でDIができるのでTestabilityが向上 • 部分適用 • カリー化するとより意図が明確になる • 暗黙パラメタ • Environment, Configuration, Execution ContextをDI • Readerモナド/ReaderTモナド・トランスフォーマ • ReaderWriterState/ReaderWriterStateT • Environment, Configuration, Execution ContextをDI • モナド・トランスフォーマ • Effect • Tagless Final • Effect polymorphism • EffectをDI • 非同期、並列、並行、分散
  • 46.
  • 47.
    まとめ • ケーススタディ • ブック・カフェPierisBooksの販売システム • プラクティス/アクティビティ • Use case lite : Test a Use-case slice • User Environment Lite : Evolve Documents • CI/CD Pipeline : Ensure CI/CD Pipeline to Test • Testable • 仕様とテストの融合 • FP (Functional Programming)
  • 48.
    参考文献 • The UnifiedModeling Language Reference Manual, 2nd (Rumbaugh他, 2004) • The Unified Modeling Language User Guide, 2nd (Booch他, 2004) • The Unified Software Development Process (Jacobson他, 1999) • The Object Constraint Language, 2nd (Warmer他, 2003) • UML 2 and the Unified Process: Practical Object-Oriented Analysis and Design (Arlow他, 2005) • OMG Unified Modeling Language Version 2.5 (OMG, 2015) • 上流工程UMLモデリング (浅海, 2008) • The Essentials of Modern Software Engineering: Free the Practices from the Method Prisons! (Jacobson他, 2019) • ソフトウェア・テストの技法 第2版 (マイヤーズ他, 2006) • 【この1冊でよくわかる】ソフトウェアテストの教科書 [増補改訂 第2版](布施 他, 2021) • 知識ゼロから学ぶソフトウェアテスト 第3版 アジャイ ル・AI時代の必携教科書 (高橋, 2023) • ソフトウェア品質を高める開発者テスト 改訂版 アジャ イル時代の実践的・効率的でスムーズなテストのやり方 (高橋, 2022) • Extreme Programming Explained: Embrace Change 2nd (Beck, 2004) • Specification by Example: How Successful Teams Deliver the Right Software (Adzic, 2011) • BDD in Action: Behavior-Driven Development for the whole software lifecycle (Smart, 2014)