91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
"""
|
|
Unit and Integration Test Suite
|
|
Validates InventoryManager, ShelfProductDetector, ProductFeatureMatcher, and Pipeline.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import cv2
|
|
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
if current_dir not in sys.path:
|
|
sys.path.insert(0, current_dir)
|
|
|
|
from inventory import InventoryManager
|
|
from feature_matcher import ProductFeatureMatcher
|
|
from detector import ShelfProductDetector
|
|
from pipeline import ShelfRecognitionPipeline
|
|
|
|
|
|
def test_inventory():
|
|
print("[TEST] Testing InventoryManager...")
|
|
inv = InventoryManager("stock")
|
|
assert len(inv.products) >= 10, f"Expected products >= 10 in stock.csv, found {len(inv.products)}"
|
|
p1 = inv.get_product("sku_001")
|
|
assert p1 is not None, "sku_001 not found"
|
|
assert p1["product_name"] == "明治 おいしい牛乳"
|
|
assert p1["price"] == 258.0
|
|
assert p1["number_on"] == 73
|
|
print(" -> InventoryManager test: PASSED")
|
|
|
|
|
|
def test_feature_matcher():
|
|
print("[TEST] Testing ProductFeatureMatcher...")
|
|
matcher = ProductFeatureMatcher("stock")
|
|
assert len(matcher.db.templates) >= 7, f"Expected templates >= 7, got {len(matcher.db.templates)}"
|
|
|
|
for method in ["hybrid", "orb", "brisk"]:
|
|
tmpl_img = matcher.db.templates["sku_001"]["image"]
|
|
res = matcher.classify_crop(tmpl_img, method=method)
|
|
assert res["status"] == "success", f"Method {method} failed"
|
|
assert res["best_sku"] == "sku_001", f"Expected sku_001 with {method}, got {res['best_sku']}"
|
|
print(f" -> {method.upper()} classification test: PASSED (Score: {res['score']}, Conf: {res['confidence']})")
|
|
|
|
|
|
def test_detector():
|
|
print("[TEST] Testing ShelfProductDetector...")
|
|
detector = ShelfProductDetector("runs/detect/train/weights/best.pt")
|
|
sample_shelf = "runs/detect/train/train_batch0.jpg"
|
|
res = detector.detect(sample_shelf)
|
|
assert res["status"] == "success", "Detection failed"
|
|
assert res["total_detected"] > 0, "No boxes detected"
|
|
print(f" -> Detector test: PASSED ({res['total_detected']} items localized)")
|
|
|
|
first_box = res["boxes"][0]
|
|
cx, cy = first_box["center"]
|
|
hit = detector.find_box_at_point(cx, cy, res["boxes"])
|
|
assert hit is not None, "Hit test failed on center coordinate"
|
|
assert hit["id"] == first_box["id"], "Hit test returned incorrect box"
|
|
print(" -> Spatial hit-test: PASSED")
|
|
|
|
|
|
def test_pipeline():
|
|
print("[TEST] Testing End-to-End Pipeline...")
|
|
pipeline = ShelfRecognitionPipeline(
|
|
weights_path="runs/detect/train/weights/best.pt",
|
|
stock_dir="stock"
|
|
)
|
|
init_res = pipeline.set_active_shelf_image("runs/detect/train/train_batch0.jpg")
|
|
assert init_res["status"] == "success"
|
|
assert len(init_res["boxes"]) > 0
|
|
|
|
first_box = init_res["boxes"][0]
|
|
cx, cy = first_box["center"]
|
|
click_res = pipeline.process_click(cx, cy, method="hybrid")
|
|
assert click_res["status"] == "success", f"Click processing failed: {click_res.get('message')}"
|
|
assert "inventory" in click_res
|
|
assert click_res["inventory"] is not None
|
|
print(f" -> End-to-End Pipeline test: PASSED (Matched: {click_res['classification']['matched_sku']} - {click_res['inventory']['product_name']})")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 60)
|
|
print("STARTING TEST SUITE")
|
|
print("=" * 60)
|
|
test_inventory()
|
|
test_feature_matcher()
|
|
test_detector()
|
|
test_pipeline()
|
|
print("=" * 60)
|
|
print("ALL TESTS PASSED SUCCESSFULLY!")
|
|
print("=" * 60)
|