107 lines
3.8 KiB
Python
107 lines
3.8 KiB
Python
import pytest
|
|
import requests as req_lib
|
|
from unittest.mock import patch, MagicMock
|
|
from plants.services.plantnet import identify, PlantNetError
|
|
|
|
|
|
def _mock_response(results=None, status_code=200):
|
|
mock = MagicMock()
|
|
mock.status_code = status_code
|
|
mock.json.return_value = {'results': results or []}
|
|
if status_code == 429:
|
|
mock.raise_for_status.side_effect = req_lib.HTTPError(response=mock)
|
|
elif status_code >= 400:
|
|
mock.raise_for_status.side_effect = req_lib.HTTPError(response=mock)
|
|
else:
|
|
mock.raise_for_status = MagicMock()
|
|
return mock
|
|
|
|
|
|
def _api_results():
|
|
return [
|
|
{
|
|
'score': 0.94,
|
|
'species': {
|
|
'scientificNameWithoutAuthor': 'Liatris spicata',
|
|
'commonNames': ['Blazing star', 'Pronkster'],
|
|
'family': {'scientificNameWithoutAuthor': 'Asteraceae'},
|
|
'genus': {'scientificNameWithoutAuthor': 'Liatris'},
|
|
},
|
|
'gbif': {'id': '2889739'},
|
|
},
|
|
{
|
|
'score': 0.04,
|
|
'species': {
|
|
'scientificNameWithoutAuthor': 'Liatris pycnostachya',
|
|
'commonNames': ['Prairie blazing star'],
|
|
'family': {'scientificNameWithoutAuthor': 'Asteraceae'},
|
|
'genus': {'scientificNameWithoutAuthor': 'Liatris'},
|
|
},
|
|
'gbif': {'id': '1234567'},
|
|
},
|
|
]
|
|
|
|
|
|
def test_identify_raises_without_api_key(settings):
|
|
settings.PLANTNET_API_KEY = ''
|
|
with pytest.raises(PlantNetError, match='API key'):
|
|
identify([(b'fake', 'flower')])
|
|
|
|
|
|
def test_identify_parses_results(settings):
|
|
settings.PLANTNET_API_KEY = 'test-key'
|
|
with patch('plants.services.plantnet.requests.post',
|
|
return_value=_mock_response(_api_results())):
|
|
results = identify([(b'fake', 'flower')])
|
|
|
|
assert len(results) == 2
|
|
assert results[0]['scientific_name'] == 'Liatris spicata'
|
|
assert results[0]['score'] == pytest.approx(0.94)
|
|
assert 'Blazing star' in results[0]['common_names']
|
|
assert results[0]['family'] == 'Asteraceae'
|
|
assert results[0]['genus'] == 'Liatris'
|
|
assert results[0]['gbif_id'] == '2889739'
|
|
|
|
|
|
def test_identify_raises_on_no_results(settings):
|
|
settings.PLANTNET_API_KEY = 'test-key'
|
|
with patch('plants.services.plantnet.requests.post',
|
|
return_value=_mock_response([])):
|
|
with pytest.raises(PlantNetError, match='No match'):
|
|
identify([(b'fake', 'flower')])
|
|
|
|
|
|
def test_identify_raises_on_quota_exceeded(settings):
|
|
settings.PLANTNET_API_KEY = 'test-key'
|
|
with patch('plants.services.plantnet.requests.post',
|
|
return_value=_mock_response(status_code=429)):
|
|
with pytest.raises(PlantNetError, match='Daily limit'):
|
|
identify([(b'fake', 'flower')])
|
|
|
|
|
|
def test_identify_raises_on_timeout(settings):
|
|
settings.PLANTNET_API_KEY = 'test-key'
|
|
with patch('plants.services.plantnet.requests.post',
|
|
side_effect=req_lib.Timeout):
|
|
with pytest.raises(PlantNetError, match='timed out'):
|
|
identify([(b'fake', 'flower')])
|
|
|
|
|
|
def test_identify_raises_on_other_http_error(settings):
|
|
settings.PLANTNET_API_KEY = 'test-key'
|
|
with patch('plants.services.plantnet.requests.post',
|
|
return_value=_mock_response(status_code=500)):
|
|
with pytest.raises(PlantNetError):
|
|
identify([(b'fake', 'flower')])
|
|
|
|
|
|
def test_identify_sends_correct_organs(settings):
|
|
settings.PLANTNET_API_KEY = 'test-key'
|
|
mock_post = MagicMock(return_value=_mock_response(_api_results()))
|
|
with patch('plants.services.plantnet.requests.post', mock_post):
|
|
identify([(b'img1', 'flower'), (b'img2', 'leaf')])
|
|
|
|
call_kwargs = mock_post.call_args
|
|
data = call_kwargs[1]['data']
|
|
assert ('organs', 'flower') in data
|
|
assert ('organs', 'leaf') in data
|