Repository: peopledoc/workalendar
Pull request #561 (2020-10-09 08:36:11)

Add all Spain regions
refs #531

- [x] Tests with a significant number of years to be tested for your calendar.
- [x] Docstrings for the Calendar class and specific methods.
- [x] Use the ``workalendar.registry_tools.iso_register`` decorator to register your new calendar using ISO codes (optional).
- [x] Calendar country / label added to the README.rst file.
- [x] Changelog amended with a mention like: "Added ``<country>`` by ``@pseudo`` (#)". **Note** *Please do NOT change the version number here. It's the project maintainers' duty.*



Patch:
diff --git a/Changelog.md b/Changelog.md
index 4bf57b8..0a44881 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,7 +2,10 @@
 
 ## master (unreleased)
 
-Nothing here yet.
+- Added Spain regions: Andalusia, Aragon, Castile and León, Castilla-La Mancha, Canary Islands, Extremadura, Galicia, Balearic Islands, La Rioja, Community of Madrid, Murcia, Navarre, Asturias, Basque Country, Cantabria, Valencian Community (#531).
+- Added all ISO codes for Spain regions (#531).
+- Refactored Spain test modules (#531).
+- Fix Catalonia calendar by removing *Sant Juan* day, which does not appear to be an official holiday (#531).
 
 ## v12.0.0 (2020-10-02)
 
diff --git a/README.rst b/README.rst
index bd4e362..c7af59d 100644
--- a/README.rst
+++ b/README.rst
@@ -113,7 +113,7 @@ Europe
 * Serbia
 * Slovakia
 * Slovenia
-* Spain (incl. Catalonia)
+* Spain (Andalusia, Aragon, Castile and León, Castilla-La Mancha, Canary Islands, Extremadura, Galicia, Balearic Islands, La Rioja, Community of Madrid, Murcia, Navarre, Asturias, Basque Country, Cantabria, Valencian Community)
 * Sweden
 * Switzerland (Aargau, Appenzell Innerrhoden, Appenzell Ausserrhoden, Bern, Basel-Landschaft, Basel-Stadt, Fribourg, Geneva, Glarus, Graubünden, Jura, Luzern, Neuchâtel, Nidwalden, Obwalden, St. Gallen, Schaffhausen, Solothurn, Schwyz, Thurgau, Ticino, Uri, Vaud, Valais, Zug, Zurich)
 * Turkey
diff --git a/workalendar/europe/__init__.py b/workalendar/europe/__init__.py
index 2f7d399..de466ab 100644
--- a/workalendar/europe/__init__.py
+++ b/workalendar/europe/__init__.py
@@ -30,7 +30,12 @@ from .russia import Russia
 from .serbia import Serbia
 from .slovakia import Slovakia
 from .slovenia import Slovenia
-from .spain import Spain, Catalonia
+from .spain import (
+    Andalusia, Aragon, Spain, Catalonia, CastileAndLeon, CastillaLaMancha,
+    CanaryIslands, Extremadura, Galicia, BalearicIslands, LaRioja,
+    CommunityofMadrid, Murcia, Navarre, Asturias, BasqueCountry, Cantabria,
+    ValencianCommunity,
+)
 from .sweden import Sweden
 from .ukraine import Ukraine
 from .united_kingdom import UnitedKingdom, UnitedKingdomNorthernIreland
@@ -66,7 +71,6 @@ __all__ = (
     'Belarus',
     'Belgium',
     'Bulgaria',
-    'Catalonia',
     'CaymanIslands',
     'Croatia',
     'Cyprus',
@@ -96,7 +100,6 @@ __all__ = (
     'Serbia',
     'Slovakia',
     'Slovenia',
-    'Spain',
     'Sweden',
     'Switzerland',
     'Ukraine',
@@ -117,6 +120,13 @@ __all__ = (
     'Hawick', 'Inverclyde', 'Inverness', 'Kilmarnock', 'Lanark', 'Linlithgow',
     'Lochaber', 'NorthLanarkshire', 'Paisley', 'Perth', 'ScottishBorders',
     'SouthLanarkshire', 'Stirling', 'WestDunbartonshire',
+
+    # Spain
+    'Spain', 'Andalusia', 'Aragon', 'Catalonia', 'CastileAndLeon',
+    'CastillaLaMancha', 'CanaryIslands', 'Extremadura', 'Galicia',
+    'BalearicIslands', 'LaRioja', 'CommunityofMadrid', 'Murcia', 'Navarre',
+    'Asturias', 'BasqueCountry', 'Cantabria', 'ValencianCommunity',
+
     # Switzerland
     'Switzerland',
     'Aargau', 'AppenzellInnerrhoden', 'AppenzellAusserrhoden', 'Bern',
diff --git a/workalendar/europe/spain.py b/workalendar/europe/spain.py
index 3654719..d9d443c 100644
--- a/workalendar/europe/spain.py
+++ b/workalendar/europe/spain.py
@@ -8,10 +8,10 @@ class Spain(WesternCalendar):
 
     # Christian holidays
     include_epiphany = True
-    include_immaculate_conception = True
     include_good_friday = True
     include_assumption = True
     include_all_saints = True
+    include_immaculate_conception = True
 
     # Civil holidays
     include_labour_day = True
@@ -22,6 +22,57 @@ class Spain(WesternCalendar):
     )
 
 
+@iso_register('ES-AN')
+class Andalusia(Spain):
+    "Andalusia"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (2, 28, "Andalusian National Day"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-AR')
+class Aragon(Spain):
+    "Aragon"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (4, 23, "Aragonese National Day"),
+        (12, 20, "Aragon Ombudsman Day"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-CL')
+class CastileAndLeon(Spain):
+    "Castile and León"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (4, 23, "Día de Castilla y León"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-CM')
+class CastillaLaMancha(Spain):
+    "Castilla-La Mancha"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (5, 31, "Día de la Región Castilla-La Mancha"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-CN')
+class CanaryIslands(Spain):
+    "Canary Islands"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (5, 30, "Día de Canarias"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
 @iso_register('ES-CT')
 class Catalonia(Spain):
     "Catalonia"
@@ -31,6 +82,118 @@ class Catalonia(Spain):
     boxing_day_label = "Sant Esteve"
 
     FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
-        (6, 24, "Sant Joan"),
         (9, 11, "Diada nacional de Catalunya"),
     )
+
+
+@iso_register('ES-EX')
+class Extremadura(Spain):
+    "Extremadura"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (9, 8, "Día de Extremadura"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-GA')
+class Galicia(Spain):
+    "Galicia"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (5, 17, "Día das Letras Galegas"),
+        (7, 25, "Santiago Apóstol o Día da Patria Galega"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-IB')
+class BalearicIslands(Spain):
+    "Balearic Islands"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (3, 1, "Dia de les Illes Balears"),
+    )
+    # Christian holidays
+    include_holy_thursday = True  # Also called Maundy thursday
+    include_easter_monday = True
+
+
+@iso_register('ES-RI')
+class LaRioja(Spain):
+    "La Rioja"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (6, 9, "Dia de La Rioja"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-MD')
+class CommunityofMadrid(Spain):
+    "Community of Madrid"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (5, 2, "Fiesta de la Comunidad de Madrid"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-MC')
+class Murcia(Spain):
+    "Region of Murcia"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (6, 9, "Día de la Región de Murcia"),
+        (3, 19, "San José"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-NA')
+class Navarre(Spain):
+    "Navarre"
+    # Christian holidays
+    include_holy_thursday = True  # Also called Maundy thursday
+    include_easter_monday = True
+
+
+@iso_register('ES-AS')
+class Asturias(Spain):
+    "Asturias"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (9, 8, "Día de Asturias"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-PV')
+class BasqueCountry(Spain):
+    "Basque Country"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (10, 25, "Euskadi Eguna"),
+    )
+    # Christian holidays
+    include_holy_thursday = True  # Also called Maundy thursday
+    include_easter_monday = True
+
+
+@iso_register('ES-CB')
+class Cantabria(Spain):
+    "Cantabria"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (9, 15, "Día de Cantabria o Día de La Montaña"),
+    )
+    # Christian holiday
+    include_holy_thursday = True  # Also called Maundy thursday
+
+
+@iso_register('ES-VC')
+class ValencianCommunity(Spain):
+    "Valencian Community"
+    FIXED_HOLIDAYS = Spain.FIXED_HOLIDAYS + (
+        (3, 19, "San José"),
+        (10, 9, "Dia de la Comunitat Valenciana"),
+    )
+    # Christian holiday
+    include_easter_monday = True


Test patch:
diff --git a/workalendar/tests/test_europe.py b/workalendar/tests/test_europe.py
index d01a7dd..d8abde3 100644
--- a/workalendar/tests/test_europe.py
+++ b/workalendar/tests/test_europe.py
@@ -34,7 +34,6 @@ from ..europe import (
     Romania,
     Russia,
     Serbia,
-    Spain, Catalonia,
     Slovenia,
     Ukraine,
     UnitedKingdom,
@@ -1276,81 +1275,6 @@ class PortugalTest(GenericCalendarTest):
         self.assertEqual(holidays[date(2020, 12, 8)], "Imaculada Conceição")
 
 
-class SpainTest(GenericCalendarTest):
-    cal_class = Spain
-
-    def test_year_2015(self):
-        holidays = self.cal.holidays_set(2015)
-        self.assertIn(date(2015, 1, 1), holidays)
-        self.assertIn(date(2015, 1, 6), holidays)
-        self.assertIn(date(2015, 4, 3), holidays)
-        self.assertIn(date(2015, 5, 1), holidays)
-        self.assertIn(date(2015, 8, 15), holidays)
-        self.assertIn(date(2015, 10, 12), holidays)
-        self.assertIn(date(2015, 12, 8), holidays)
-        self.assertIn(date(2015, 12, 25), holidays)
-
-    def test_year_2016(self):
-        holidays = self.cal.holidays_set(2016)
-        self.assertIn(date(2016, 1, 1), holidays)
-        self.assertIn(date(2016, 1, 6), holidays)
-        self.assertIn(date(2016, 3, 25), holidays)
-        self.assertIn(date(2016, 8, 15), holidays)
-        self.assertIn(date(2016, 10, 12), holidays)
-        self.assertIn(date(2016, 11, 1), holidays)
-        self.assertIn(date(2016, 12, 6), holidays)
-        self.assertIn(date(2016, 12, 8), holidays)
-
-    def test_labour_day_label(self):
-        holidays = self.cal.holidays(2020)
-        holidays = dict(holidays)
-        self.assertEqual(
-            holidays[date(2020, 5, 1)], "Día del trabajador")
-
-
-class CataloniaTest(GenericCalendarTest):
-    cal_class = Catalonia
-
-    def test_year_2015(self):
-        holidays = self.cal.holidays_set(2015)
-        self.assertIn(date(2015, 1, 1), holidays)
-        self.assertIn(date(2015, 1, 6), holidays)
-        self.assertIn(date(2015, 4, 3), holidays)
-        self.assertIn(date(2015, 4, 6), holidays)
-        self.assertIn(date(2015, 5, 1), holidays)
-        self.assertIn(date(2015, 6, 24), holidays)
-        self.assertIn(date(2015, 8, 15), holidays)
-        self.assertIn(date(2015, 9, 11), holidays)
-        self.assertIn(date(2015, 10, 12), holidays)
-        self.assertIn(date(2015, 11, 1), holidays)
-        self.assertIn(date(2015, 12, 6), holidays)
-        self.assertIn(date(2015, 12, 8), holidays)
-        self.assertIn(date(2015, 12, 25), holidays)
-        self.assertIn(date(2015, 12, 26), holidays)
-
-    def test_year_2016(self):
-        holidays = self.cal.holidays_set(2016)
-        self.assertIn(date(2016, 1, 1), holidays)
-        self.assertIn(date(2016, 1, 6), holidays)
-        self.assertIn(date(2016, 3, 25), holidays)
-        self.assertIn(date(2016, 3, 28), holidays)
-        self.assertIn(date(2016, 6, 24), holidays)
-        self.assertIn(date(2016, 8, 15), holidays)
-        self.assertIn(date(2016, 9, 11), holidays)
-        self.assertIn(date(2016, 10, 12), holidays)
-        self.assertIn(date(2016, 11, 1), holidays)
-        self.assertIn(date(2016, 12, 6), holidays)
-        self.assertIn(date(2016, 12, 8), holidays)
-        self.assertIn(date(2016, 12, 25), holidays)
-        self.assertIn(date(2016, 12, 26), holidays)
-
-    def test_labour_day_label(self):
-        holidays = self.cal.holidays(2020)
-        holidays = dict(holidays)
-        self.assertEqual(
-            holidays[date(2020, 5, 1)], "Día del trabajador")
-
-
 class SerbiaTest(GenericCalendarTest):
     cal_class = Serbia
 
diff --git a/workalendar/tests/test_registry_europe.py b/workalendar/tests/test_registry_europe.py
index 6fd2268..bace312 100644
--- a/workalendar/tests/test_registry_europe.py
+++ b/workalendar/tests/test_registry_europe.py
@@ -5,11 +5,19 @@ from ..europe import (
     # FranceAlsaceMoselle,  # TODO: Should we add it to the registry?
     Greece, Hungary, Iceland, Ireland, Italy, Latvia, Lithuania, Luxembourg,
     Malta, Monaco, Netherlands, Norway, Poland, Portugal, Romania, Russia,
-    Slovakia, Slovenia, Spain, Catalonia,
+    Slovakia, Slovenia,
     Sweden, UnitedKingdom,
     UnitedKingdomNorthernIreland,
 )
 
+# Spain & regions
+from ..europe import (
+    Spain, Andalusia, Aragon, Catalonia, CastileAndLeon, CastillaLaMancha,
+    CanaryIslands, Extremadura, Galicia, BalearicIslands, LaRioja,
+    CommunityofMadrid, Murcia, Navarre, Asturias, BasqueCountry, Cantabria,
+    ValencianCommunity,
+)
+
 # Switzerland
 from ..europe import (
     Switzerland,
@@ -47,7 +55,10 @@ SWITZERLAND_REGION_CLASSES = (
 )
 
 SPAIN_REGION_CLASSES = (
-    Catalonia,
+    Andalusia, Aragon, Catalonia, CastileAndLeon, CastillaLaMancha,
+    CanaryIslands, Extremadura, Galicia, BalearicIslands, LaRioja,
+    CommunityofMadrid, Murcia, Navarre, Asturias, BasqueCountry, Cantabria,
+    ValencianCommunity,
 )
 
 
diff --git a/workalendar/tests/test_spain.py b/workalendar/tests/test_spain.py
new file mode 100644
index 0000000..f593e12
--- /dev/null
+++ b/workalendar/tests/test_spain.py
@@ -0,0 +1,344 @@
+from datetime import date
+
+from . import GenericCalendarTest
+from ..europe import (
+    Spain, Andalusia, Aragon, Catalonia, CastileAndLeon, CastillaLaMancha,
+    CanaryIslands, Extremadura, Galicia, BalearicIslands, LaRioja,
+    CommunityofMadrid, Murcia, Navarre, Asturias, BasqueCountry, Cantabria,
+    ValencianCommunity
+)
+
+
+class SpainTest(GenericCalendarTest):
+    cal_class = Spain
+
+    def test_common_year_2015(self):
+        holidays = self.cal.holidays_set(2015)
+        self.assertIn(date(2015, 1, 1), holidays)    # New Year
+        self.assertIn(date(2015, 1, 6), holidays)    # Epiphany
+        self.assertIn(date(2015, 4, 3), holidays)    # Good Friday
+        self.assertIn(date(2015, 5, 1), holidays)    # Labour Day
+        self.assertIn(date(2015, 8, 15), holidays)   # Assumption
+        self.assertIn(date(2015, 10, 12), holidays)  # Nation Day
+        self.assertIn(date(2015, 11, 1), holidays)   # All Saints
+        self.assertIn(date(2015, 12, 6), holidays)   # Dia de la Constitución
+        self.assertIn(date(2015, 12, 8), holidays)   # Immaculate conception
+        self.assertIn(date(2015, 12, 25), holidays)  # Christmas
+
+    def test_common_year_2016(self):
+        holidays = self.cal.holidays_set(2016)
+        self.assertIn(date(2016, 1, 1), holidays)    # New Year
+        self.assertIn(date(2016, 1, 6), holidays)    # Epiphany
+        self.assertIn(date(2016, 3, 25), holidays)   # Good Friday
+        self.assertIn(date(2016, 5, 1), holidays)    # Labour Day
+        self.assertIn(date(2016, 8, 15), holidays)   # Assumption
+        self.assertIn(date(2016, 10, 12), holidays)  # Nation Day
+        self.assertIn(date(2016, 11, 1), holidays)   # All Saints
+        self.assertIn(date(2016, 12, 6), holidays)   # Dia de la Constitución
+        self.assertIn(date(2016, 12, 8), holidays)   # Immaculate conception
+        self.assertIn(date(2016, 12, 25), holidays)  # Christmas
+
+    def test_labour_day_label(self):
+        holidays = self.cal.holidays(2020)
+        holidays = dict(holidays)
+        self.assertEqual(
+            holidays[date(2020, 5, 1)], "Día del trabajador")
+
+
+class AndalusiaTest(SpainTest):
+    cal_class = Andalusia
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 2, 28), holidays)  # Andalusian National Day
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 2, 28), holidays)  # Andalusian National Day
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertEqual(len(holidays), 12)
+
+
+class AragonTest(SpainTest):
+    cal_class = Aragon
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 4, 23), holidays)  # Regional Day
+        self.assertIn(date(2019, 12, 20), holidays)  # Aragon Ombudsman Day
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 4, 23), holidays)  # Regional Day
+        self.assertIn(date(2020, 12, 20), holidays)  # Aragon Ombudsman Day
+        self.assertEqual(len(holidays), 13)
+
+
+class CastileAndLeonTest(SpainTest):
+    cal_class = CastileAndLeon
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 4, 23), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 4, 23), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+
+class CastillaLaManchaTest(SpainTest):
+    cal_class = CastillaLaMancha
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 5, 31), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 5, 31), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+
+class CanaryIslandsTest(SpainTest):
+    cal_class = CanaryIslands
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 5, 30), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 5, 30), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+
+class CataloniaTest(SpainTest):
+    cal_class = Catalonia
+
+    def test_region_year_2015(self):
+        holidays = self.cal.holidays_set(2015)
+        self.assertIn(date(2015, 4, 6), holidays)  # Easter Monday
+        # Diada nacional de Catalunya
+        self.assertIn(date(2015, 9, 11), holidays)
+        self.assertIn(date(2015, 12, 26), holidays)  # Sant Esteve
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2016(self):
+        holidays = self.cal.holidays_set(2016)
+        self.assertIn(date(2016, 3, 28), holidays)  # Easter Monday
+        # Diada nacional de Catalunya
+        self.assertIn(date(2016, 9, 11), holidays)
+        self.assertIn(date(2016, 12, 26), holidays)  # Sant Esteve
+        self.assertEqual(len(holidays), 13)
+
+    def test_boxing_day_label(self):
+        holidays = self.cal.holidays(2020)
+        holidays = dict(holidays)
+        self.assertEqual(holidays[date(2020, 12, 26)], "Sant Esteve")
+
+
+class ExtremaduraTest(SpainTest):
+    cal_class = Extremadura
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 9, 8), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 9, 8), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 12)
+
+
+class GaliciaTest(SpainTest):
+    cal_class = Galicia
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 5, 17), holidays)  # Galician Literature Day
+        self.assertIn(date(2019, 7, 25), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 5, 17), holidays)  # Galician Literature Day
+        self.assertIn(date(2020, 7, 25), holidays)  # Regional Day
+        self.assertEqual(len(holidays), 13)
+
+
+class BalearicIslandsTest(SpainTest):
+    cal_class = BalearicIslands
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 3, 1), holidays)  # Balearic National Day
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 4, 22), holidays)  # Easter Monday
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 3, 1), holidays)  # Balearic National Day
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 4, 13), holidays)  # Easter Monday
+        self.assertEqual(len(holidays), 13)
+
+
+class LaRiojaTest(SpainTest):
+    cal_class = LaRioja
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 6, 9), holidays)  # Dia de La Rioja
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 6, 9), holidays)  # Dia de La Rioja
+        self.assertEqual(len(holidays), 12)
+
+
+class CommunityofMadridTest(SpainTest):
+    cal_class = CommunityofMadrid
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        # Fiesta de la Comunidad de Madrid
+        self.assertIn(date(2019, 5, 2), holidays)
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        # Fiesta de la Comunidad de Madrid
+        self.assertIn(date(2020, 5, 2), holidays)
+        self.assertEqual(len(holidays), 12)
+
+
+class MurciaTest(SpainTest):
+    cal_class = Murcia
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 3, 19), holidays)  # San José
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 6, 9), holidays)  # Día de la Región de Murcia
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 3, 19), holidays)  # San José
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 6, 9), holidays)  # Día de la Región de Murcia
+        self.assertEqual(len(holidays), 13)
+
+
+class NavarreTest(SpainTest):
+    cal_class = Navarre
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 4, 22), holidays)  # Easter Monday
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 4, 13), holidays)  # Easter Monday
+        self.assertEqual(len(holidays), 12)
+
+
+class AsturiasTest(SpainTest):
+    cal_class = Asturias
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 9, 8), holidays)  # Día de Asturias
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 9, 8), holidays)  # Día de Asturias
+        self.assertEqual(len(holidays), 12)
+
+
+class BasqueCountryTest(SpainTest):
+    cal_class = BasqueCountry
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2019, 4, 22), holidays)  # Easter Monday
+        self.assertIn(date(2019, 10, 25), holidays)  # Euskadi Eguna
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        self.assertIn(date(2020, 4, 13), holidays)  # Easter Monday
+        self.assertIn(date(2020, 10, 25), holidays)  # Euskadi Eguna
+        self.assertEqual(len(holidays), 13)
+
+
+class CantabriaTest(SpainTest):
+    cal_class = Cantabria
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 4, 18), holidays)  # Maundy/Holy Thursday
+        # Día de Cantabria o Día de La Montaña
+        self.assertIn(date(2019, 9, 15), holidays)
+        self.assertEqual(len(holidays), 12)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 4, 9), holidays)  # Maundy/Holy Thursday
+        # Día de Cantabria o Día de La Montaña
+        self.assertIn(date(2020, 9, 15), holidays)
+        self.assertEqual(len(holidays), 12)
+
+
+class ValencianCommunityTest(SpainTest):
+    cal_class = ValencianCommunity
+
+    def test_region_year_2019(self):
+        holidays = self.cal.holidays_set(2019)
+        self.assertIn(date(2019, 3, 19), holidays)  # San José
+        self.assertIn(date(2019, 4, 22), holidays)  # Easter Monday
+        # Dia de la Comunitat Valenciana
+        self.assertIn(date(2019, 10, 9), holidays)
+        self.assertEqual(len(holidays), 13)
+
+    def test_region_year_2020(self):
+        holidays = self.cal.holidays_set(2020)
+        self.assertIn(date(2020, 3, 19), holidays)  # San José
+        self.assertIn(date(2020, 4, 13), holidays)  # Easter Monday
+        # Dia de la Comunitat Valenciana
+        self.assertIn(date(2020, 10, 9), holidays)
+        self.assertEqual(len(holidays), 13)