Download tests/test_taxonomy.py from HuggingFaceBio/carbon-a-database-explorer: direct link, hf CLI and curl.
- Browser
- Download file 7.08 kB
-
https://huggingface.co/spaces/HuggingFaceBio/carbon-a-database-explorer/resolve/refs%2Fpr%2F2/tests/test_taxonomy.py
- Command line
-
hf download hf://spaces/HuggingFaceBio/carbon-a-database-explorer@refs/pr/2/tests/test_taxonomy.py
-
curl -L -o test_taxonomy.py https://huggingface.co/spaces/HuggingFaceBio/carbon-a-database-explorer/resolve/refs%2Fpr%2F2/tests/test_taxonomy.py
7.08 kB
| import json | |
| import re | |
| import sqlite3 | |
| import unittest | |
| from refresh_common_names import CURATED | |
| from taxonomy import COMMON_NAMES, DATABASE, DEFAULT_PATH, ICON_DIR, ICONS, MAX_ENGLISH, Taxonomy | |
| class TaxonomyTests(unittest.TestCase): | |
| def setUpClass(cls): | |
| cls.taxonomy = Taxonomy() | |
| def columns(self, html): | |
| return sorted({float(x) for x in re.findall(r'<rect x="([\d.]+)" y="[\d.]+" width="14"', html)}) | |
| def test_expansion_keeps_every_ancestor_column(self): | |
| self.assertEqual(len(self.columns(self.taxonomy.view("2759"))), 2) | |
| self.assertEqual(len(self.columns(self.taxonomy.view(DEFAULT_PATH))), 3) | |
| html = self.taxonomy.view("2759/33154/33208") | |
| self.assertEqual(len(self.columns(html)), 4) | |
| self.assertEqual(html.count('class="tree-node is-selected"'), 3) | |
| def test_search_path_expands_lineage(self): | |
| path = self.taxonomy.taxon_path(9606) | |
| self.assertTrue(path.startswith("2759/33154/33208/")) | |
| self.assertTrue(path.endswith("/9606")) | |
| self.assertIn(f'data-route="{path}"', self.taxonomy.view_taxon(9606)) | |
| def test_other_lineages_expand_as_columns(self): | |
| html = self.taxonomy.view("2759/2759~6") | |
| self.assertIn('data-path="2759/2759~6/2759~12"', html) | |
| def test_english_names_label_latin_clades(self): | |
| html = self.taxonomy.view("2759/33154/33208") | |
| for scientific, english in (("Opisthokonta", "animals and fungi"), ("Metazoa", "animals"), | |
| ("Eumetazoa", "animals with true tissues"), ("Porifera", "sponges")): | |
| self.assertIn(f'class="tree-label">{scientific}</text>', html) | |
| self.assertIn(f'class="tree-english">{english}</text>', html) | |
| # A gloss that only repeats the scientific name is dropped by the build. | |
| self.assertIn('class="tree-label">Fungi</text>', html) | |
| self.assertNotIn('class="tree-english">fungi</text>', html) | |
| def test_one_tooltip_per_node(self): | |
| html = self.taxonomy.view(DEFAULT_PATH) | |
| # <title> would render the browser's own tooltip on top of the styled one. | |
| self.assertNotIn("<title>", html) | |
| self.assertIn('data-detail="Viridiplantae (green plants) ·', html) | |
| self.assertEqual(html.count("data-detail="), html.count('class="tree-hit"')) | |
| def test_curated_glosses_match_the_snapshot(self): | |
| with sqlite3.connect(f"{DATABASE.resolve().as_uri()}?mode=ro", uri=True) as conn: | |
| for taxid, (scientific, english) in CURATED.items(): | |
| row = conn.execute("SELECT name FROM taxa WHERE taxid=?", (taxid,)).fetchone() | |
| self.assertIsNotNone(row, f"taxid {taxid} is not in the snapshot") | |
| self.assertEqual(row[0], scientific, f"taxid {taxid}") | |
| self.assertLessEqual(len(english), MAX_ENGLISH, f"taxid {taxid} gloss is clipped in the chart") | |
| def test_published_names_cover_the_curated_table(self): | |
| names = json.loads(COMMON_NAMES.read_text())["names"] | |
| redundant = {t for t, (scientific, english) in CURATED.items() if scientific.casefold() == english.casefold()} | |
| self.assertEqual({int(t) for t in names} & set(CURATED), set(CURATED) - redundant) | |
| self.assertEqual(names["6040"], "sponges") # straight from NCBI Taxonomy | |
| def test_icons_are_free_to_use_and_present(self): | |
| if not ICONS.exists(): | |
| self.skipTest("silhouettes unavailable") | |
| payload = json.loads(ICONS.read_text()) | |
| self.assertTrue(payload["images"]) | |
| for image, meta in payload["images"].items(): | |
| # NonCommercial is legally murky for a company-run Space and ShareAlike | |
| # would reach into the repository; refresh_icons.py filters both out. | |
| self.assertNotIn("-nc", meta["license"], image) | |
| self.assertNotIn("-sa", meta["license"], image) | |
| self.assertTrue((ICON_DIR / f"{image}.svg").is_file(), image) | |
| for taxid, image in payload["taxa"].items(): | |
| self.assertIn(image, payload["images"], taxid) | |
| def test_small_groups_inherit_an_ancestor_icon(self): | |
| if not self.taxonomy.icons: | |
| self.skipTest("silhouettes unavailable") | |
| with sqlite3.connect(f"{DATABASE.resolve().as_uri()}?mode=ro", uri=True) as conn: | |
| conn.row_factory = sqlite3.Row | |
| own, borrowed = self.taxonomy.icon_for(conn, 2759) | |
| self.assertTrue(own) | |
| self.assertFalse(borrowed) | |
| # A taxon with no icon of its own still resolves, through its lineage. | |
| uncovered = next(r['taxid'] for r in conn.execute( | |
| "SELECT taxid FROM taxa WHERE total_count=1 ORDER BY taxid") | |
| if r['taxid'] in self.taxonomy.eukaryote_ids and r['taxid'] not in self.taxonomy.icons) | |
| image, borrowed = self.taxonomy.icon_for(conn, uncovered) | |
| self.assertTrue(image) | |
| self.assertTrue(borrowed) | |
| self.assertTrue((ICON_DIR / f"{image}.svg").is_file()) | |
| def test_borrowed_icons_never_repeat_within_a_column(self): | |
| if not self.taxonomy.icons: | |
| self.skipTest("silhouettes unavailable") | |
| for path in ("2759", DEFAULT_PATH, "2759/33154/33208", "2759/33154/33208/6072/33213"): | |
| html = self.taxonomy.view(path) | |
| # Columns are laid out left to right, so group the icons by their x. | |
| drawn = re.findall(r'<image class="tree-icon" x="([\d.]+)"[^>]*?/data/icons/([0-9a-f-]+)\.svg"', html) | |
| columns = {} | |
| for x, image in drawn: | |
| columns.setdefault(round(float(x)), []).append(image) | |
| for x, images in columns.items(): | |
| self.assertEqual(len(images), len(set(images)), f"{path} column at {x}") | |
| def test_chart_references_icons_by_url(self): | |
| if not self.taxonomy.icons: | |
| self.skipTest("silhouettes unavailable") | |
| html = self.taxonomy.view(DEFAULT_PATH) | |
| self.assertIn('class="tree-icon"', html) | |
| for image in re.findall(r'href="[^"]*/data/icons/([0-9a-f-]+)\.svg"', html): | |
| self.assertIn(image, self.taxonomy.icon_credits) | |
| def test_viewbox_spans_the_whole_chart(self): | |
| # A stray local named width or height inside the node loop once shrank the | |
| # viewBox to 23x23, which renders as a blank chart with every element intact. | |
| for path in ("2759", DEFAULT_PATH, "2759/33154/33208"): | |
| box = re.search(r'<svg viewBox="0 0 ([\d.]+) ([\d.]+)"', self.taxonomy.view(path)) | |
| self.assertIsNotNone(box, path) | |
| self.assertGreater(float(box.group(1)), 500, path) | |
| self.assertGreater(float(box.group(2)), 400, path) | |
| def test_rejects_paths_outside_the_tree(self): | |
| for path in ("1", "33208", "2759/33208", "2759/2759~3", "2759/9606", "abc"): | |
| with self.assertRaises(ValueError, msg=path): | |
| self.taxonomy.view(path) | |
| if __name__ == "__main__": | |
| unittest.main() | |