# -*- coding: utf-8 -*-
"""
Test suite for app navigation and annotation logic.
Tests app behavior without running Streamlit.
"""
import pytest
from types import SimpleNamespace
# 簡易的なMockSessionState
# SimpleNamespaceを使うと obj.attr = value のように書けるので便利
class MockState(SimpleNamespace):
pass
def test_navigation_next_unannotated():
"""
【基本動作】保存後、次の未完了症例に進むか
"""
# 状態の準備
state = MockState(
current_case_idx=0,
case_ids=[101, 102, 103],
annotated_cases=set()
)
# 1. 現在の症例(101)を保存したと仮定
current_id = state.case_ids[state.current_case_idx]
state.annotated_cases.add(current_id)
# --- アプリのロジック(簡易再現) ---
next_idx = state.current_case_idx + 1
found = False
while next_idx < len(state.case_ids):
if state.case_ids[next_idx] not in state.annotated_cases:
state.current_case_idx = next_idx
found = True
break
next_idx += 1
# ----------------------------------
# 検証: idxが1(102)に進んでいること
assert found is True
assert state.current_case_idx == 1
assert state.case_ids[state.current_case_idx] == 102
def test_navigation_skip_annotated():
"""
【スキップ動作】完了済み症例を飛ばして、その次の未完了に進むか
"""
# 状態: 101(今), 102(完了済), 103(未完了)
state = MockState(
current_case_idx=0,
case_ids=[101, 102, 103],
annotated_cases={102}
)
# 1. 現在の症例(101)を保存
current_id = state.case_ids[state.current_case_idx]
state.annotated_cases.add(current_id)
# --- アプリのロジック ---
next_idx = state.current_case_idx + 1
found = False
while next_idx < len(state.case_ids):
if state.case_ids[next_idx] not in state.annotated_cases:
state.current_case_idx = next_idx
found = True
break
next_idx += 1
# ---------------------
# 検証: idxが2(103)まで飛んでいること
assert found is True
assert state.current_case_idx == 2
assert state.case_ids[state.current_case_idx] == 103
def test_completion_logic():
"""
【完了判定】全症例終わったら完了フラグが立つか
"""
state = MockState(
case_ids=[101, 102],
annotated_cases={101, 102}
)
# 完了判定ロジック
is_complete = len(state.annotated_cases) >= len(state.case_ids)
assert is_complete is True