はじめに
本業でトラックドライバーとして働きながら、Python / Flaskを中心にWebアプリケーションを個人開発している tosane932 です。
2026年5月から開発を続けている Bakery Hub は、商品登録、売上分析、材料発注、店舗メモ、タスク管理、Guest Demoなどを備えたWebアプリケーションです。
AIを活用しながら開発を続ける中で機能が増え、以前に実装した処理の詳細を調べ直す機会も増えてきました。
そこで、Bakery Hub自体に、PythonやWeb開発の仕組みを復習できる「システム概要」を追加しました。
今回の記事では、学習ページが必要になった背景よりも、どのように設計・実装し、pytestで何を検証しているのかを中心に紹介します。
主に扱う技術は次のとおりです。
| 技術 | 今回の用途 |
|---|---|
| Python / Flask | 学習ページの公開・処理フローの解説 |
| Jinja / HTML | 教材の共通化・開閉表示 |
| SQLAlchemy | 実際のDB操作を教材化 |
| Python AST | 関数・クラスの定義位置を解析 |
| pytest | 教材と実装の整合性検証 |
| JavaScript | 現在地表示・章移動 |
| GitHub / AGENTS.md | 実コードへの導線・教材の更新運用 |
1. READMEとは別に、実装を学ぶページを設計する
最初に整理したのは、READMEとの役割分担です。
Bakery Hubには、すでに機能や技術構成を説明するREADMEがあります。
しかし、READMEに「SQLAlchemyを使用」と書いてあっても、どの機能でどのように使用しているかまでは、すぐに理解できません。
そこで、役割を分けました。
| 比較項目 | README | システム概要 |
|---|---|---|
| 主な目的 | アプリの紹介 | 実装の理解・復習 |
| 機能説明 | 何ができるか | どう動いているか |
| Python | 使用技術として紹介 | 構文・用途・使用箇所 |
| Flask | フレームワークを紹介 | route・request・response |
| SQLAlchemy | DB構成を紹介 | Model・query・transaction |
| pytest | テスト方針・結果 | 何を検証しているか |
| コードへの導線 | リポジトリ全体 | ファイル・関数・該当行 |
システム概要は、READMEを置き換えるものではありません。
READMEでアプリを知り、システム概要で実装を理解し、GitHubで実コードを読む。
この流れを作ることが目的です。
公開ページはGET専用にする
Flask側では、app.py に次のrouteを追加しました。
@app.get("/system-overview")
def system_overview():
"""実装を復習するための公開ページ。業務データは取得しない。"""
return render_template("system_overview.html")
処理はシンプルです。
GET /system-overview にアクセスすると、学習用テンプレートを返します。
ここで意識したのは、学習ページの表示に業務データを必要としないことです。
| 設計項目 | 方針 |
|---|---|
| URL | /system-overview |
| HTTPメソッド | GET |
| 認証 | 不要 |
| 業務データ取得 | 行わない |
| DB更新 | 行わない |
| AI API呼び出し | 行わない |
| 表示内容 | 実装済み機能の説明 |
売上や店舗メモのような業務データを表示するページではないため、Dataset取得やDBへの問い合わせを行わない構成にしました。
また、Dashboardなどの既存画面に学習コンテンツを混ぜるのではなく、独立したページとして追加しました。
これにより、通常の業務操作を妨げずに学習機能を提供できます。
関連PR: #72|学習用の公開「システム概要」を追加
2. 9章構成とJinjaのmacroで教材を整理する
システム概要は、現在9章で構成しています。
9章の構成
| 章 | 内容 | 学習の目的 |
|---|---|---|
| 1 | Bakery Hub全体の流れ | Webアプリの処理を把握する |
| 2 | 1つの処理を最後まで追ってみる | HTTPからDBまでの関係を理解する |
| 3 | メニュー・機能別の仕組み | 各機能の実装を調べる |
| 4 | Python基礎・応用マップ | Pythonの使用箇所を学ぶ |
| 5 | 共通技術と役割 | 技術同士の関係を理解する |
| 6 | テストは何を壊さないためにある? | pytestの目的を理解する |
| 7 | 理解度チェック | Web開発の知識を確認する |
| 8 | Python基礎チェック | Pythonの理解を確認する |
| 9 | 困ったときはどこを見る? | 不具合の調査場所を探す |
ここで工夫したのは、情報を増やすだけでなく、同じHTMLを繰り返し書かなくて済むようにすることです。
Jinjaのmacroで説明カードを共通化
実際の system_overview.html では、機能を説明するカードをJinjaの macro で定義しています。
{% macro feature(id, title, role, routes) -%}
<article class="overview-card" id="feature-{{ id }}">
<h3>{{ title }}</h3>
<p>{{ role }}</p>
<p class="overview-route">
<span>主なURL</span>
<code>{{ routes }}</code>
</p>
<details>
<summary>仕組みと確認コードを読む</summary>
<dl class="overview-description">{{ caller() }}</dl>
</details>
</article>
{%- endmacro %}
macro は、Jinjaテンプレート内で再利用できる部品を定義する仕組みです。
今回の構成では、次の情報を受け取ります。
| 引数 | 役割 |
|---|---|
id |
カードを識別するID |
title |
機能名 |
role |
機能の概要 |
routes |
主なURL |
caller() |
機能ごとの詳しい説明 |
外側のカード構造を共通化し、詳しい説明だけを機能ごとに変更できるようにしました。
detailsで必要な情報だけ開く
説明コンテンツには、HTML標準の details / summary を利用しています。
<details>
<summary>仕組みと確認コードを読む</summary>
<p>ここに詳しい説明を表示します。</p>
</details>
これなら、開閉処理のためにJavaScriptを追加する必要がありません。
| 課題 | 対応 |
|---|---|
| HTMLの重複 | Jinja macroで共通化 |
| 見出しの階層がばらつく | 共通構造で統一 |
| 説明が長くなる | detailsで開閉 |
| 必要な情報を探しにくい | 章と機能IDを使用 |
| 表示構造を変更したい | 共通部品を修正 |
今回は、同じ形式の説明カードが複数あるため、macroによる共通化が有効だと判断しました。
3. 実際の売上処理を6段階で追える教材にする
次に追加したのが、1つの処理を最初から最後まで追う学習機能です。
題材にしたのは、Bakery Hubの日次売上入力です。
例えば、次の販売数量を保存する場面を考えます。
| 商品 | 販売数量 |
|---|---|
| クロワッサン | 10個 |
| 食パン | 15個 |
| メロンパン | 20個 |
利用者から見える操作は、数量を入力して保存ボタンを押すだけです。
しかし、内部では複数の処理が動いています。
売上入力からDashboardまでの処理
① GET /input
売上入力画面を開く
↓
② POST /input
日付・商品ID・数量を送信
↓
③ Flask / Python
入力内容とDatasetを検証
↓
④ SQLAlchemy / PostgreSQL
売上データを保存・確定
↓
⑤ Flask / Jinja
保存結果を画面に表示
↓
⑥ GET /dashboard
売上を集計・表示
実際のシステム概要では、それぞれの段階を開いて詳しく確認できます。
Flaskがリクエストを受け取る
売上入力は、app.py の input_sales() が担当しています。
@app.route("/input", methods=["GET", "POST"])
@admin_or_guest_required
def input_sales():
today = business_today()
current_dataset = require_current_dataset()
ここだけでも、複数の技術が使われています。
| コード | 役割 |
|---|---|
@app.route() |
URLと関数を結びつける |
methods |
GET・POSTを受け付ける |
@admin_or_guest_required |
アクセス権限を確認 |
def |
関数を定義 |
business_today() |
日本時間の営業日を取得 |
require_current_dataset() |
利用者のデータ領域を取得 |
Pythonの基礎学習では、これらを個別に覚えることが多いです。
しかし、実際のFlaskアプリでは、一つの処理の中で組み合わされています。
フォームの値を受け取り、検証する
売上フォームから送信された複数の商品IDと数量は、次のように取得します。
product_ids = request.form.getlist("product_id")
quantities = request.form.getlist("quantity")
その後、商品IDと数量の件数が一致しているかを確認します。
実際のコードです。
if len(product_ids) != len(quantities):
logger.warning(
"Mismatched sales input lengths rejected: "
f"product_ids={len(product_ids)}, "
f"quantities={len(quantities)}"
)
return "商品と販売数量の件数が一致しません。", 400
なぜ、この検証が必要なのでしょうか。
その後の処理で、zip() を使用しているからです。
for product_id, quantity in zip(product_ids, quantities):
Pythonの zip() は、通常、短い方のデータが終わった時点で繰り返しを終了します。
例えば、商品IDが3件、数量が2件だった場合、何も確認せずに zip() を使用すると3件目が処理されません。
そこで、事前に len() で件数一致を確認しています。
| Pythonの要素 | 実際の役割 |
|---|---|
request.form.getlist() |
フォームの複数値を取得 |
len() |
件数を確認 |
if |
不正な入力を判定 |
return |
不正な場合に処理を終了 |
zip() |
商品IDと数量を組み合わせる |
for |
各商品を繰り返し検証 |
set() |
商品IDの重複を確認 |
このように、Pythonの構文が何のために使われているのかまで説明することを意識しました。
SQLAlchemyのtransactionを理解する
売上データは、SQLAlchemyを通してDBへ保存します。
ここで重要になるのが次の処理です。
| 処理 | 役割 |
|---|---|
db.session.execute() |
SQLステートメントを実行 |
db.session.commit() |
transactionを確定 |
db.session.rollback() |
transactionを取り消す |
複数商品の売上を保存する場合、途中でDBエラーが発生したときに、一部の変更だけが残る状態は避けたいところです。
そのため、正常に保存できた場合だけでなく、失敗した場合の処理も説明しています。
なお、現在の実装では売上保存後にDashboardへ自動リダイレクトするわけではありません。
入力画面に成功結果を表示し、利用者がDashboardへのリンクを開くと、新しいGETリクエストで集計が行われます。
この実際の画面遷移も教材へ反映しています。
関連コード: app.py|売上入力処理
関連PR: #73|処理フロー・理解度チェック・逆引きの追加
4. Python基礎を17カテゴリ・37使用例に整理する
今回の学習ページで、特に拡張したかった部分です。
最初は各機能と技術の関係を説明していましたが、それだけでは特定のPython構文を学び直すには不十分でした。
例えば、
enumerate()はどの機能で使用している?
yieldは実際にどう使われている?
Noneは何を表している?
といった疑問から、直接コードへ辿れるようにしたかったからです。
そこで、Bakery Hubで実際に使用しているPythonの要素を、17カテゴリ・37の使用例に整理しました。
Python基礎・応用マップ
| カテゴリ | 主な学習内容 |
|---|---|
| 値・型・基本演算 |
int、str、比較演算 |
| 条件分岐 |
if、elif、else
|
| 繰り返し |
for、while
|
| データ構造 |
list、dict、set
|
| 関数 |
def、return
|
| クラス・オブジェクト |
class、Model |
| 例外処理 |
try、except
|
| 反復・データ処理 |
enumerate()、zip()、sorted()
|
| 文字列処理 | 文字列の加工 |
| 型と状態の確認 |
None、型ヒント |
| モジュール・import | import |
| 標準ライブラリ | Python標準の機能 |
| 正規表現 | re |
| ファイルとパス | pathlib |
| コンテキスト管理 |
with、yield
|
| デコレータ |
@ を使った処理 |
| 日付と時間 | datetime |
各学習項目には、4つの情報を用意しています。
| 項目 | 内容 |
|---|---|
| これは何か | 構文や関数の意味 |
| Bakery Hubでは | 使用している機能 |
| なぜ使うか | 実装上の目的 |
| 教材の住所 | ファイル・関数・GitHubリンク |
Jinjaで実コードへのリンクを生成する
Python基礎・応用マップでは、python_lesson というmacroを利用しています。
実際のテンプレートの一部です。
{% macro python_lesson(
id, title, meaning, use, reason,
locations, feature_id, feature_label, snippet=''
) -%}
<section class="python-lesson" id="python-{{ id }}">
<h4>{{ title }}</h4>
<dl class="overview-description">
<dt>これは何か</dt>
<dd>{{ meaning }}</dd>
<dt>Bakery Hubでは</dt>
<dd>
{{ use }}
<a href="#feature-{{ feature_id }}">
{{ feature_label }}の仕組み
</a>
</dd>
<dt>なぜ使うか</dt>
<dd>{{ reason }}</dd>
※macroの前半部分を抜粋しています。
ここでは、学習項目の意味、用途、理由、関連機能などを表示しています。
さらに、教材の住所としてGitHubへのリンクを生成します。
<a
data-code-address
data-source-file="{{ path }}"
data-source-symbol="{{ symbol }}"
data-source-scope="{{ scope }}"
href="https://github.com/tosane932/tosane-works/blob/main/store/bakery-hub/{{ path }}#L{{ line }}"
>
<code>{{ path }}</code> → <code>{{ symbol }}</code>
</a>
このリンクには、次の情報を含めています。
| 情報 | 目的 |
|---|---|
path |
対象ファイル |
symbol |
関数・クラス |
line |
定義の行番号 |
scope |
業務処理・テストなどの分類 |
これにより、次のような学習ができます。
Python基礎・応用マップ
↓
学習したい構文を選ぶ
↓
意味・用途・理由を確認
↓
ファイルと関数名を確認
↓
GitHubの実コードを開く
関連PR: #83|Python基礎・応用17カテゴリへの拡張
5. ASTとpytestでコードリンクの整合性を検証する
今回の実装で、特に技術的に重視した部分です。
学習ページには、GitHubの実コードへのリンクがあります。
しかし、コードを変更すると関数の行番号が変わる可能性があります。
例えば、ある関数が100行目から120行目へ移動した場合です。
教材のリンク:app.py#L100
実際の定義 :app.py#L120
↓
不一致
ファイル自体が存在していても、意図したコードへ移動できなくなります。
そこで、PythonのASTを利用して、教材の参照先と実際の関数・クラス定義を照合するpytestを追加しました。
ASTとは?
ASTは Abstract Syntax Tree(抽象構文木)の略です。
Pythonのソースコードを構文として解析し、関数定義やクラス定義などの構造を調べられます。
例えば、次のコードがあるとします。
def calculate_total(price, quantity):
return price * quantity
ASTを利用すると、calculate_total という関数が存在することや、その定義開始行を取得できます。
実際のpytest
Bakery Hubでは、次のテストを用意しています。
def test_python_code_links_resolve_to_existing_files_definitions_and_lines(
client,
):
テストの一部です。
document = _document(client.get("/system-overview"))
app_root = Path(app_module.__file__).parent.resolve()
links = document.select("#basics a[data-code-address]")
まず、学習ページを取得し、コードリンクを抽出します。
次に、リンクに記載したファイルや関数を確認します。
path = (app_root / link["data-source-file"]).resolve()
assert path.is_relative_to(app_root)
assert path.is_file()
source = path.read_text(encoding="utf-8")
definition = _source_definitions(source)[link["data-source-symbol"]]
この検証で確認している内容は次のとおりです。
| 検証対象 | 確認内容 |
|---|---|
| パス | アプリのルート内にあるか |
| ファイル | 実際に存在するか |
| 関数・クラス | 指定した定義が存在するか |
| GitHub URL | 正しいリポジトリを指すか |
| 行番号 | 実際の定義開始行と一致するか |
| 使用場所 | 業務処理・テストなどの分類があるか |
さらに、行番号を照合します。
assert url.fragment == f"L{definition.lineno}"
definition.lineno は、ASTから取得した実際の定義開始行です。
教材に記載したリンクの行番号と一致するかを確認しています。
なぜこのテストが必要なのか
例えば、app.py の途中にコードを追加した結果、ある関数の定義位置が変わったとします。
その際、教材内の行番号を更新し忘れる可能性があります。
ファイル自体は存在するため、単純なファイル存在確認では問題を検出できません。
しかし、ASTで定義位置を取得すれば、行番号の不一致を検出できます。
短いコード抜粋も検証する
Python基礎・応用マップでは、一部の項目に短い実コードを掲載しています。
この抜粋についても、ast.get_source_segment() を利用して、実際のソースコードに含まれていることを確認しています。
学習用の説明と実コードの差を小さくするためのテストです。
関連コード: test_system_overview.py|コードリンクの検証
6. 公開ページがDBやAIを呼び出さないこともテストする
システム概要はログイン不要で閲覧できる公開ページです。
そのため、表示に成功することだけでなく、不要な業務処理が実行されないことも確認しています。
実際のテストは次の関数です。
def test_anonymous_overview_is_public_without_database_or_ai_calls(
client, monkeypatch,
):
このテストでは、呼び出してほしくない処理を、テスト中だけ失敗する関数に置き換えています。
def unexpected_call(*args, **kwargs):
pytest.fail(
"The public overview must not query business data or call AI"
)
monkeypatch.setattr(
app_module,
"require_current_dataset",
unexpected_call,
)
monkeypatch.setattr(
app_module.genai,
"Client",
unexpected_call,
)
monkeypatch は、テスト中に関数や属性を一時的に差し替えるためのpytestの機能です。
さらに、SQLAlchemyの before_cursor_execute イベントを使用して、SQLの実行も監視しています。
これにより、表示時に不要なDBアクセスが発生した場合はテストが失敗します。
検証内容
| 対象 | 期待する結果 |
|---|---|
| 未ログイン閲覧 | 200で表示 |
| Dataset取得 | 呼び出されない |
| AIクライアント生成 | 呼び出されない |
| SQL実行 | 発生しない |
| 管理者用表示 | 未ログイン時に表示しない |
| POST | 405で拒否 |
このように、「正常に表示されること」と「不要な処理が行われないこと」を分けて検証しています。
関連コード: test_system_overview.py|公開ページの検証
7. 理解度チェック23問とトラブル逆引き8項目を追加する
説明を読むだけでは、本当に理解できたのか分からないこともあります。
そこで、2種類の理解度チェックを追加しました。
理解度チェック
| 種類 | 問題数 | 主な対象 |
|---|---|---|
| Webアプリ理解度チェック | 8問 | Flask・DB・認証・画面処理 |
| Python基礎チェック | 15問 | 構文・関数・データ構造 |
| 合計 | 23問 |
例えば、次のような問題があります。
Q. 認証のSessionと、SQLAlchemyの
db.sessionは同じもの?
どちらにも session という名前がありますが、役割は異なります。
| 項目 | 役割 |
|---|---|
| 認証のSession | 利用者の認証状態などを管理 |
db.session |
DB操作やtransactionを管理 |
ほかにも、
Q.
zip()の前に商品IDと数量の件数を確認するのはなぜ?
Q.
try / exceptでDBエラーを捕まえた後、rollbackするのはなぜ?
Q. 型ヒントを付ければ、不正な型を実行時に自動で拒否できる?
といった問題を用意しています。
答えは初期状態では表示せず、HTML標準の details / summary で開ける形式です。
<details>
<summary>答えを見る</summary>
<p>ここに解説を表示します。</p>
</details>
※上記は仕組みを説明するための簡略例です。
実際のページでは、解説から関連する学習項目へ移動できるようにしています。
トラブル逆引き
不具合が起きたときに、症状から確認場所を探せるようにもしました。
| 現象 | 最初に確認する場所 |
|---|---|
| ボタンが反応しない | HTML / JavaScript / route |
| POSTで400になる | CSRF / 入力検証 |
| 保存できない | validation / transaction |
| DBにあるのに表示されない | query / 表示条件 |
| 日付がおかしい | business_today() |
| Guestのデータが混ざる | Dataset / 権限 |
| 並び順がおかしい | sort / 保存順 |
| pytestだけ失敗する | fixture / テスト環境 |
例えばボタンが反応しない場合です。
ボタンを押しても反応しない
↓
Networkを確認
↓
リクエストは送信された?
↓
YES NO
↓ ↓
Flaskのroute HTML / JavaScript
レスポンス Consoleエラー
HTTPステータス フォーム制限
原因を決めつけず、確認する場所を絞り込むための入口です。
8. 長い教材を読むためのJavaScriptを追加する
Pythonの教材を追加し、全9章構成にしたことで、ページの情報量が増えました。
すると今度は、現在どの章を読んでいるのか分かりにくくなります。
そこで、章の現在地を表示するバーと目次を追加しました。
章の現在地を判定する
各章には、次のような属性を付けています。
<section
class="overview-section"
id="flow"
data-overview-chapter="1"
>
JavaScript側では、章の要素を取得します。
const chapters = [
...document.querySelectorAll(
"main > [data-overview-chapter]"
)
];
この情報をもとに現在の章を判定し、表示を更新します。
実際の setCurrent() の一部です。
function setCurrent(index) {
currentIndex = index;
label.textContent = links[index].textContent;
links.forEach((link, i) => {
if (i === index) {
link.setAttribute("aria-current", "location");
} else {
link.removeAttribute("aria-current");
}
});
※関数の前半部分を抜粋しています。
aria-current="location" は、現在の位置に対応するリンクを示す属性です。
JavaScriptが使えなくても読めるようにする
今回のページでは、JavaScriptが無効な場合でも通常の目次が使えるようにしました。
| 状態 | 利用できる機能 |
|---|---|
| JavaScript有効 | 現在地表示・開閉目次・章移動 |
| JavaScript無効 | 通常の目次・アンカー移動 |
| 対応するモバイル環境 | 章スクラバー |
| 動きを減らす設定 | アニメーションを抑制 |
必要な情報は最初からHTMLとして用意し、JavaScriptは閲覧体験を改善するために追加しています。
これは Progressive Enhancement(段階的な機能拡張) の考え方です。
スマートフォン向けの章スクラバー
長いページを移動しやすくするため、対応するモバイル環境では章スクラバーも利用できるようにしました。
| 項目 | 設計 |
|---|---|
| 表示 | スクロール中 |
| 自動非表示 | 停止後、約1.6秒 |
| 操作領域 | 44px |
| 章移動 | ドラッグ操作 |
| 代替手段 | 通常の目次 |
| JavaScript無効時 | 通常の目次を維持 |
ただし、pytestやブラウザの自動操作だけで、すべての実機操作を保証できるわけではありません。
AndroidやiOSでは、アドレスバーやタッチ操作による違いも考慮する必要があります。
関連コード: system_overview.js
9. 新機能追加時には教材の更新要否も確認する
学習ページを作っても、アプリ本体だけが更新され続ければ、説明が古くなります。
特に今回は、関数や行番号までリンクしています。
そのため、コード変更後も説明が正しい状態を維持する必要があります。
そこで、AGENTS.md にシステム概要の更新ルールを追加しました。
更新ルール
| 変更内容 | システム概要の扱い |
|---|---|
| 新機能の追加 | 反映の必要性を確認 |
| 主要な仕様変更 | 関連する説明を更新 |
| 処理フロー変更 | 実コードに合わせて更新 |
| 使用技術の変更 | 技術説明を確認 |
| 軽微な文言修正 | 必要な場合だけ更新 |
| 見た目のみの変更 | 学習内容への影響を確認 |
このルールは教材を自動生成する仕組みではありません。
AIを活用して開発する場合も、実際のコードとテストを確認して説明を更新するための運用ルールです。
機能追加・仕様変更
↓
実装・テストを確認
↓
システム概要への反映要否を判断
↓
必要なら教材を更新
↓
整合性を確認
また、学習内容に影響しない小さな見た目の変更まで、無理に追記しないことにしています。
関連PR: #74|AGENTS.mdに更新ルールを追加
10. 実装と検証の結果
今回のシステム概要は、最初からすべての機能を一度に実装したわけではありません。
公開ページを作り、必要な学習機能を段階的に追加してきました。
開発の流れ
| 段階 | 主な実装内容 |
|---|---|
| 初期実装 | 公開システム概要・機能説明 |
| 教材拡張 | 処理フロー・理解度チェック・逆引き |
| 更新運用 | AGENTS.mdの更新ルール |
| Python教材 | 17カテゴリ・37使用例・15問 |
| 閲覧UI | 章番号・現在地バー・開閉目次 |
| 操作性改善 | 章スクラバー・モバイルナビ |
最終的な教材構成
| 項目 | 内容 |
|---|---|
| 章構成 | 9章 |
| 主要機能の解説 | 10機能 |
| 処理フロー | 売上入力からDashboardまで6段階 |
| Python基礎・応用 | 17カテゴリ・37使用例 |
| 理解度チェック | 23問 |
| トラブル逆引き | 8項目 |
| 実コード連携 | GitHubのファイル・関数・行番号 |
| 品質確認 | 専用pytest |
| 更新運用 | AGENTS.md |
PR #83時点のテスト結果
Python基礎・応用マップを追加した際には、次の結果を確認しています。
| 検証対象 | 結果 |
|---|---|
| システム概要専用pytest | 43 passed |
| 全pytest | 1,014 passed |
| skipped | 18 |
| warnings | 9 |
※上記はPR #83時点の結果であり、現在の最新テスト件数ではありません。ローカル環境では、PostgreSQLなどの環境依存テストがskipされています。
この時点で、教材そのものにも専用のテストを追加し、ページの構造や実コードへの参照を継続的に確認できるようになりました。
おわりに
今回のシステム概要は、単に技術名をまとめたページではありません。
実際に動いているFlaskアプリを、
機能を知る
↓
処理の流れを理解する
↓
Pythonの構文を確認する
↓
GitHubの実コードを読む
↓
pytestで何を確認しているか調べる
という流れで学び直すためのページです。
今回、特に重視したのは次の3点です。
1. 説明と実装を結びつけること
どのファイル・関数で使われているかまで辿れるようにしました。
2. 学習用ページもテスト対象にすること
公開ページの表示だけでなく、コードリンクや教材構造の整合性も検証しています。
3. 今後も正しい情報を維持すること
機能追加や主要な仕様変更の際には、教材の更新要否も確認するルールを作りました。
もちろん、学習ページを完成させただけで、自分がすべてのコードを理解できるようになったわけではありません。
これからは、実際のコードを読み、動作を予測し、なぜその結果になるのかを自分の言葉で説明できるようにしていきたいと思います。
AIを活用して作ったシステムを、今度は自分自身の学習教材として活用する。
Bakery Hubを「作って終わりのポートフォリオ」ではなく、学び続けるための場所にもしていきたいと思います。
🔗 関連リンク
Bakery Hubの実装、開発PR、過去の技術記事をまとめました。
| 分類 | 内容 | リンク |
|---|---|---|
| 🌐 Live Demo | Bakery Hub | アプリを体験する |
| 📘 学習ページ | 公開システム概要 | 実際の教材を読む |
| 💻 GitHub | Tosane Works | リポジトリ |
| 💻 GitHub | Bakery Hub | ソースコード |
| 📄 README | Bakery Hubの機能・仕様 | README.md |
| 🐍 Flask | システム概要のroute・業務処理 | app.py |
| 📖 Jinja | システム概要テンプレート | system_overview.html |
| 🎨 JavaScript | 章ナビゲーション・現在地表示 | system_overview.js |
| 🧪 pytest | システム概要専用テスト | test_system_overview.py |
| 📄 運用 | システム概要の更新ルール | AGENTS.md |
| 🔀 PR #72 | 公開システム概要の初期実装 | Pull Request |
| 🔀 PR #73 | 処理フロー・理解度チェック・逆引き | Pull Request |
| 🔀 PR #74 | AGENTS.mdの更新ルール | Pull Request |
| 🔀 PR #83 | Python基礎・応用教材への拡張 | Pull Request |
| 🔀 PR #84 | 章番号・現在地バー・目次 | Pull Request |
| 🔀 PR #85 | 目次改善・章スクラバー試作 | Pull Request |
| 🔀 PR #86 | 章スクラバーの通常利用 | Pull Request |
| 🔀 PR #87 | モバイル上部ナビ・スクラバー調整 | Pull Request |
| 🔀 PR #88 | モバイル上部ナビの安定化 | Pull Request |
| 🔀 PR #89 | スクロール判定・章バーの調整 | Pull Request |
| 📰 Qiita | 商品管理の再設計 | 18商品テンプレート・履歴Catalog・Admin登録 |
| 📰 Qiita | Mutation Testing | pytestが通るだけでは安心できない |
| 📰 Qiita | pytest再監査 | 1,286件のMutation Testing |
| 📰 Qiita | UI/UX改善 | 店舗メモツール完成 |
| 📰 Qiita | pytest強化 | pytestを「事故防止台帳」として育てる 第5段階 |
| 📚 Zenn | 個人開発・学習の振り返り | tosane932のプロフィール |
