-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_batch_integration.py
More file actions
193 lines (164 loc) · 8.03 KB
/
Copy pathtest_batch_integration.py
File metadata and controls
193 lines (164 loc) · 8.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
"""
Integration tests for batch SDK methods against a live API.
These tests validate that batch operations work end-to-end with real API responses,
using actual parse functions (no mocks). They require a running API server at
http://localhost:3000/api.
Run via: pytest tests/python/test_batch_integration.py -v
Requirements:
- pytest
- Running API server: cd crates/genomehubs-api && cargo run
"""
import pytest
from cli_generator import QueryBuilder, parse_batch_json, parse_lookup_json, parse_record_json
API_BASE = "http://localhost:3000/api"
SKIP_REASON = "Requires live API server at http://localhost:3000"
@pytest.fixture
def api_available():
"""Check if API server is running before running integration tests."""
import urllib.request
try:
urllib.request.urlopen(f"{API_BASE}/v3/search?q=test", timeout=2)
return True
except Exception:
pytest.skip(SKIP_REASON)
class TestBatchIntegration:
"""Integration tests for batch operations."""
def test_search_batch_single_query(self, api_available):
"""Test searchBatch with a single query."""
qb = QueryBuilder("taxon")
query = QueryBuilder("taxon").set_taxa(["Canis lupus"])
result = qb.search_batch([query], api_base=API_BASE)
assert isinstance(result, list)
assert len(result) > 0
def test_search_batch_multiple_queries(self, api_available):
"""Test searchBatch with 10 queries."""
qb = QueryBuilder("taxon")
queries = [
QueryBuilder("taxon").set_taxa(["Canis lupus"]),
QueryBuilder("taxon").set_taxa(["Felis catus"]),
QueryBuilder("taxon").set_taxa(["Mus musculus"]),
QueryBuilder("taxon").set_taxa(["Danio rerio"]),
QueryBuilder("taxon").set_taxa(["Drosophila melanogaster"]),
QueryBuilder("taxon").set_taxa(["Arabidopsis thaliana"]),
QueryBuilder("taxon").set_taxa(["Oryza sativa"]),
QueryBuilder("taxon").set_taxa(["Zea mays"]),
QueryBuilder("taxon").set_taxa(["Solanum lycopersicum"]),
QueryBuilder("taxon").set_taxa(["Triticum aestivum"]),
]
result = qb.search_batch(queries, api_base=API_BASE)
assert isinstance(result, list)
assert len(result) == 10
def test_search_batch_boundary_100_queries(self, api_available):
"""Test searchBatch with exactly 100 queries (max boundary)."""
qb = QueryBuilder("taxon")
queries = [QueryBuilder("taxon").set_taxa(["Canis lupus"]) for _ in range(100)]
result = qb.search_batch(queries, api_base=API_BASE)
assert isinstance(result, list)
assert len(result) == 100
def test_count_batch_single_query(self, api_available):
"""Test countBatch with a single query."""
qb = QueryBuilder("taxon")
query = QueryBuilder("taxon").set_taxa(["Mammalia"])
result = qb.count_batch([query], api_base=API_BASE)
assert isinstance(result, list)
assert len(result) == 1
assert isinstance(result[0], int)
assert result[0] > 0
def test_count_batch_multiple_queries(self, api_available):
"""Test countBatch with 5 queries returns hit counts for each."""
qb = QueryBuilder("taxon")
queries = [
QueryBuilder("taxon").set_taxa(["Mammalia"]),
QueryBuilder("taxon").set_taxa(["Aves"]),
QueryBuilder("taxon").set_taxa(["Reptilia"]),
QueryBuilder("taxon").set_taxa(["Amphibia"]),
QueryBuilder("taxon").set_taxa(["Pisces"]),
]
result = qb.count_batch(queries, api_base=API_BASE)
assert isinstance(result, list)
assert len(result) == 5
assert all(isinstance(count, int) for count in result)
assert all(count >= 0 for count in result)
def test_count_batch_empty_result(self, api_available):
"""Test countBatch handles query with no results gracefully."""
qb = QueryBuilder("taxon")
query = QueryBuilder("taxon").set_taxa(["NonExistentSpecies"])
result = qb.count_batch([query], api_base=API_BASE)
assert isinstance(result, list)
assert len(result) == 1
assert result[0] >= 0 # Should return 0 or non-error value
def test_record_single_taxon(self, api_available):
"""Test record() with a single taxon lookup."""
qb = QueryBuilder("taxon")
result = qb.record("taxon-9646", "taxon") # Canis lupus
assert isinstance(result, dict)
assert len(result) > 0
def test_lookup_taxon_name(self, api_available):
"""Test lookup() with a taxon name."""
qb = QueryBuilder("taxon").set_taxa(["Homo"])
result = qb.lookup("Homo", api_base=API_BASE)
assert isinstance(result, (dict, list))
def test_summary_with_field(self, api_available):
"""Test summary() with a field aggregation."""
qb = QueryBuilder("taxon").set_taxa(["Canis lupus"]).add_field("genome_size")
result = qb.summary("9646", "genome_size", api_base=API_BASE)
assert isinstance(result, (dict, list))
def test_search_batch_with_fields(self, api_available):
"""Test searchBatch with field additions."""
qb = QueryBuilder("taxon")
queries = [
QueryBuilder("taxon").set_taxa(["Mammalia"]).add_field("genome_size"),
QueryBuilder("taxon").set_taxa(["Aves"]).add_field("genome_size"),
]
result = qb.search_batch(queries, api_base=API_BASE)
assert isinstance(result, list)
assert len(result) == 2
def test_count_batch_ordering(self, api_available):
"""Test that countBatch returns results in the same order as queries."""
qb = QueryBuilder("taxon")
query_taxa = [
["Mammalia"],
["Aves"],
["Reptilia"],
]
queries = [QueryBuilder("taxon").set_taxa(taxa) for taxa in query_taxa]
result = qb.count_batch(queries, api_base=API_BASE)
assert len(result) == len(queries)
# Results should be in same order as queries (can't assert specific values
# since API data may vary, but can assert ordering is consistent)
def test_search_batch_response_parsing(self, api_available):
"""Test that searchBatch response is properly parsed."""
qb = QueryBuilder("taxon")
query = QueryBuilder("taxon").set_taxa(["Canis lupus"])
result = qb.search_batch([query], api_base=API_BASE)
# Result should be a list of records (each record from a result object)
assert isinstance(result, list)
# Each result should be a dict with record data
for record in result:
assert isinstance(record, dict)
class TestBatchIntegrationErrorHandling:
"""Integration tests for error conditions."""
def test_search_batch_invalid_api_base(self):
"""Test searchBatch with invalid API base."""
qb = QueryBuilder("taxon")
query = QueryBuilder("taxon").set_taxa(["Canis lupus"])
with pytest.raises(Exception): # Should raise connection or HTTP error
qb.search_batch([query], api_base="http://invalid.example.com:9999")
def test_count_batch_invalid_api_base(self):
"""Test countBatch with invalid API base."""
qb = QueryBuilder("taxon")
query = QueryBuilder("taxon").set_taxa(["Mammalia"])
with pytest.raises(Exception):
qb.count_batch([query], api_base="http://invalid.example.com:9999")
def test_search_batch_exceeds_limit(self):
"""Test that searchBatch raises error for >100 queries."""
qb = QueryBuilder("taxon")
queries = [QueryBuilder("taxon") for _ in range(101)]
with pytest.raises(ValueError, match="maximum 100 searches"):
qb.search_batch(queries, api_base=API_BASE)
def test_count_batch_exceeds_limit(self):
"""Test that countBatch raises error for >100 queries."""
qb = QueryBuilder("taxon")
queries = [QueryBuilder("taxon") for _ in range(101)]
with pytest.raises(ValueError, match="maximum 100 searches"):
qb.count_batch(queries, api_base=API_BASE)