278 lines
10 KiB
Python
278 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for muhurta.py — Panchanga calculation, auspicious/inauspicious periods."""
|
|
|
|
from __future__ import annotations
|
|
import sys, os, pytest
|
|
|
|
SCRIPTS = os.path.join(os.path.dirname(__file__), '..', 'scripts')
|
|
if SCRIPTS not in sys.path:
|
|
sys.path.insert(0, SCRIPTS)
|
|
|
|
from muhurta import (
|
|
calc_tithi, calc_nakshatra_from_lon, calc_yoga, calc_karana,
|
|
calc_vara, calc_hora, calc_abhijit_muhurta, calc_panchanga,
|
|
check_activity_muhurta, muhurta_full_report,
|
|
TITHI_NAMES, TITHI_QUALITY, NAKSHATRAS, NAKSHATRA_TYPE,
|
|
YOGA_NAMES, YOGA_QUALITY, KARANA_NAMES, KARANA_QUALITY,
|
|
VARA_LORDS, ACTIVITY_RULES,
|
|
)
|
|
|
|
|
|
# ── Tithi Tests ─────────────────────────────────────────────────────
|
|
|
|
class TestTithi:
|
|
def test_new_moon_tithi_30(self):
|
|
# Moon-Sun diff = 0 → tithi 1
|
|
result = calc_tithi(0.0, 0.0)
|
|
assert result['tithi_num'] == 1
|
|
|
|
def test_full_moon_tithi_15(self):
|
|
# Moon-Sun diff = 180° → tithi 16 (Krishna 1)
|
|
result = calc_tithi(0.0, 180.0)
|
|
assert result['tithi_num'] == 16 # Krishna Pratipada
|
|
|
|
def test_shukla_paksha(self):
|
|
result = calc_tithi(0.0, 60.0) # 60/12=5+1=6
|
|
assert result['paksha'] == 'Shukla'
|
|
|
|
def test_krishna_paksha(self):
|
|
result = calc_tithi(0.0, 210.0) # 210/12=17+1=18
|
|
assert result['paksha'] == 'Krishna'
|
|
|
|
def test_purnima_name(self):
|
|
result = calc_tithi(0.0, 174.0) # ~15th tithi
|
|
if result['tithi_num'] == 15:
|
|
assert result['name'] == 'Purnima'
|
|
|
|
def test_amavasya_name(self):
|
|
result = calc_tithi(0.0, 354.0) # ~30th tithi
|
|
if result['tithi_num'] == 30:
|
|
assert result['name'] == 'Amavasya'
|
|
|
|
@pytest.mark.parametrize("diff,tithi",
|
|
[(0, 1), (12, 2), (24, 3), (168, 15), (180, 16), (348, 30)])
|
|
def test_tithi_from_diff(self, diff, tithi):
|
|
result = calc_tithi(0.0, float(diff))
|
|
assert result['tithi_num'] == tithi
|
|
|
|
def test_tithi_quality_present(self):
|
|
result = calc_tithi(0.0, 60.0)
|
|
assert result['quality'] in ('subha', 'asubha', 'mixed')
|
|
|
|
|
|
# ── Nakshatra from Longitude Tests ──────────────────────────────────
|
|
|
|
class TestNakshatraFromLon:
|
|
def test_ashwini_at_0(self):
|
|
result = calc_nakshatra_from_lon(0.0)
|
|
assert result['nakshatra'] == 'Ashwini'
|
|
|
|
def test_revati_near_360(self):
|
|
result = calc_nakshatra_from_lon(355.0)
|
|
assert result['nakshatra'] == 'Revati'
|
|
|
|
def test_pada_range(self):
|
|
for lon in [1.0, 5.0, 8.0, 11.0]:
|
|
result = calc_nakshatra_from_lon(lon)
|
|
assert 1 <= result['pada'] <= 4
|
|
|
|
def test_27_nakshatras(self):
|
|
assert len(NAKSHATRAS) == 27
|
|
|
|
def test_nakshatra_type(self):
|
|
result = calc_nakshatra_from_lon(0.0) # Ashwini
|
|
assert result['type'] == 'laghu'
|
|
|
|
|
|
# ── Yoga Tests ──────────────────────────────────────────────────────
|
|
|
|
class TestYoga:
|
|
def test_vishkambha_at_low_sum(self):
|
|
result = calc_yoga(0.0, 0.0) # sum=0 → idx 0
|
|
assert result['yoga'] == 'Vishkambha'
|
|
|
|
def test_yoga_idx_range(self):
|
|
result = calc_yoga(180.0, 180.0)
|
|
assert 0 <= result['yoga_idx'] < 27
|
|
|
|
def test_yoga_quality_present(self):
|
|
result = calc_yoga(45.0, 120.0)
|
|
assert result['quality'] in ('subha', 'asubha', 'mixed')
|
|
|
|
def test_27_yogas(self):
|
|
assert len(YOGA_NAMES) == 27
|
|
|
|
def test_vaidhriti_asubha(self):
|
|
assert YOGA_QUALITY['Vaidhriti'] == 'asubha'
|
|
|
|
def test_priti_subha(self):
|
|
assert YOGA_QUALITY['Priti'] == 'subha'
|
|
|
|
|
|
# ── Karana Tests ────────────────────────────────────────────────────
|
|
|
|
class TestKarana:
|
|
def test_kimstughna_first_half(self):
|
|
# Moon-Sun diff near 0 → k_num=0
|
|
result = calc_karana(0.0, 1.0)
|
|
assert result['karana'] == 'Kimstughna'
|
|
|
|
def test_vishti_asubha(self):
|
|
assert KARANA_QUALITY['Vishti'] == 'asubha'
|
|
|
|
def test_karana_quality_present(self):
|
|
result = calc_karana(0.0, 60.0)
|
|
assert result['quality'] in ('subha', 'asubha', 'mixed')
|
|
|
|
def test_11_karana_names(self):
|
|
assert len(KARANA_NAMES) == 11
|
|
|
|
def test_is_vishti_flag(self):
|
|
# Test when karana is Vishti
|
|
result = calc_karana(0.0, 60.0)
|
|
assert isinstance(result['is_vishti'], bool)
|
|
|
|
|
|
# ── Vara Tests ──────────────────────────────────────────────────────
|
|
|
|
class TestVara:
|
|
def test_sunday(self):
|
|
result = calc_vara(0)
|
|
assert result['vara'] == 'Sunday'
|
|
assert result['vara_lord'] == 'Sun'
|
|
assert result['quality'] == 'asubha'
|
|
|
|
def test_monday(self):
|
|
result = calc_vara(1)
|
|
assert result['vara_lord'] == 'Moon'
|
|
assert result['quality'] == 'subha'
|
|
|
|
def test_thursday_jupiter(self):
|
|
result = calc_vara(4)
|
|
assert result['vara_lord'] == 'Jupiter'
|
|
|
|
def test_7_days(self):
|
|
assert len(VARA_LORDS) == 7
|
|
|
|
@pytest.mark.parametrize("idx,expected_lord",
|
|
[(0, 'Sun'), (1, 'Moon'), (2, 'Mars'), (3, 'Mercury'),
|
|
(4, 'Jupiter'), (5, 'Venus'), (6, 'Saturn')])
|
|
def test_all_vara_lords(self, idx, expected_lord):
|
|
result = calc_vara(idx)
|
|
assert result['vara_lord'] == expected_lord
|
|
|
|
|
|
# ── Hora Tests ──────────────────────────────────────────────────────
|
|
|
|
class TestHora:
|
|
def test_hora_lord_calculated(self):
|
|
result = calc_hora(0, 6.0) # Sunday, 6h from sunrise
|
|
assert result['hora_lord'] in ('Sun', 'Moon', 'Mars', 'Mercury',
|
|
'Jupiter', 'Venus', 'Saturn')
|
|
|
|
def test_hora_quality_present(self):
|
|
result = calc_hora(0, 6.0)
|
|
assert result['quality'] in ('subha', 'asubha', 'mixed')
|
|
|
|
def test_hora_num_range(self):
|
|
result = calc_hora(0, 6.0)
|
|
assert 1 <= result['hora_num'] <= 24
|
|
|
|
|
|
# ── Abhijit Muhurta Tests ──────────────────────────────────────────
|
|
|
|
class TestAbhijitMuhurta:
|
|
def test_basic_structure(self):
|
|
result = calc_abhijit_muhurta()
|
|
assert 'duration_minutes' in result
|
|
assert result['duration_minutes'] == 48
|
|
|
|
def test_wednesday_warning(self):
|
|
result = calc_abhijit_muhurta()
|
|
assert 'Wednesday' in result['warning']
|
|
|
|
def test_with_jd_values(self):
|
|
result = calc_abhijit_muhurta(2460000.0, 2460000.5)
|
|
assert 'abhijit_start_jd' in result
|
|
assert 'abhijit_end_jd' in result
|
|
|
|
|
|
# ── Panchanga Complete Tests ────────────────────────────────────────
|
|
|
|
class TestPanchangaComplete:
|
|
def test_five_elements_present(self):
|
|
result = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
assert 'tithi' in result
|
|
assert 'nakshatra' in result
|
|
assert 'yoga' in result
|
|
assert 'karana' in result
|
|
assert 'vara' in result
|
|
|
|
def test_overall_score_range(self):
|
|
result = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
assert 0 <= result['overall_score'] <= 1
|
|
|
|
def test_auspicious_count(self):
|
|
result = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
assert 0 <= result['auspicious_count'] <= 6
|
|
|
|
def test_warnings_list(self):
|
|
result = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
assert isinstance(result['warnings'], list)
|
|
|
|
|
|
# ── Activity Muhurta Tests ─────────────────────────────────────────
|
|
|
|
class TestActivityMuhurta:
|
|
def test_marriage_activity(self):
|
|
panchanga = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
result = check_activity_muhurta(panchanga, 'marriage')
|
|
assert result['verdict'] is not None
|
|
|
|
def test_all_5_activities(self):
|
|
panchanga = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
for act in ['marriage', 'business', 'travel', 'medical', 'education']:
|
|
result = check_activity_muhurta(panchanga, act)
|
|
assert 'verdict' in result
|
|
|
|
def test_unknown_activity_error(self):
|
|
panchanga = calc_panchanga(45.0, 120.0, 4, 6.0)
|
|
result = check_activity_muhurta(panchanga, 'unknown')
|
|
assert 'error' in result
|
|
|
|
def test_good_tithi_for_marriage(self):
|
|
# Create a panchanga with tithi 2 (good for marriage)
|
|
panchanga = calc_panchanga(0.0, 24.0, 4, 6.0) # tithi 3
|
|
result = check_activity_muhurta(panchanga, 'marriage')
|
|
assert result['tithi_eval'] in ('good', 'neutral', 'bad')
|
|
|
|
def test_pushya_nakshatra_good_for_business(self):
|
|
# Pushya nakshatra center ≈ 104°
|
|
panchanga = calc_panchanga(80.0, 104.0, 4, 6.0)
|
|
result = check_activity_muhurta(panchanga, 'business')
|
|
if panchanga['nakshatra']['nakshatra'] == 'Pushya':
|
|
assert result['nakshatra_eval'] == 'good'
|
|
|
|
|
|
# ── Full Report Tests ───────────────────────────────────────────────
|
|
|
|
class TestMuhurtaFullReport:
|
|
def test_report_structure(self):
|
|
result = muhurta_full_report(45.0, 120.0, 4, 6.0, '2026-06-04')
|
|
assert 'panchanga' in result
|
|
assert 'abhijit_muhurta' in result
|
|
assert 'activity_checks' in result
|
|
assert 'summary' in result
|
|
|
|
def test_best_activities_list(self):
|
|
result = muhurta_full_report(45.0, 120.0, 4, 6.0)
|
|
assert isinstance(result['summary']['best_activities'], list)
|
|
|
|
def test_avoid_activities_list(self):
|
|
result = muhurta_full_report(45.0, 120.0, 4, 6.0)
|
|
assert isinstance(result['summary']['avoid_activities'], list)
|
|
|
|
def test_query_date_preserved(self):
|
|
result = muhurta_full_report(45.0, 120.0, 4, 6.0, '2026-06-04')
|
|
assert result['query_date'] == '2026-06-04'
|