Skip to content

Commit 3ef868a

Browse files
Elarwei001claude
authored andcommitted
test(reactome): cover remaining lines for codecov (#114)
Add a network-free TestReactomeOffline class that mocks http_json to cover _strip_html passthrough, the pathways/search/entity parsing, verbose logging, 404 and non-404 error branches, the entity name fallback/summation, and resource/query validation. gget_reactome.py now 98% (only the import-time PackageNotFoundError version fallback, lines 16-17, remains, which is un-coverable in an installed environment). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 1488b3b commit 3ef868a

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

tests/test_reactome.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import json
22
import unittest
3+
from unittest.mock import patch
34

5+
import gget.gget_reactome as gget_reactome
46
import pandas as pd
57
from gget.gget_reactome import reactome
68

@@ -61,5 +63,113 @@ def test_reactome_pathways_no_results_network(self):
6163
self.assertEqual(list(df.columns), ["stable_id", "name", "species", "schema_class", "in_disease"])
6264

6365

66+
class TestReactomeOffline(unittest.TestCase):
67+
"""Network-free tests of the Reactome parsing/branch logic (issue #114).
68+
69+
All HTTP access goes through gget_reactome.http_json, which is mocked here.
70+
"""
71+
72+
def test_strip_html_passthrough(self):
73+
# Non-string values pass through unchanged.
74+
self.assertIsNone(gget_reactome._strip_html(None))
75+
self.assertEqual(gget_reactome._strip_html(123), 123)
76+
self.assertEqual(gget_reactome._strip_html("<span>TP53</span>"), "TP53")
77+
78+
@patch.object(gget_reactome, "http_json")
79+
def test_pathways_parsing_verbose(self, mock_http):
80+
mock_http.return_value = [
81+
{
82+
"stId": "R-HSA-1",
83+
"displayName": "Pathway A",
84+
"speciesName": "Homo sapiens",
85+
"schemaClass": "Pathway",
86+
"isInDisease": False,
87+
}
88+
]
89+
df = reactome("P04637", resource="pathways", species="Homo sapiens", verbose=True)
90+
self.assertEqual(df.iloc[0]["stable_id"], "R-HSA-1")
91+
self.assertEqual(df.iloc[0]["species"], "Homo sapiens")
92+
93+
@patch.object(gget_reactome, "http_json")
94+
def test_pathways_404_returns_empty(self, mock_http):
95+
mock_http.side_effect = RuntimeError("Reactome returned HTTP 404")
96+
df = reactome("NOTREAL", resource="pathways", verbose=False)
97+
self.assertEqual(len(df), 0)
98+
99+
@patch.object(gget_reactome, "http_json")
100+
def test_pathways_other_error_raises(self, mock_http):
101+
mock_http.side_effect = RuntimeError("Reactome returned HTTP 500")
102+
with self.assertRaises(RuntimeError):
103+
reactome("P04637", resource="pathways", verbose=False)
104+
105+
@patch.object(gget_reactome, "http_json")
106+
def test_search_parsing_species_types_verbose(self, mock_http):
107+
mock_http.return_value = {
108+
"results": [
109+
{
110+
"entries": [
111+
{
112+
"stId": "R-HSA-9",
113+
"name": "<span class='highlighting'>TP53</span>",
114+
"exactType": "Protein",
115+
"species": ["Homo sapiens"],
116+
"id": 12345,
117+
}
118+
]
119+
}
120+
]
121+
}
122+
df = reactome("TP53", resource="search", species="9606", types="Protein", verbose=True)
123+
self.assertEqual(df.iloc[0]["stable_id"], "R-HSA-9")
124+
self.assertEqual(df.iloc[0]["name"], "TP53") # HTML stripped
125+
self.assertEqual(df.iloc[0]["species"], "Homo sapiens") # list flattened
126+
127+
@patch.object(gget_reactome, "http_json")
128+
def test_search_404_returns_empty(self, mock_http):
129+
mock_http.side_effect = RuntimeError("Reactome returned HTTP 404")
130+
df = reactome("zzzz", resource="search", verbose=False)
131+
self.assertEqual(len(df), 0)
132+
133+
@patch.object(gget_reactome, "http_json")
134+
def test_search_other_error_raises(self, mock_http):
135+
mock_http.side_effect = RuntimeError("Reactome returned HTTP 503")
136+
with self.assertRaises(RuntimeError):
137+
reactome("TP53", resource="search", verbose=False)
138+
139+
@patch.object(gget_reactome, "http_json")
140+
def test_entity_name_fallback_and_summation(self, mock_http):
141+
# displayName missing -> fall back to first of name list; summation HTML stripped.
142+
mock_http.return_value = {
143+
"stId": "R-HSA-6804754",
144+
"displayName": None,
145+
"name": ["Regulation of TP53 Activity"],
146+
"schemaClass": "Pathway",
147+
"speciesName": "Homo sapiens",
148+
"isInDisease": False,
149+
"summation": [{"text": "<p>Some <b>summary</b>.</p>"}],
150+
}
151+
result = reactome("R-HSA-6804754", resource="entity", json=True, verbose=True)
152+
self.assertEqual(result[0]["name"], "Regulation of TP53 Activity")
153+
self.assertEqual(result[0]["summation"], "Some summary.")
154+
155+
@patch.object(gget_reactome, "http_json")
156+
def test_entity_404_raises_valueerror(self, mock_http):
157+
mock_http.side_effect = RuntimeError("Reactome returned HTTP 404")
158+
with self.assertRaises(ValueError):
159+
reactome("R-HSA-0", resource="entity", verbose=False)
160+
161+
@patch.object(gget_reactome, "http_json")
162+
def test_entity_other_error_raises(self, mock_http):
163+
mock_http.side_effect = RuntimeError("Reactome returned HTTP 500")
164+
with self.assertRaises(RuntimeError):
165+
reactome("R-HSA-6804754", resource="entity", verbose=False)
166+
167+
def test_invalid_resource_and_empty_query(self):
168+
with self.assertRaises(ValueError):
169+
reactome("TP53", resource="banana", verbose=False)
170+
with self.assertRaises(ValueError):
171+
reactome(" ", resource="pathways", verbose=False)
172+
173+
64174
if __name__ == "__main__":
65175
unittest.main()

0 commit comments

Comments
 (0)