File size: 4,952 Bytes
505d5db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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()