Skip to content

Commit 1bb97fc

Browse files
committed
Adding append subcommand unittests
1 parent 97c15ce commit 1bb97fc

2 files changed

Lines changed: 110 additions & 5 deletions

File tree

taxtastic/subcommands/append.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ def action(args):
7676
}
7777

7878
log.info('fetching lineages for {} tax_ids'.format(len(tax_ids)))
79-
lineage_rows = tax._get_lineage_table(tax_ids)
80-
81-
# build {tid: {rank: tax_name}}
8279
lineages = defaultdict(dict)
83-
for tid, _tax_id, _parent_id, rank, tax_name in lineage_rows:
84-
lineages[tid][rank] = (_tax_id, tax_name)
80+
try:
81+
lineage_rows = tax._get_lineage_table(tax_ids)
82+
for tid, _tax_id, _parent_id, rank, tax_name in lineage_rows:
83+
lineages[tid][rank] = (_tax_id, tax_name)
84+
except ValueError:
85+
log.warning('no tax_ids were found in the database')
8586

8687
missing = tax_ids - set(lineages)
8788
if missing:

tests/test_subcommand_append.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python
2+
import csv
3+
import sys
4+
import unittest
5+
from io import StringIO
6+
7+
from sqlalchemy import create_engine
8+
9+
from taxtastic.subcommands import append
10+
from taxtastic.taxonomy import Taxonomy
11+
12+
from . import config
13+
from .config import TestBase
14+
15+
dbname = config.ncbi_master_db
16+
17+
18+
class Args:
19+
schema = None
20+
verbosity = 0
21+
tax_id_column = 'tax_id'
22+
23+
24+
class TestAppendAction(TestBase):
25+
26+
def setUp(self):
27+
self.engine = create_engine('sqlite:///%s' % dbname)
28+
self.tax = Taxonomy(self.engine)
29+
30+
def tearDown(self):
31+
self.engine.dispose()
32+
33+
def _make_args(self, rows, columns):
34+
buf = StringIO()
35+
writer = csv.DictWriter(buf, fieldnames=list(rows[0].keys()))
36+
writer.writeheader()
37+
writer.writerows(rows)
38+
buf.seek(0)
39+
40+
args = Args()
41+
args.url = 'sqlite:///%s' % dbname
42+
args.infile = buf
43+
args.columns = columns
44+
args.outfile = StringIO()
45+
return args
46+
47+
def test_appends_genus_and_species_name(self):
48+
"""Normal case: valid tax_ids get genus and species_name appended."""
49+
rows = [
50+
{'seqname': 'seq1', 'tax_id': '1280'}, # Staphylococcus aureus
51+
{'seqname': 'seq2', 'tax_id': '1378'}, # Gemella
52+
]
53+
args = self._make_args(rows, ['genus', 'species_name'])
54+
append.action(args)
55+
56+
args.outfile.seek(0)
57+
result = list(csv.DictReader(args.outfile))
58+
59+
self.assertEqual(len(result), 2)
60+
self.assertIn('genus', result[0])
61+
self.assertIn('species_name', result[0])
62+
63+
# Staphylococcus aureus (1280) should have a genus tax_id
64+
self.assertTrue(result[0]['genus'])
65+
self.assertEqual(
66+
result[0]['species_name'], 'Staphylococcus aureus')
67+
68+
def test_existing_columns_not_duplicated(self):
69+
"""Columns already in the CSV are not added twice to fieldnames."""
70+
rows = [{'tax_id': '1280', 'genus': 'existing_value'}]
71+
args = self._make_args(rows, ['genus'])
72+
append.action(args)
73+
74+
args.outfile.seek(0)
75+
reader = csv.DictReader(args.outfile)
76+
self.assertEqual(reader.fieldnames.count('genus'), 1)
77+
78+
def test_missing_tax_id_produces_empty_columns(self):
79+
"""Tax_ids not found in the database produce empty column values."""
80+
rows = [{'tax_id': 'invalid_tax_id_999'}]
81+
args = self._make_args(rows, ['genus', 'species_name'])
82+
append.action(args)
83+
84+
args.outfile.seek(0)
85+
result = list(csv.DictReader(args.outfile))
86+
87+
self.assertEqual(len(result), 1)
88+
self.assertEqual(result[0]['genus'], '')
89+
self.assertEqual(result[0]['species_name'], '')
90+
91+
def test_output_preserves_input_columns(self):
92+
"""All original columns are preserved in the output."""
93+
rows = [
94+
{'seqname': 'seq1', 'description': 'a desc', 'tax_id': '1280'},
95+
]
96+
args = self._make_args(rows, ['species_name'])
97+
append.action(args)
98+
99+
args.outfile.seek(0)
100+
result = list(csv.DictReader(args.outfile))
101+
102+
self.assertEqual(result[0]['seqname'], 'seq1')
103+
self.assertEqual(result[0]['description'], 'a desc')
104+
self.assertEqual(result[0]['tax_id'], '1280')

0 commit comments

Comments
 (0)