275 lines
10 KiB
Python
275 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for nakshatra_advanced.py — Nakshatra identification, Tara, Sub-Lord, Dasha."""
|
|
|
|
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 nakshatra_advanced import (
|
|
find_nakshatra, calc_tara_bala, calc_all_tara_balas,
|
|
calc_vimshottari_start, calc_sub_lord, nakshatra_compatibility,
|
|
calc_chandra_bala, calc_tara_chandra_combined,
|
|
calc_nakshatra_transits_natal, nakshatra_full_report,
|
|
NAK_NAMES, NAK_LORDS, NAK_YEARS, TARA_NAMES,
|
|
)
|
|
|
|
# ── Nakshatra Identification Tests ──────────────────────────────────
|
|
|
|
class TestFindNakshatra:
|
|
def test_0_degrees_ashwini(self):
|
|
result = find_nakshatra(0.0)
|
|
assert result['nakshatra'] == 'Ashwini'
|
|
assert result['nakshatra_idx'] == 0
|
|
|
|
def test_13_33_degrees_bharani(self):
|
|
result = find_nakshatra(13.34)
|
|
assert result['nakshatra'] == 'Bharani'
|
|
|
|
def test_360_degrees_wraps(self):
|
|
result = find_nakshatra(360.0)
|
|
# 360° = 0° → Ashwini
|
|
assert result['nakshatra'] == 'Ashwini'
|
|
|
|
@pytest.mark.parametrize("lon,expected_idx", [
|
|
(0.0, 0), (6.0, 0), (13.34, 1),
|
|
(26.66, 1), (26.67, 2),
|
|
(39.99, 2), (40.0, 3), (53.33, 3), (53.34, 4),
|
|
(180.0, 13), (240.0, 18), (320.0, 24), (346.67, 26),
|
|
])
|
|
def test_nakshatra_indices(self, lon, expected_idx):
|
|
result = find_nakshatra(lon)
|
|
assert result['nakshatra_idx'] == expected_idx
|
|
|
|
def test_pada_range_1_to_4(self):
|
|
for lon in [0.0, 5.0, 10.0, 12.0]:
|
|
result = find_nakshatra(lon)
|
|
assert 1 <= result['pada'] <= 4
|
|
|
|
def test_lord_correct(self):
|
|
result = find_nakshatra(0.0) # Ashwini
|
|
assert result['nakshatra_lord'] == 'Ketu'
|
|
|
|
def test_dasha_years_correct(self):
|
|
result = find_nakshatra(0.0) # Ashwini → Ketu → 7 years
|
|
assert result['dasha_years'] == 7
|
|
|
|
def test_gana_present(self):
|
|
result = find_nakshatra(0.0)
|
|
assert 'gana' in result
|
|
|
|
def test_element_present(self):
|
|
result = find_nakshatra(0.0)
|
|
assert 'element' in result
|
|
|
|
def test_all_27_nakshatras_accessible(self):
|
|
for i in range(27):
|
|
lon = i * (360.0 / 27) + 0.01
|
|
result = find_nakshatra(lon)
|
|
assert result['nakshatra_idx'] == i
|
|
|
|
|
|
# ── Tara Bala Tests ─────────────────────────────────────────────────
|
|
|
|
class TestTaraBala:
|
|
def test_same_nakshatra_janma(self):
|
|
result = calc_tara_bala(0, 0)
|
|
assert result['tara_index'] == 0
|
|
assert result['tara_name'] == 'Janma(生命)'
|
|
|
|
def test_1_step_sampat(self):
|
|
result = calc_tara_bala(0, 1)
|
|
assert result['tara_index'] == 1
|
|
assert result['is_auspicious'] == True
|
|
|
|
def test_2_step_vipat(self):
|
|
result = calc_tara_bala(0, 2)
|
|
assert result['tara_index'] == 2
|
|
assert result['is_dangerous'] == True
|
|
|
|
def test_9_steps_cyclic(self):
|
|
result = calc_tara_bala(0, 9)
|
|
assert result['tara_index'] == 0 # 9 % 9 = 0
|
|
|
|
def test_auspicious_taras(self):
|
|
for d in [1, 3, 5, 7, 8]:
|
|
result = calc_tara_bala(0, d)
|
|
assert result['is_auspicious'] == True
|
|
|
|
def test_dangerous_taras(self):
|
|
for d in [2, 4, 6]:
|
|
result = calc_tara_bala(0, d)
|
|
assert result['is_dangerous'] == True
|
|
|
|
def test_all_tara_balas(self):
|
|
planet_lons = {'Sun': 45.0, 'Moon': 120.0, 'Mars': 200.0}
|
|
result = calc_all_tara_balas(0, planet_lons)
|
|
for pname in planet_lons:
|
|
assert pname in result
|
|
assert 'tara' in result[pname]
|
|
|
|
|
|
# ── Chandra Bala Tests ─────────────────────────────────────────────
|
|
|
|
class TestChandraBala:
|
|
def test_same_sign_janma(self):
|
|
result = calc_chandra_bala(0, 0)
|
|
assert result['rashi_from_moon'] == 0
|
|
assert result['chandra_cn'] == '生命位'
|
|
|
|
def test_1_step_sampat(self):
|
|
result = calc_chandra_bala(0, 1)
|
|
assert result['is_auspicious'] == True
|
|
|
|
def test_6_step_vadha(self):
|
|
result = calc_chandra_bala(0, 6)
|
|
assert result['is_dangerous'] == True
|
|
|
|
def test_8_step_parama_mitra(self):
|
|
result = calc_chandra_bala(0, 8)
|
|
assert result['is_auspicious'] == True
|
|
|
|
def test_quality_classification(self):
|
|
for d in range(12):
|
|
result = calc_chandra_bala(0, d)
|
|
assert result['quality'] in ('auspicious', 'dangerous', 'neutral')
|
|
|
|
|
|
# ── Vimshottari Start Tests ────────────────────────────────────────
|
|
|
|
class TestVimshottariStart:
|
|
def test_moon_nakshatra_correct(self):
|
|
result = calc_vimshottari_start(0.0) # Ashwini
|
|
assert result['moon_nakshatra'] == 'Ashwini'
|
|
assert result['first_mahadasha_lord'] == 'Ketu'
|
|
|
|
def test_remaining_ratio_range(self):
|
|
for lon in [0.01, 6.0, 10.0, 13.0, 350.0]:
|
|
result = calc_vimshottari_start(lon)
|
|
assert 0 <= result['remaining_ratio'] <= 1
|
|
assert 0 <= result['used_ratio'] <= 1
|
|
assert abs(result['remaining_ratio'] + result['used_ratio'] - 1.0) < 0.001
|
|
|
|
def test_remaining_years_positive(self):
|
|
result = calc_vimshottari_start(5.0)
|
|
assert result['first_mahadasha_remaining_years'] > 0
|
|
|
|
def test_pada_present(self):
|
|
result = calc_vimshottari_start(5.0)
|
|
assert 1 <= result['moon_pada'] <= 4
|
|
|
|
|
|
# ── Sub-Lord Tests ──────────────────────────────────────────────────
|
|
|
|
class TestSubLord:
|
|
def test_sub_lord_calculated(self):
|
|
result = calc_sub_lord(5.0)
|
|
assert 'sub_lord' in result
|
|
assert result['sub_lord'] in ['Ketu', 'Venus', 'Sun', 'Moon', 'Mars',
|
|
'Rahu', 'Jupiter', 'Saturn', 'Mercury']
|
|
|
|
def test_sub_lord_index_range(self):
|
|
result = calc_sub_lord(5.0)
|
|
assert 0 <= result['sub_index'] < 9
|
|
|
|
def test_different_lons_different_sub_lords(self):
|
|
subs = set()
|
|
for lon in [0.5, 2.0, 4.0, 7.0, 10.0]:
|
|
result = calc_sub_lord(lon)
|
|
subs.add(result['sub_lord'])
|
|
assert len(subs) >= 2 # Different longitudes should yield different sub-lords
|
|
|
|
def test_nakshatra_lord_matches(self):
|
|
result = calc_sub_lord(0.01)
|
|
assert result['nakshatra_lord'] == 'Ketu' # Ashwini lord
|
|
|
|
|
|
# ── Nakshatra Compatibility Tests ───────────────────────────────────
|
|
|
|
class TestNakshatraCompatibility:
|
|
def test_compatibility_result(self):
|
|
result = nakshatra_compatibility(0, 3) # Ashwini vs Rohini
|
|
assert 'overall' in result
|
|
assert result['overall'] in ('compatible', 'moderate', 'challenging')
|
|
|
|
def test_same_nakshatra_compatible(self):
|
|
result = nakshatra_compatibility(0, 0)
|
|
assert result['tara_score'] >= 1.5
|
|
|
|
def test_element_match(self):
|
|
result = nakshatra_compatibility(0, 2) # Ashwini(fire) vs Krittika(fire)
|
|
assert result['element_match']['compatible'] == True
|
|
|
|
def test_gana_match(self):
|
|
result = nakshatra_compatibility(0, 6) # Ashwini(Dev) vs Punarvasu(Dev)
|
|
assert result['gana_match']['score'] >= 3
|
|
|
|
|
|
# ── Tara+Chandra Combined Tests ────────────────────────────────────
|
|
|
|
class TestTaraChandraCombined:
|
|
def test_combined_analysis(self):
|
|
planet_lons = {'Sun': 45.0, 'Mars': 200.0}
|
|
result = calc_tara_chandra_combined(0, 0, planet_lons)
|
|
for pname in planet_lons:
|
|
assert 'tara' in result[pname]
|
|
assert 'chandra' in result[pname]
|
|
assert 'combined_score' in result[pname]
|
|
|
|
def test_score_categories(self):
|
|
planet_lons = {'Sun': 45.0}
|
|
result = calc_tara_chandra_combined(0, 0, planet_lons)
|
|
for pname in planet_lons:
|
|
assert result[pname]['combined_score'] in (
|
|
'double_auspicious', 'double_dangerous',
|
|
'tara_good_chandra_bad', 'tara_bad_chandra_good',
|
|
'mixed_favorable', 'mixed_unfavorable', 'neutral')
|
|
|
|
|
|
# ── Natal Nakshatra Transits Tests ─────────────────────────────────
|
|
|
|
class TestNakshatraTransitsNatal:
|
|
def test_all_planets_analyzed(self):
|
|
planet_lons = {'Sun': 45.0, 'Moon': 120.0, 'Mars': 200.0}
|
|
result = calc_nakshatra_transits_natal(planet_lons)
|
|
assert len(result) == 3
|
|
for pname in planet_lons:
|
|
assert result[pname]['nakshatra'] in NAK_NAMES
|
|
|
|
def test_details_present(self):
|
|
planet_lons = {'Sun': 45.0}
|
|
result = calc_nakshatra_transits_natal(planet_lons)
|
|
for key in ['nakshatra', 'pada', 'gana', 'element', 'dasha_years']:
|
|
assert key in result['Sun']
|
|
|
|
|
|
# ── Full Report Tests ──────────────────────────────────────────────
|
|
|
|
class TestNakshatraFullReport:
|
|
def test_full_report_structure(self):
|
|
chart_data = {
|
|
'planets': {
|
|
'Sun': {'degree': 45.0},
|
|
'Moon': {'degree': 120.0},
|
|
'Mars': {'degree': 200.0},
|
|
}
|
|
}
|
|
result = nakshatra_full_report(chart_data)
|
|
assert 'natal_nakshatras' in result
|
|
assert 'tara_bala' in result
|
|
assert 'chandra_bala' in result
|
|
assert 'sub_lords' in result
|
|
|
|
def test_power_ranking_present(self):
|
|
chart_data = {
|
|
'planets': {
|
|
'Sun': {'degree': 45.0},
|
|
'Moon': {'degree': 120.0},
|
|
}
|
|
}
|
|
result = nakshatra_full_report(chart_data)
|
|
assert 'power_ranking' in result
|
|
assert len(result['power_ranking']) >= 2
|