Skip to main content
テスト
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)