- 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
69 lines
2.9 KiB
Python
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()
|