|
| 1 | +import unittest |
| 2 | + |
| 3 | +import pysus |
| 4 | +from pysus.ftp import Database |
| 5 | + |
| 6 | + |
| 7 | +class TestAvailableDatabases(unittest.TestCase): |
| 8 | + """Test suite for AVAILABLE_DATABASES registry""" |
| 9 | + |
| 10 | + def test_available_databases_exists(self): |
| 11 | + """Verify AVAILABLE_DATABASES is accessible from pysus namespace""" |
| 12 | + self.assertTrue(hasattr(pysus, "AVAILABLE_DATABASES")) |
| 13 | + self.assertIsInstance(pysus.AVAILABLE_DATABASES, list) |
| 14 | + |
| 15 | + def test_available_databases_not_empty(self): |
| 16 | + """Verify AVAILABLE_DATABASES list contains entries""" |
| 17 | + self.assertGreater(len(pysus.AVAILABLE_DATABASES), 0) |
| 18 | + |
| 19 | + def test_all_are_database_classes(self): |
| 20 | + """Verify all entries inherit from Database base class""" |
| 21 | + for db_class in pysus.AVAILABLE_DATABASES: |
| 22 | + with self.subTest(db_class=db_class): |
| 23 | + self.assertTrue( |
| 24 | + issubclass(db_class, Database), |
| 25 | + f"{db_class.__name__} does not inherit from Database", |
| 26 | + ) |
| 27 | + |
| 28 | + def test_all_have_required_attributes(self): |
| 29 | + """Verify all database classes have name, paths, metadata""" |
| 30 | + for db_class in pysus.AVAILABLE_DATABASES: |
| 31 | + with self.subTest(db_class=db_class): |
| 32 | + db_instance = db_class() |
| 33 | + self.assertTrue( |
| 34 | + hasattr(db_instance, "name"), |
| 35 | + f"{db_class.__name__} missing 'name' attribute", |
| 36 | + ) |
| 37 | + self.assertTrue( |
| 38 | + hasattr(db_instance, "paths"), |
| 39 | + f"{db_class.__name__} missing 'paths' attribute", |
| 40 | + ) |
| 41 | + self.assertTrue( |
| 42 | + hasattr(db_instance, "metadata"), |
| 43 | + f"{db_class.__name__} missing 'metadata' attribute", |
| 44 | + ) |
| 45 | + |
| 46 | + def test_all_have_valid_metadata(self): |
| 47 | + """Verify metadata contains required fields""" |
| 48 | + required_fields = {"long_name", "source", "description"} |
| 49 | + for db_class in pysus.AVAILABLE_DATABASES: |
| 50 | + with self.subTest(db_class=db_class): |
| 51 | + db_instance = db_class() |
| 52 | + metadata_keys = set(db_instance.metadata.keys()) |
| 53 | + self.assertTrue( |
| 54 | + required_fields.issubset(metadata_keys), |
| 55 | + f"{db_class.__name__} metadata missing required fields. " |
| 56 | + f"Expected: {required_fields}, Got: {metadata_keys}", |
| 57 | + ) |
| 58 | + # verify values exist (can be strings or tuples) |
| 59 | + for field in required_fields: |
| 60 | + value = db_instance.metadata[field] |
| 61 | + if field == "source": |
| 62 | + # can be a string or tuple of strings |
| 63 | + self.assertTrue( |
| 64 | + isinstance(value, (str, tuple)), |
| 65 | + f"{db_class.__name__}.metadata['source'] " |
| 66 | + f"must be str or tuple", |
| 67 | + ) |
| 68 | + if isinstance(value, tuple): |
| 69 | + self.assertTrue( |
| 70 | + all(isinstance(s, str) for s in value), |
| 71 | + f"{db_class.__name__}.metadata['source'] " |
| 72 | + f"tuple must contain only strings", |
| 73 | + ) |
| 74 | + else: |
| 75 | + # long_name and description should be strings |
| 76 | + # Note: Some databases may have empty descriptions |
| 77 | + self.assertIsInstance( |
| 78 | + value, |
| 79 | + str, |
| 80 | + f"{db_class.__name__}.metadata['{field}'] " |
| 81 | + f"is not a string", |
| 82 | + ) |
| 83 | + |
| 84 | + def test_expected_databases_present(self): |
| 85 | + """Verify all expected database classes are included""" |
| 86 | + expected_databases = { |
| 87 | + "CIHA", |
| 88 | + "CNES", |
| 89 | + "IBGEDATASUS", |
| 90 | + "PNI", |
| 91 | + "SIA", |
| 92 | + "SIH", |
| 93 | + "SIM", |
| 94 | + "SINAN", |
| 95 | + "SINASC", |
| 96 | + } |
| 97 | + actual_databases = { |
| 98 | + db_class.__name__ for db_class in pysus.AVAILABLE_DATABASES |
| 99 | + } |
| 100 | + self.assertEqual( |
| 101 | + expected_databases, |
| 102 | + actual_databases, |
| 103 | + f"Database list mismatch. " |
| 104 | + f"Missing: {expected_databases - actual_databases}, " |
| 105 | + f"Extra: {actual_databases - expected_databases}", |
| 106 | + ) |
| 107 | + |
| 108 | + def test_can_instantiate_all_databases(self): |
| 109 | + """Verify all database classes can be instantiated without errors""" |
| 110 | + for db_class in pysus.AVAILABLE_DATABASES: |
| 111 | + with self.subTest(db_class=db_class): |
| 112 | + try: |
| 113 | + db_instance = db_class() |
| 114 | + self.assertIsInstance(db_instance, Database) |
| 115 | + except Exception as e: |
| 116 | + self.fail( |
| 117 | + f"Failed to instantiate {db_class.__name__}: {e}" |
| 118 | + ) |
| 119 | + |
| 120 | + def test_list_order_is_consistent(self): |
| 121 | + """Document that the list order is alphabetical by class name""" |
| 122 | + class_names = [ |
| 123 | + db_class.__name__ for db_class in pysus.AVAILABLE_DATABASES |
| 124 | + ] |
| 125 | + sorted_names = sorted(class_names) |
| 126 | + self.assertEqual( |
| 127 | + class_names, |
| 128 | + sorted_names, |
| 129 | + "AVAILABLE_DATABASES should be in alphabetical order", |
| 130 | + ) |
| 131 | + |
| 132 | + def test_usage_example(self): |
| 133 | + """Demonstrate iteration pattern for accessing metadata""" |
| 134 | + databases_info = [] |
| 135 | + for db_class in pysus.AVAILABLE_DATABASES: |
| 136 | + db = db_class() |
| 137 | + databases_info.append( |
| 138 | + { |
| 139 | + "name": db.name, |
| 140 | + "long_name": db.metadata["long_name"], |
| 141 | + "description": db.metadata["description"], |
| 142 | + } |
| 143 | + ) |
| 144 | + |
| 145 | + self.assertEqual(len(databases_info), 9) |
| 146 | + |
| 147 | + # vrify all entries have the expected structure |
| 148 | + for info in databases_info: |
| 149 | + self.assertIn("name", info) |
| 150 | + self.assertIn("long_name", info) |
| 151 | + self.assertIn("description", info) |
| 152 | + self.assertTrue(isinstance(info["name"], str)) |
| 153 | + self.assertTrue(isinstance(info["long_name"], str)) |
| 154 | + self.assertTrue(isinstance(info["description"], str)) |
| 155 | + |
| 156 | + |
| 157 | +if __name__ == "__main__": |
| 158 | + unittest.main() |
0 commit comments