diff --git a/requirements-dev.txt b/requirements-dev.txt index 7703670..21a7017 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,3 +5,4 @@ requests==2.32.3 # Dev only packages. black==24.4.2 +coverage==7.5.3 diff --git a/run_tests.py b/run_tests.py index f695555..174d6b3 100644 --- a/run_tests.py +++ b/run_tests.py @@ -2,8 +2,17 @@ def main(): - subprocess.call(["python", "-m", "unittest"]) + # Run tests with coverage + subprocess.call(["python", "-m", "coverage", "run", "-m", "unittest", "discover"]) + + # Generate the coverage report in the terminal + subprocess.call(["python", "-m", "coverage", "report", "-m"]) + + # Generate the HTML coverage report + subprocess.call(["python", "-m", "coverage", "html"]) + print("\n\nTests completed.") + print("HTML report generated at 'htmlcov/index.html'") if __name__ == "__main__": diff --git a/tests/test_rates.py b/tests/test_rates.py index 54dd666..3bcef11 100644 --- a/tests/test_rates.py +++ b/tests/test_rates.py @@ -1,4 +1,9 @@ +import json import unittest +from unittest.mock import patch, MagicMock + +import requests + from tipbot import rates from .samples import UPDATE @@ -6,4 +11,48 @@ class TestRate(unittest.TestCase): def test_get_rate(self): rate = rates.get_rate(UPDATE) - self.assertIs(type(rate), float) + self.assertIsInstance(rate, float) + + def test_get_rate_unsupported_currency(self): + mock_update = MagicMock() + rates.get_rate(mock_update, "XYZ") + + mock_update.message.reply_text.assert_called_once_with( + "XYZ is not a supported currency." + ) + + @patch("tipbot.rates.requests.get") + def test_get_rate_api_failure(self, mock_requests_get): + mock_requests_get.side_effect = requests.exceptions.RequestException + mock_update = MagicMock() + rates.get_rate(mock_update, "USD") + + mock_update.message.reply_text.assert_called_once_with( + f"Unable to contact {rates.RATE_API}" + ) + + @patch("tipbot.rates.requests.get") + def test_get_rate_http_error(self, mock_requests_get): + mock_requests_get.side_effect = requests.exceptions.HTTPError + mock_response = MagicMock() + mock_response.text = "Error message" + mock_requests_get.return_value = mock_response + mock_update = MagicMock() + rates.get_rate(mock_update, "USD") + + mock_update.message.reply_text.assert_called_once_with( + f"Unable to contact {rates.RATE_API}" + ) + + @patch("tipbot.rates.requests.get") + def test_get_rate_parse_failure(self, mock_requests_get): + mock_response = MagicMock() + mock_response.raise_for_status = MagicMock() + mock_response.json.side_effect = json.JSONDecodeError("Expecting value", "", 0) + mock_requests_get.return_value = mock_response + mock_update = MagicMock() + rates.get_rate(mock_update, "USD") + + mock_update.message.reply_text.assert_called_once_with( + f"Unable to parse rate data: {mock_response.text}" + )