alessandro trinca tornidor
commited on
Commit
·
46e78fd
1
Parent(s):
7496446
test: add missing test cases
Browse files- tests/test_app.py +111 -0
- tests/test_pymongo_operations_rw.py +61 -0
- tests/test_pymongo_utils.py +59 -0
tests/test_app.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import unittest
|
| 2 |
+
from unittest.mock import patch, MagicMock
|
| 3 |
+
from fastapi.testclient import TestClient
|
| 4 |
+
|
| 5 |
+
from my_ghost_writer.app import app
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class TestAppEndpoints(unittest.TestCase):
|
| 9 |
+
def setUp(self):
|
| 10 |
+
self.client = TestClient(app)
|
| 11 |
+
|
| 12 |
+
def test_health(self):
|
| 13 |
+
response = self.client.get("/health")
|
| 14 |
+
self.assertEqual(response.status_code, 200)
|
| 15 |
+
self.assertIn("Still alive", response.text)
|
| 16 |
+
|
| 17 |
+
@patch("my_ghost_writer.app.mongodb_health_check")
|
| 18 |
+
@patch("my_ghost_writer.app.pymongo_version", "8.0.0")
|
| 19 |
+
def test_health_mongo_ok(self, mock_health_check):
|
| 20 |
+
mock_health_check.return_value = True
|
| 21 |
+
response = self.client.get("/health-mongo")
|
| 22 |
+
self.assertEqual(response.status_code, 200)
|
| 23 |
+
self.assertIn("Mongodb: still alive", response.text)
|
| 24 |
+
|
| 25 |
+
@patch("my_ghost_writer.app.mongodb_health_check", side_effect=Exception("mongo error"))
|
| 26 |
+
def test_health_mongo_fail(self, mock_health_check):
|
| 27 |
+
mock_health_check.side_effect = Exception("mongo error")
|
| 28 |
+
response = self.client.get("/health-mongo")
|
| 29 |
+
self.assertNotEqual(response.status_code, 200)
|
| 30 |
+
self.assertEqual(response.status_code, 500)
|
| 31 |
+
|
| 32 |
+
@patch("my_ghost_writer.app.text_stemming")
|
| 33 |
+
def test_words_frequency(self, mock_stemming):
|
| 34 |
+
mock_stemming.return_value = (1, {"word": 2})
|
| 35 |
+
body = '{"text": "test test"}'
|
| 36 |
+
response = self.client.post("/words-frequency", json=body)
|
| 37 |
+
self.assertEqual(response.status_code, 200)
|
| 38 |
+
self.assertIn("words_frequency", response.json())
|
| 39 |
+
|
| 40 |
+
def test_words_frequency_fail_request(self):
|
| 41 |
+
body = '{}'
|
| 42 |
+
response = self.client.post("/words-frequency", json=body)
|
| 43 |
+
self.assertEqual(response.status_code, 500)
|
| 44 |
+
|
| 45 |
+
@patch("my_ghost_writer.app.text_stemming")
|
| 46 |
+
def test_words_frequency_fail2(self, mock_stemming):
|
| 47 |
+
mock_stemming.side_effect = ValueError("stemming error")
|
| 48 |
+
body = '{"text": "test test"}'
|
| 49 |
+
response = self.client.post("/words-frequency", json=body)
|
| 50 |
+
self.assertEqual(response.status_code, 500)
|
| 51 |
+
|
| 52 |
+
@patch("my_ghost_writer.app.pymongo_operations_rw.get_document_by_word")
|
| 53 |
+
def test_thesaurus_wordsapi_local(self, mock_get_doc):
|
| 54 |
+
mock_get_doc.return_value = {"word": "test"}
|
| 55 |
+
with patch("my_ghost_writer.app.db_ok", {"mongo_ok": True}):
|
| 56 |
+
body = '{"query": "test"}'
|
| 57 |
+
response = self.client.post("/thesaurus-wordsapi", json=body)
|
| 58 |
+
self.assertEqual(response.status_code, 200)
|
| 59 |
+
self.assertEqual(response.json()["source"], "local")
|
| 60 |
+
|
| 61 |
+
@patch("my_ghost_writer.app.WORDSAPI_URL", "http://mocked-url.com")
|
| 62 |
+
@patch("my_ghost_writer.app.RAPIDAPI_HOST", "mocked-rapidapi-host.com")
|
| 63 |
+
@patch("my_ghost_writer.app.WORDSAPI_KEY", "WORDSAPI_KEY")
|
| 64 |
+
@patch("my_ghost_writer.app.requests.get")
|
| 65 |
+
@patch("my_ghost_writer.app.pymongo_operations_rw.get_document_by_word", side_effect=AssertionError)
|
| 66 |
+
@patch("my_ghost_writer.app.pymongo_operations_rw.insert_document")
|
| 67 |
+
def test_thesaurus_wordsapi_remote_mongo_ok(self, mock_insert, mock_get_doc, mock_requests_get):
|
| 68 |
+
mock_get_doc.return_value = None
|
| 69 |
+
mock_response = MagicMock()
|
| 70 |
+
mock_response.status_code = 200
|
| 71 |
+
mock_response.json.return_value = {"word": "test", "_id": "_id"}
|
| 72 |
+
mock_requests_get.return_value = mock_response
|
| 73 |
+
with patch("my_ghost_writer.app.db_ok", {"mongo_ok": True}):
|
| 74 |
+
body = '{"query": "test"}'
|
| 75 |
+
response = self.client.post("/thesaurus-wordsapi", json=body)
|
| 76 |
+
self.assertEqual(response.status_code, 200)
|
| 77 |
+
self.assertEqual(response.json()["source"], "wordsapi")
|
| 78 |
+
|
| 79 |
+
@patch("my_ghost_writer.app.WORDSAPI_URL", "http://mocked-url.com")
|
| 80 |
+
@patch("my_ghost_writer.app.RAPIDAPI_HOST", "mocked-rapidapi-host.com")
|
| 81 |
+
@patch("my_ghost_writer.app.WORDSAPI_KEY", "WORDSAPI_KEY")
|
| 82 |
+
@patch("my_ghost_writer.app.requests.get")
|
| 83 |
+
def test_thesaurus_wordsapi_remote_mongo_disabled(self, mock_requests_get):
|
| 84 |
+
mock_response = MagicMock()
|
| 85 |
+
mock_response.status_code = 200
|
| 86 |
+
mock_response.json.return_value = {"word": "test", "_id": "_id"}
|
| 87 |
+
mock_requests_get.return_value = mock_response
|
| 88 |
+
with patch("my_ghost_writer.app.db_ok", {"mongo_ok": False}):
|
| 89 |
+
body = '{"query": "test"}'
|
| 90 |
+
response = self.client.post("/thesaurus-wordsapi", json=body)
|
| 91 |
+
self.assertEqual(response.status_code, 200)
|
| 92 |
+
self.assertEqual(response.json()["source"], "wordsapi")
|
| 93 |
+
|
| 94 |
+
@patch("my_ghost_writer.app.WORDSAPI_URL", "http://mocked-url.com")
|
| 95 |
+
@patch("my_ghost_writer.app.RAPIDAPI_HOST", "mocked-rapidapi-host.com")
|
| 96 |
+
@patch("my_ghost_writer.app.WORDSAPI_KEY", "WORDSAPI_KEY")
|
| 97 |
+
@patch("my_ghost_writer.app.requests.get")
|
| 98 |
+
def test_thesaurus_wordsapi_remote_mongo_disabled_fail(self, mock_requests_get):
|
| 99 |
+
mock_response = MagicMock()
|
| 100 |
+
mock_response.status_code = 200
|
| 101 |
+
mock_response.json.return_value = {"word": "test", "_id": "_id"}
|
| 102 |
+
mock_requests_get.side_effect = IOError("io error")
|
| 103 |
+
with patch("my_ghost_writer.app.db_ok", {"mongo_ok": False}):
|
| 104 |
+
body = '{"query": "test"}'
|
| 105 |
+
response = self.client.post("/thesaurus-wordsapi", json=body)
|
| 106 |
+
self.assertEqual(response.status_code, 500)
|
| 107 |
+
self.assertEqual(response.text, "")
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
if __name__ == "__main__":
|
| 111 |
+
unittest.main()
|
tests/test_pymongo_operations_rw.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import unittest
|
| 2 |
+
from unittest.mock import patch, MagicMock
|
| 3 |
+
from my_ghost_writer import pymongo_operations_rw
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class TestPymongoOperationsRW(unittest.TestCase):
|
| 7 |
+
@patch('my_ghost_writer.pymongo_operations_rw.pymongo_utils.get_thesaurus_collection')
|
| 8 |
+
def test_get_document_by_word_found(self, mock_get_collection):
|
| 9 |
+
mock_collection = MagicMock()
|
| 10 |
+
mock_collection.find_one.return_value = {"word": "example", "meaning": "test", "_id": "someid"}
|
| 11 |
+
mock_get_collection.return_value = mock_collection
|
| 12 |
+
|
| 13 |
+
result = pymongo_operations_rw.get_document_by_word("example")
|
| 14 |
+
self.assertEqual(result, {"word": "example", "meaning": "test"})
|
| 15 |
+
mock_collection.find_one.assert_called_with({"word": "example"})
|
| 16 |
+
|
| 17 |
+
@patch('my_ghost_writer.pymongo_operations_rw.pymongo_utils.get_thesaurus_collection')
|
| 18 |
+
def test_get_document_by_word_not_found(self, mock_get_collection):
|
| 19 |
+
mock_collection = MagicMock()
|
| 20 |
+
mock_collection.find_one.return_value = None
|
| 21 |
+
mock_get_collection.return_value = mock_collection
|
| 22 |
+
|
| 23 |
+
with self.assertRaises(AssertionError):
|
| 24 |
+
try:
|
| 25 |
+
pymongo_operations_rw.get_document_by_word("notfound")
|
| 26 |
+
except AssertionError as ae:
|
| 27 |
+
self.assertEqual(str(ae), "word 'notfound' not found in thesaurus collection")
|
| 28 |
+
raise ae
|
| 29 |
+
|
| 30 |
+
@patch('my_ghost_writer.pymongo_operations_rw.app_logger')
|
| 31 |
+
@patch('my_ghost_writer.pymongo_operations_rw.pymongo_utils.get_thesaurus_collection')
|
| 32 |
+
def test_insert_document_success(self, mock_get_collection, mock_logger):
|
| 33 |
+
mock_collection = MagicMock()
|
| 34 |
+
mock_result = MagicMock()
|
| 35 |
+
mock_result.inserted_id = "someid"
|
| 36 |
+
mock_collection.insert_one.return_value = mock_result
|
| 37 |
+
mock_get_collection.return_value = mock_collection
|
| 38 |
+
|
| 39 |
+
pymongo_operations_rw.insert_document({"word": "example"})
|
| 40 |
+
mock_collection.insert_one.assert_called_with({"word": "example"})
|
| 41 |
+
mock_logger.info.assert_called()
|
| 42 |
+
|
| 43 |
+
@patch('my_ghost_writer.pymongo_operations_rw.app_logger')
|
| 44 |
+
@patch('my_ghost_writer.pymongo_operations_rw.pymongo_utils.get_thesaurus_collection')
|
| 45 |
+
def test_insert_document_failure(self, mock_get_collection, mock_logger):
|
| 46 |
+
mock_collection = MagicMock()
|
| 47 |
+
mock_result = MagicMock()
|
| 48 |
+
mock_result.inserted_id = None
|
| 49 |
+
mock_collection.insert_one.return_value = mock_result
|
| 50 |
+
mock_get_collection.return_value = mock_collection
|
| 51 |
+
|
| 52 |
+
with self.assertRaises(IOError):
|
| 53 |
+
try:
|
| 54 |
+
pymongo_operations_rw.insert_document({"word": "fail"})
|
| 55 |
+
except IOError as e:
|
| 56 |
+
self.assertEqual(str(e), """failed insert of document '{"word": "fail"}'""")
|
| 57 |
+
raise e
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
if __name__ == '__main__':
|
| 61 |
+
unittest.main()
|
tests/test_pymongo_utils.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import unittest
|
| 2 |
+
from unittest.mock import patch, MagicMock
|
| 3 |
+
|
| 4 |
+
from my_ghost_writer import pymongo_utils
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class TestPymongoUtils(unittest.TestCase):
|
| 8 |
+
@patch('my_ghost_writer.pymongo_utils.MongoClient')
|
| 9 |
+
def test_get_client(self, mock_mongo_client):
|
| 10 |
+
client = pymongo_utils.get_client()
|
| 11 |
+
mock_mongo_client.assert_called_with(
|
| 12 |
+
pymongo_utils.MONGO_CONNECTION_STRING,
|
| 13 |
+
timeoutMS=pymongo_utils.MONGO_CONNECTION_TIMEOUT
|
| 14 |
+
)
|
| 15 |
+
self.assertEqual(client, mock_mongo_client.return_value)
|
| 16 |
+
|
| 17 |
+
@patch('my_ghost_writer.pymongo_utils.get_client')
|
| 18 |
+
def test_get_database(self, mock_get_client):
|
| 19 |
+
mock_client = MagicMock()
|
| 20 |
+
mock_get_client.return_value = mock_client
|
| 21 |
+
db = pymongo_utils.get_database('testdb')
|
| 22 |
+
mock_get_client.assert_called_once()
|
| 23 |
+
mock_client.__getitem__.assert_called_with('testdb')
|
| 24 |
+
self.assertEqual(db, mock_client.__getitem__.return_value)
|
| 25 |
+
|
| 26 |
+
@patch('my_ghost_writer.pymongo_utils.get_database')
|
| 27 |
+
def test_get_thesaurus_collection(self, mock_get_database):
|
| 28 |
+
mock_db = MagicMock()
|
| 29 |
+
mock_get_database.return_value = mock_db
|
| 30 |
+
collection = pymongo_utils.get_thesaurus_collection('testdb', 'testcol')
|
| 31 |
+
mock_get_database.assert_called_with(db_name='testdb')
|
| 32 |
+
mock_db.__getitem__.assert_called_with('testcol')
|
| 33 |
+
self.assertEqual(collection, mock_db.__getitem__.return_value)
|
| 34 |
+
|
| 35 |
+
@patch('my_ghost_writer.pymongo_utils.get_client')
|
| 36 |
+
@patch('my_ghost_writer.pymongo_utils.app_logger')
|
| 37 |
+
def test_mongodb_health_check(self, mock_logger, mock_get_client):
|
| 38 |
+
mock_client = MagicMock()
|
| 39 |
+
mock_get_client.return_value = mock_client
|
| 40 |
+
mock_client.admin.command.return_value = {'ok': 1}
|
| 41 |
+
mock_client.server_info.return_value = {'version': '8.0.0'}
|
| 42 |
+
mock_db = MagicMock()
|
| 43 |
+
mock_collection = MagicMock()
|
| 44 |
+
mock_client.__getitem__.return_value = mock_db
|
| 45 |
+
mock_db.__getitem__.return_value = mock_collection
|
| 46 |
+
mock_collection.find_one.return_value = {}
|
| 47 |
+
|
| 48 |
+
result = pymongo_utils.mongodb_health_check('testdb', 'testcol')
|
| 49 |
+
mock_client.admin.command.assert_called_with('ping', check=True)
|
| 50 |
+
mock_client.server_info.assert_called_once()
|
| 51 |
+
mock_db.__getitem__.assert_called_with('testcol')
|
| 52 |
+
mock_collection.find_one.assert_called_once()
|
| 53 |
+
self.assertTrue(result)
|
| 54 |
+
mock_logger.info.assert_any_call("mongodb server_version:8.0.0!")
|
| 55 |
+
mock_logger.info.assert_any_call("mongodb: still alive...")
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
if __name__ == '__main__':
|
| 59 |
+
unittest.main()
|