Files
set50-system/backend/tests/test_energy_thai.py
Kunthawat Greethong 3f7fccd25b [verified] Add Thai Energy/Refining collector (TOP quarterly financials) replacing EIA US crack spread
- energy_thai.py: scrape Thai Oil (TOP) investor financial-highlights -> quarterly + annual EBITDA/Net Profit/Sales (Million Baht), largest Thai refinery
- Thai-specific factor per user (energy must reflect Thai companies, not US EIA proxy); Krungsri was projection-only, TOP gives real quarterly actuals
- Frequency: quarterly (documented in research note)
- 4 tests; full backend suite 156 OK; compileall ok; static scan clean
2026-08-25 15:13:36 +07:00

69 lines
2.9 KiB
Python

"""Tests for the Thai Energy/Refining (TOP financial highlights) parser."""
from __future__ import annotations
import unittest
from app import energy_thai
def _top_html() -> str:
return """
<html><body>
<table class="table table--financial">
<thead><tr><th class="persist"></th><th>2025</th><th>2024</th><th>2023</th></tr></thead>
<tbody>
<tr class="table__header"><td colspan="4">Operating</td></tr>
<tr><td>Sales Revenue</td><td>394,336</td><td>455,857</td><td>459,402</td></tr>
<tr><td>EBITDA</td><td>17,619</td><td>22,026</td><td>35,453</td></tr>
<tr><td>Net Profit / (Loss)</td><td>14,584</td><td>9,959</td><td>19,443</td></tr>
<tr><td>Basic Earnings / (Loss) (Baht / Share)</td><td>6.53</td><td>4.46</td><td>8.70</td></tr>
</tbody>
</table>
<table class="table table--financial">
<thead><tr><th class="persist"></th><th>Q2/2026</th><th>Q1/2026</th><th>Q4/2025</th></tr></thead>
<tbody>
<tr class="table__header"><td colspan="4">Operating</td></tr>
<tr><td>Sales Revenue</td><td>129,709</td><td>114,809</td><td>108,931</td></tr>
<tr><td>EBITDA</td><td>8,915</td><td>31,641</td><td>5,981</td></tr>
<tr><td>Net Profit / (Loss)</td><td>8,284</td><td>19,481</td><td>2,458</td></tr>
<tr><td>Basic Earnings / (Loss) (Baht / Share)</td><td>3.71</td><td>8.41</td><td>1.10</td></tr>
</tbody>
</table>
</body></html>
"""
class EnergyThaiParseTest(unittest.TestCase):
def test_parses_quarterly_and_annual(self) -> None:
parsed = energy_thai.parse_energy_thai_html(_top_html())
self.assertIn("Q2/2026", parsed["quarterly"]["columns"])
self.assertIn("2025", parsed["annual"]["columns"])
self.assertEqual(parsed["quarterly"]["rows"]["net_profit"][0], 8284.0)
self.assertEqual(parsed["annual"]["rows"]["ebitda"][0], 17619.0)
def test_period_map(self) -> None:
parsed = energy_thai.parse_energy_thai_html(_top_html())
qmap = energy_thai._to_period_map(parsed["quarterly"])
self.assertEqual(qmap["Q2/2026"]["net_profit"], 8284.0)
self.assertEqual(qmap["Q2/2026"]["sales"], 129709.0)
amap = energy_thai._to_period_map(parsed["annual"])
self.assertEqual(amap["2025"]["ebitda"], 17619.0)
def test_no_tables_raises(self) -> None:
with self.assertRaises(energy_thai.EnergyThaiError):
energy_thai.parse_energy_thai_html("<html>no data</html>")
def test_negative_net_profit_parses(self) -> None:
html_text = """
<table class="table table--financial">
<tr><th></th><th>Q1/2026</th></tr>
<tr><td>Net Profit / (Loss)</td><td>-5,380</td></tr>
</table>"""
parsed = energy_thai.parse_energy_thai_html(html_text)
self.assertEqual(parsed["quarterly"]["rows"]["net_profit"][0], -5380.0)
if __name__ == "__main__":
unittest.main()