backend.tests.unit.components.camera_verification.qrcode.test_qrcode_service
1import pytest 2import numpy as np 3from unittest.mock import patch, MagicMock 4 5from backend.components.camera_verification.qrcode.qrcodeService import ( 6 generate_qr_code, 7 decode_qr_image, 8 MultipleCodesError, 9 NoCodeFoundError 10) 11 12 13# -------------------------------------------------------------------------- 14# Fixtures 15# -------------------------------------------------------------------------- 16 17@pytest.fixture 18def fake_image(): 19 """Tworzy pustą tablicę numpy udającą obraz (dla decode).""" 20 return np.zeros((100, 100, 3), dtype=np.uint8) 21 22 23# -------------------------------------------------------------------------- 24# Testy generate_qr_code 25# -------------------------------------------------------------------------- 26 27@patch('backend.components.camera_verification.qrcode.qrcodeService.encode_image') 28@patch('backend.components.camera_verification.qrcode.qrcodeService.cv2') 29def test_generate_qr_code_success(mock_cv2, mock_encode_image): 30 """ 31 Testuje generowanie kodu QR. 32 Sprawdza, czy wywoływane są odpowiednie metody z biblioteki cv2 oraz funkcja kodująca wynik. 33 """ 34 # Setup 35 secret = "my_secret_code" 36 37 # Mockowanie łańcucha wywołań cv2 38 mock_encoder = MagicMock() 39 mock_cv2.QRCodeEncoder.return_value.create.return_value = mock_encoder 40 41 # Mockowanie wyników operacji na obrazie 42 # encode zwraca surowy obraz QR 43 mock_encoder.encode.return_value = np.zeros((10, 10), dtype=np.uint8) 44 # resize zwraca przeskalowany obraz 45 mock_cv2.resize.return_value = np.zeros((100, 100), dtype=np.uint8) 46 # copyMakeBorder dodaje ramkę 47 mock_cv2.copyMakeBorder.return_value = np.zeros((120, 120), dtype=np.uint8) 48 # threshold zwraca (retval, image) 49 mock_cv2.threshold.return_value = (127, np.zeros((120, 120), dtype=np.uint8)) 50 51 # Mock encode_image (zwraca bytes) 52 expected_bytes = b'fake_png_bytes' 53 mock_encode_image.return_value = expected_bytes 54 55 # Action 56 result = generate_qr_code(secret) 57 58 # Assert 59 assert result == expected_bytes 60 61 # Weryfikacja czy encoder został utworzony i użyty z sekretem 62 mock_cv2.QRCodeEncoder.return_value.create.assert_called_once() 63 mock_encoder.encode.assert_called_once_with(secret) 64 65 # Weryfikacja czy zakodowano ostateczny obraz 66 mock_encode_image.assert_called_once() 67 68 69# -------------------------------------------------------------------------- 70# Testy decode_qr_image 71# -------------------------------------------------------------------------- 72 73@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 74def test_decode_qr_image_success(mock_decode, fake_image): 75 """ 76 Scenariusz pozytywny: Wykryto dokładnie jeden kod QR. 77 """ 78 # Setup 79 mock_qr_obj = MagicMock() 80 mock_qr_obj.data = b"decoded_secret_123" 81 82 # pyzbar.decode zwraca listę znalezionych obiektów 83 mock_decode.return_value = [mock_qr_obj] 84 85 # Action 86 result = decode_qr_image(fake_image) 87 88 # Assert 89 assert result == "decoded_secret_123" 90 mock_decode.assert_called_once_with(fake_image) 91 92 93@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 94def test_decode_qr_image_multiple_codes(mock_decode, fake_image): 95 """ 96 Negative scenario: More than one QR code detected. 97 Expected exception: MultipleCodesError. 98 """ 99 # Setup 100 obj1 = MagicMock() 101 obj1.data = b"code1" 102 obj2 = MagicMock() 103 obj2.data = b"code2" 104 105 mock_decode.return_value = [obj1, obj2] 106 107 # Action & Assert 108 with pytest.raises(MultipleCodesError, match="Wykryto 2 kodów QR"): 109 decode_qr_image(fake_image) 110 111 112@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 113def test_decode_qr_image_no_code_empty_list(mock_decode, fake_image): 114 """ 115 Negative scenario: The library returns an empty list (no codes). 116 Expected exception: NoCodeFoundError. 117 """ 118 # Setup 119 mock_decode.return_value = [] 120 121 # Action & Assert 122 with pytest.raises(NoCodeFoundError, match="Nie wykryto kodu QR"): 123 decode_qr_image(fake_image) 124 125 126@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 127def test_decode_qr_image_no_code_none(mock_decode, fake_image): 128 """ 129 Negative scenario: The library returns None (theoretical case of a library error). 130 Expected exception: NoCodeFoundError. 131 """ 132 # Setup 133 mock_decode.return_value = None 134 135 # Action & Assert 136 with pytest.raises(NoCodeFoundError, match="Nie wykryto kodu QR"): 137 decode_qr_image(fake_image) 138 139 140@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 141def test_decode_qr_image_decoding_utf8_error(mock_decode, fake_image): 142 """ 143 Sprawdza, czy błąd dekodowania bajtów (np. złe kodowanie) rzuci standardowy błąd Pythonowy 144 lub czy przejdzie (zależnie od implementacji, tutaj testujemy domyślne zachowanie .decode()). 145 """ 146 # Setup 147 mock_qr_obj = MagicMock() 148 # Niepoprawna sekwencja UTF-8 149 mock_qr_obj.data = b'\xff\xfe\xfa' 150 151 mock_decode.return_value = [mock_qr_obj] 152 153 # Action & Assert 154 with pytest.raises(UnicodeDecodeError): 155 decode_qr_image(fake_image)
@pytest.fixture
def
fake_image():
18@pytest.fixture 19def fake_image(): 20 """Tworzy pustą tablicę numpy udającą obraz (dla decode).""" 21 return np.zeros((100, 100, 3), dtype=np.uint8)
Tworzy pustą tablicę numpy udającą obraz (dla decode).
@patch('backend.components.camera_verification.qrcode.qrcodeService.encode_image')
@patch('backend.components.camera_verification.qrcode.qrcodeService.cv2')
def
test_generate_qr_code_success(mock_cv2, mock_encode_image):
28@patch('backend.components.camera_verification.qrcode.qrcodeService.encode_image') 29@patch('backend.components.camera_verification.qrcode.qrcodeService.cv2') 30def test_generate_qr_code_success(mock_cv2, mock_encode_image): 31 """ 32 Testuje generowanie kodu QR. 33 Sprawdza, czy wywoływane są odpowiednie metody z biblioteki cv2 oraz funkcja kodująca wynik. 34 """ 35 # Setup 36 secret = "my_secret_code" 37 38 # Mockowanie łańcucha wywołań cv2 39 mock_encoder = MagicMock() 40 mock_cv2.QRCodeEncoder.return_value.create.return_value = mock_encoder 41 42 # Mockowanie wyników operacji na obrazie 43 # encode zwraca surowy obraz QR 44 mock_encoder.encode.return_value = np.zeros((10, 10), dtype=np.uint8) 45 # resize zwraca przeskalowany obraz 46 mock_cv2.resize.return_value = np.zeros((100, 100), dtype=np.uint8) 47 # copyMakeBorder dodaje ramkę 48 mock_cv2.copyMakeBorder.return_value = np.zeros((120, 120), dtype=np.uint8) 49 # threshold zwraca (retval, image) 50 mock_cv2.threshold.return_value = (127, np.zeros((120, 120), dtype=np.uint8)) 51 52 # Mock encode_image (zwraca bytes) 53 expected_bytes = b'fake_png_bytes' 54 mock_encode_image.return_value = expected_bytes 55 56 # Action 57 result = generate_qr_code(secret) 58 59 # Assert 60 assert result == expected_bytes 61 62 # Weryfikacja czy encoder został utworzony i użyty z sekretem 63 mock_cv2.QRCodeEncoder.return_value.create.assert_called_once() 64 mock_encoder.encode.assert_called_once_with(secret) 65 66 # Weryfikacja czy zakodowano ostateczny obraz 67 mock_encode_image.assert_called_once()
Testuje generowanie kodu QR. Sprawdza, czy wywoływane są odpowiednie metody z biblioteki cv2 oraz funkcja kodująca wynik.
@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode')
def
test_decode_qr_image_success(mock_decode, fake_image):
74@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 75def test_decode_qr_image_success(mock_decode, fake_image): 76 """ 77 Scenariusz pozytywny: Wykryto dokładnie jeden kod QR. 78 """ 79 # Setup 80 mock_qr_obj = MagicMock() 81 mock_qr_obj.data = b"decoded_secret_123" 82 83 # pyzbar.decode zwraca listę znalezionych obiektów 84 mock_decode.return_value = [mock_qr_obj] 85 86 # Action 87 result = decode_qr_image(fake_image) 88 89 # Assert 90 assert result == "decoded_secret_123" 91 mock_decode.assert_called_once_with(fake_image)
Scenariusz pozytywny: Wykryto dokładnie jeden kod QR.
@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode')
def
test_decode_qr_image_multiple_codes(mock_decode, fake_image):
94@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 95def test_decode_qr_image_multiple_codes(mock_decode, fake_image): 96 """ 97 Negative scenario: More than one QR code detected. 98 Expected exception: MultipleCodesError. 99 """ 100 # Setup 101 obj1 = MagicMock() 102 obj1.data = b"code1" 103 obj2 = MagicMock() 104 obj2.data = b"code2" 105 106 mock_decode.return_value = [obj1, obj2] 107 108 # Action & Assert 109 with pytest.raises(MultipleCodesError, match="Wykryto 2 kodów QR"): 110 decode_qr_image(fake_image)
Negative scenario: More than one QR code detected. Expected exception: MultipleCodesError.
@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode')
def
test_decode_qr_image_no_code_empty_list(mock_decode, fake_image):
113@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 114def test_decode_qr_image_no_code_empty_list(mock_decode, fake_image): 115 """ 116 Negative scenario: The library returns an empty list (no codes). 117 Expected exception: NoCodeFoundError. 118 """ 119 # Setup 120 mock_decode.return_value = [] 121 122 # Action & Assert 123 with pytest.raises(NoCodeFoundError, match="Nie wykryto kodu QR"): 124 decode_qr_image(fake_image)
Negative scenario: The library returns an empty list (no codes). Expected exception: NoCodeFoundError.
@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode')
def
test_decode_qr_image_no_code_none(mock_decode, fake_image):
127@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 128def test_decode_qr_image_no_code_none(mock_decode, fake_image): 129 """ 130 Negative scenario: The library returns None (theoretical case of a library error). 131 Expected exception: NoCodeFoundError. 132 """ 133 # Setup 134 mock_decode.return_value = None 135 136 # Action & Assert 137 with pytest.raises(NoCodeFoundError, match="Nie wykryto kodu QR"): 138 decode_qr_image(fake_image)
Negative scenario: The library returns None (theoretical case of a library error). Expected exception: NoCodeFoundError.
@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode')
def
test_decode_qr_image_decoding_utf8_error(mock_decode, fake_image):
141@patch('backend.components.camera_verification.qrcode.qrcodeService.pyzbar.decode') 142def test_decode_qr_image_decoding_utf8_error(mock_decode, fake_image): 143 """ 144 Sprawdza, czy błąd dekodowania bajtów (np. złe kodowanie) rzuci standardowy błąd Pythonowy 145 lub czy przejdzie (zależnie od implementacji, tutaj testujemy domyślne zachowanie .decode()). 146 """ 147 # Setup 148 mock_qr_obj = MagicMock() 149 # Niepoprawna sekwencja UTF-8 150 mock_qr_obj.data = b'\xff\xfe\xfa' 151 152 mock_decode.return_value = [mock_qr_obj] 153 154 # Action & Assert 155 with pytest.raises(UnicodeDecodeError): 156 decode_qr_image(fake_image)
Sprawdza, czy błąd dekodowania bajtów (np. złe kodowanie) rzuci standardowy błąd Pythonowy lub czy przejdzie (zależnie od implementacji, tutaj testujemy domyślne zachowanie .decode()).