test_math_logic.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import unittest
  2. from unittest.mock import patch, MagicMock
  3. from fastapi.testclient import TestClient
  4. from main import app
  5. class TestMealMathLogic(unittest.TestCase):
  6. def setUp(self):
  7. self.client = TestClient(app)
  8. # Mock user authentication for the calculation endpoint
  9. self.headers = {"Authorization": "Bearer mock-token"}
  10. @patch("main.get_user_from_token")
  11. @patch("main.get_foods_by_ids")
  12. def test_math_scaling_and_aggregation(self, mock_get_foods, mock_auth):
  13. # 1. Setup mocks
  14. mock_auth.return_value = {"id": 1, "username": "testuser"}
  15. # Mock database return for two foods
  16. mock_get_foods.return_value = [
  17. {
  18. "id": 1, "name": "Food A",
  19. "calories": 100.0, "protein_g": 10.0, "fat_g": 5.0, "carbs_g": 2.0,
  20. "fiber_g": 1.0, "sugar_g": 0.5, "cholesterol_mg": 0.0,
  21. "vitamin_a_iu": 0.0, "vitamin_c_mg": 0.0,
  22. "calcium_mg": 0.0, "iron_mg": 0.0, "potassium_mg": 0.0, "sodium_mg": 0.0
  23. },
  24. {
  25. "id": 2, "name": "Food B",
  26. "calories": 200.0, "protein_g": 20.0, "fat_g": 10.0, "carbs_g": 4.0,
  27. "fiber_g": 2.0, "sugar_g": 1.0, "cholesterol_mg": 5.0,
  28. "vitamin_a_iu": 100.0, "vitamin_c_mg": 10.0,
  29. "calcium_mg": 50.0, "iron_mg": 2.0, "potassium_mg": 300.0, "sodium_mg": 100.0
  30. }
  31. ]
  32. # 2. Test Case: 50g of Food A and 150g of Food B
  33. # Expected Food A (50g): Cal=50, Pro=5
  34. # Expected Food B (150g): Cal=300, Pro=30
  35. # Totals: Cal=350, Pro=35, Weight=200
  36. payload = {
  37. "items": [
  38. {"food_id": 1, "amount_g": 50},
  39. {"food_id": 2, "amount_g": 150}
  40. ]
  41. }
  42. response = self.client.post("/api/meal/calculate", json=payload, headers=self.headers)
  43. self.assertEqual(response.status_code, 200)
  44. data = response.json()
  45. self.assertEqual(data["total_weight_g"], 200.0)
  46. self.assertEqual(data["macros"]["calories"], 350.0)
  47. self.assertEqual(data["macros"]["protein_g"], 35.0)
  48. self.assertEqual(data["macros"]["fat_g"], 17.5) # (5 * 0.5) + (10 * 1.5) = 2.5 + 15 = 17.5
  49. self.assertEqual(data["macros"]["carbs_g"], 7.0) # (2 * 0.5) + (4 * 1.5) = 1.0 + 6.0 = 7.0
  50. @patch("main.get_user_from_token")
  51. @patch("main.get_foods_by_ids")
  52. def test_precision_rounding(self, mock_get_foods, mock_auth):
  53. mock_auth.return_value = {"id": 1, "username": "testuser"}
  54. # Mock food with irregular values to trigger rounding
  55. mock_get_foods.return_value = [
  56. {
  57. "id": 1, "name": "Irregular Food",
  58. "calories": 123.456, "protein_g": 10.123, "fat_g": 5.555, "carbs_g": 0.0,
  59. "fiber_g": 0.0, "sugar_g": 0.0, "cholesterol_mg": 0.0,
  60. "vitamin_a_iu": 0.0, "vitamin_c_mg": 0.0,
  61. "calcium_mg": 0.0, "iron_mg": 0.0, "potassium_mg": 0.0, "sodium_mg": 0.0
  62. }
  63. ]
  64. # 123g of Food A -> Ratio 1.23
  65. # Calories: 123.456 * 1.23 = 151.85088 -> Rounded to 151.85
  66. # Protein: 10.123 * 1.23 = 12.45129 -> Rounded to 12.45
  67. # Fat: 5.555 * 1.23 = 6.83265 -> Rounded to 6.83
  68. payload = {"items": [{"food_id": 1, "amount_g": 123}]}
  69. response = self.client.post("/api/meal/calculate", json=payload, headers=self.headers)
  70. data = response.json()
  71. self.assertEqual(data["macros"]["calories"], 151.85)
  72. self.assertEqual(data["macros"]["protein_g"], 12.45)
  73. self.assertEqual(data["macros"]["fat_g"], 6.83)
  74. @patch("main.get_user_from_token")
  75. @patch("main.get_foods_by_ids")
  76. def test_null_value_handling(self, mock_get_foods, mock_auth):
  77. mock_auth.return_value = {"id": 1, "username": "testuser"}
  78. # Mock food with NULLs
  79. mock_get_foods.return_value = [
  80. {
  81. "id": 1, "name": "Null Food",
  82. "calories": None, "protein_g": 10.0, "fat_g": None, "carbs_g": 2.0,
  83. "fiber_g": None, "sugar_g": None, "cholesterol_mg": None,
  84. "vitamin_a_iu": None, "vitamin_c_mg": None,
  85. "calcium_mg": None, "iron_mg": None, "potassium_mg": None, "sodium_mg": None
  86. }
  87. ]
  88. payload = {"items": [{"food_id": 1, "amount_g": 100}]}
  89. response = self.client.post("/api/meal/calculate", json=payload, headers=self.headers)
  90. self.assertEqual(response.status_code, 200)
  91. data = response.json()
  92. self.assertEqual(data["macros"]["calories"], 0.0)
  93. self.assertEqual(data["macros"]["fat_g"], 0.0)
  94. self.assertEqual(data["extended"]["fiber_g"], 0.0)
  95. if __name__ == "__main__":
  96. unittest.main()