QC_Rules / tests /test_barcode.py
Jakecole1's picture
Upload 14 files
505d5db verified
import unittest
import cv2
import numpy as np
from PIL import Image
import os
from typing import Dict, Any, Optional, TypedDict, List, Tuple, cast
from src.utils.barcode import Barcode
class BarcodeResult(TypedDict):
type: str
data: str
valid: bool
class TestBarcode(unittest.TestCase):
def setUp(self):
self.barcode = Barcode()
# Create test directory if it doesn't exist
self.test_dir = os.path.dirname(os.path.abspath(__file__))
self.test_images_dir = os.path.join(self.test_dir, 'test_images')
os.makedirs(self.test_images_dir, exist_ok=True)
def test_validate_barcode(self):
"""Test barcode validation for different formats"""
# Test valid EAN-13
self.assertTrue(self.barcode.validate_barcode('5901234123457', 'EAN13'))
# Test invalid EAN-13
self.assertFalse(self.barcode.validate_barcode('5901234123458', 'EAN13'))
# Test valid EAN-8
self.assertTrue(self.barcode.validate_barcode('40170725', 'EAN8'))
# Test invalid EAN-8
self.assertFalse(self.barcode.validate_barcode('40170726', 'EAN8'))
# Test valid UPC-A
self.assertTrue(self.barcode.validate_barcode('042100005264', 'UPCA'))
# Test invalid UPC-A
self.assertFalse(self.barcode.validate_barcode('042100005265', 'UPCA'))
def test_scan_and_validate_from_pil(self):
"""Test barcode scanning from PIL Image"""
# Create a simple test image with a barcode
# This is a placeholder - you should replace with actual barcode images
test_image_path = os.path.join(self.test_images_dir, 'test_barcode.png')
if not os.path.exists(test_image_path):
# Create a blank image if test image doesn't exist
img = Image.new('RGB', (400, 200), color='white')
img.save(test_image_path)
# Load test image
image = Image.open(test_image_path)
# Test scanning
results = self.barcode.scan_and_validate(image)
# Basic structure test
self.assertIsInstance(results, list)
# If a barcode is found, verify the result structure
for result in results:
typed_result = cast(BarcodeResult, result)
self.assertIsInstance(result, dict)
self.assertTrue(all(key in result for key in ['type', 'data', 'valid']))
self.assertIsInstance(typed_result['type'], str)
self.assertIsInstance(typed_result['data'], str)
self.assertIsInstance(typed_result['valid'], bool)
def test_scan_and_validate_from_cv2(self):
"""Test barcode scanning from OpenCV image"""
# Create a test image using OpenCV
test_image_path = os.path.join(self.test_images_dir, 'test_barcode_cv2.png')
if not os.path.exists(test_image_path):
# Create a blank image if test image doesn't exist
img = np.full((200, 400, 3), 255, dtype=np.uint8) # White background
cv2.imwrite(test_image_path, img)
# Load test image
image = cv2.imread(test_image_path)
# Test scanning with show_image=True
scan_result = self.barcode.scan_and_validate(image, show_image=True)
self.assertIsInstance(scan_result, tuple)
results, annotated_image = scan_result
# Verify results
self.assertIsInstance(results, list)
self.assertIsInstance(annotated_image, np.ndarray)
# Check if the annotated image has the same dimensions as input
self.assertEqual(annotated_image.shape, image.shape)
def test_error_handling(self):
"""Test error handling for invalid inputs"""
# Test with None - should raise an exception
with self.assertRaises(Exception):
self.barcode.scan_and_validate(None) # type: ignore
# Test with invalid image type - should raise an exception
with self.assertRaises(Exception):
self.barcode.scan_and_validate("not an image") # type: ignore
# Test empty strings are always invalid
self.assertFalse(self.barcode.validate_barcode("", "EAN13"))
self.assertFalse(self.barcode.validate_barcode("", "UNKNOWN"))
# Test validation with unknown format
# For unknown formats, we validate against known formats first
self.assertFalse(self.barcode.validate_barcode("invalid", "UNKNOWN")) # Invalid data structure
self.assertFalse(self.barcode.validate_barcode("12345678", "UNKNOWN")) # Valid structure but not a valid barcode
self.assertTrue(self.barcode.validate_barcode("5901234123457", "UNKNOWN")) # Valid EAN13 structure
if __name__ == '__main__':
unittest.main()