forked from ElsevierDev/elsapy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_elsapy.py
350 lines (279 loc) · 14.4 KB
/
test_elsapy.py
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
"""Test cases for elsapy"""
## TODO:
## - break down in modules (test suites) for each class to allow faster unit-testing
## - this will require a shared 'utility class'
## - add a module that integrates all
from elsapy.elsclient import ElsClient
from elsapy.elsprofile import ElsAuthor, ElsAffil
from elsapy.elsdoc import FullDoc, AbsDoc
from elsapy.elssearch import ElsSearch
from urllib.parse import quote_plus as url_encode
import json, pathlib
## Load good client configuration
conFile = open("config.json")
config = json.load(conFile)
conFile.close()
## Set local path for test data and ensure it's clean
test_path = pathlib.Path.cwd() / 'test_data'
if not test_path.exists():
test_path.mkdir()
else:
file_list = list(test_path.glob('*'))
## TODO: write recursive function that also identifies and clears out child directories
for e in file_list:
if e.is_file():
e.unlink()
class util:
"""Contains tests common to test cases from multiple classes"""
def file_exist_with_id(id):
"""Test case: exactly one local file exist with given ID in the filename"""
if len(list(test_path.glob('*' + id +'*'))) == 1:
return True
class TestElsClient:
"""Test general client functionality"""
def test_init_apikey_(self):
"""Test case: APIkey and token are set correctly during initialization"""
my_client = ElsClient(config['apikey'])
assert my_client.api_key == config['apikey']
assert my_client.inst_token == None
def test_init_apikey_insttoken(self):
"""Test case: APIkey and insttoken are set correctly during initialization"""
my_client = ElsClient(config['apikey'], inst_token = config['insttoken'])
assert my_client.api_key == config['apikey']
assert my_client.inst_token == config['insttoken']
def test_init_apikey_insttoken_path(self):
"""Test case: APIkey, insttoken and local path are set correctly during initialization"""
loc_dir = '\\TEMP'
my_client = ElsClient(config['apikey'], inst_token = config['insttoken'], local_dir = loc_dir)
assert my_client.api_key == config['apikey']
assert my_client.inst_token == config['insttoken']
assert str(my_client.local_dir) == loc_dir
def test_set_apikey_insttoken(self):
"""Test case: APIkey and insttoken are set correctly using setters"""
my_client = ElsClient("dummy")
my_client.api_key = config['apikey']
my_client.inst_token = config['insttoken']
assert my_client.api_key == config['apikey']
assert my_client.inst_token == config['insttoken']
class TestElsAuthor:
"""Test author object functionality"""
## Test data
auth_uri = "https://api.elsevier.com/content/author/author_id/55070335500"
auth_id_int = 55070335500
auth_id_str = "55070335500"
## Test initialization
def test_init_uri(self):
""" Test case: uri is set correctly during initialization with uri"""
myAuth = ElsAuthor(uri = self.auth_uri)
assert myAuth.uri == self.auth_uri
def test_init_auth_id_int(self):
""" Test case: uri is set correctly during initialization with author id as integer"""
myAuth = ElsAuthor(author_id = self.auth_id_int)
assert myAuth.uri == self.auth_uri
def test_init_auth_id_str(self):
""" Test case: uri is set correctly during initialization with author id as string"""
myAuth = ElsAuthor(author_id = self.auth_id_str)
assert myAuth.uri == self.auth_uri
## Test reading/writing author profile data
bad_client = ElsClient("dummy")
good_client = ElsClient(config['apikey'], inst_token = config['insttoken'])
good_client.local_dir = str(test_path)
myAuth = ElsAuthor(uri = auth_uri)
def test_read_good_bad_client(self):
"""Test case: using a well-configured client leads to successful read
and using a badly-configured client does not."""
assert self.myAuth.read(self.bad_client) == False
assert self.myAuth.read(self.good_client) == True
def test_json_to_dict(self):
"""Test case: the JSON read by the author object from the API is parsed
into a Python dictionary"""
assert type(self.myAuth.data) == dict
def test_name_getter(self):
"""Test case: the full name attribute is returned as a non-empty string"""
assert (type(self.myAuth.full_name) == str and self.myAuth.full_name != '')
def test_write(self):
"""Test case: the author object's data is written to a file with the author
ID in the filename"""
self.myAuth.write()
assert util.file_exist_with_id(self.myAuth.data['coredata']['dc:identifier'].split(':')[1])
def test_read_docs(self):
self.myAuth.read_docs()
assert len(self.myAuth.doc_list) > 0
## TODO: once author metrics inconsistency is resolved, change to:
# assert len(self.myAuth.doc_list) == int(self.myAuth.data['coredata']['document-count'])
def test_read_metrics_new_author(self):
myAuth = ElsAuthor(uri = self.auth_uri)
myAuth.read_metrics(self.good_client)
assert (
myAuth.data['coredata']['citation-count'] and
myAuth.data['coredata']['cited-by-count'] and
myAuth.data['coredata']['document-count'] and
myAuth.data['h-index'])
def test_read_metrics_existing_author(self):
self.myAuth.read_metrics(self.good_client)
assert (
self.myAuth.data['coredata']['citation-count'] and
self.myAuth.data['coredata']['cited-by-count'] and
self.myAuth.data['coredata']['document-count'] and
self.myAuth.data['h-index'])
class TestElsAffil:
"""Test affiliation functionality"""
## Test data
aff_uri = "https://api.elsevier.com/content/affiliation/affiliation_id/60101411"
aff_id_int = 60101411
aff_id_str = "60101411"
## Test initialization
def test_init_uri(self):
""" Test case: uri is set correctly during initialization with uri"""
myAff = ElsAffil(uri = self.aff_uri)
assert myAff.uri == self.aff_uri
def test_init_aff_id_int(self):
""" Test case: uri is set correctly during initialization with affiliation id as integer"""
myAff = ElsAffil(affil_id = self.aff_id_int)
assert myAff.uri == self.aff_uri
def test_init_aff_id_str(self):
""" Test case: uri is set correctly during initialization with affiliation id as string"""
myAff = ElsAffil(affil_id = self.aff_id_str)
assert myAff.uri == self.aff_uri
## Test reading/writing author profile data
bad_client = ElsClient("dummy")
good_client = ElsClient(config['apikey'], inst_token = config['insttoken'])
good_client.local_dir = str(test_path)
myAff = ElsAffil(uri = aff_uri)
def test_read_good_bad_client(self):
"""Test case: using a well-configured client leads to successful read
and using a badly-configured client does not."""
assert self.myAff.read(self.bad_client) == False
assert self.myAff.read(self.good_client) == True
def test_json_to_dict(self):
"""Test case: the JSON read by the author object from the API is parsed
into a Python dictionary"""
assert type(self.myAff.data) == dict
def test_name_getter(self):
"""Test case: the name attribute is returned as a non-empty string"""
assert (type(self.myAff.name) == str and self.myAff.name != '')
def test_write(self):
"""Test case: the author object's data is written to a file with the author
ID in the filename"""
self.myAff.write()
assert util.file_exist_with_id(self.myAff.data['coredata']['dc:identifier'].split(':')[1])
def test_read_docs(self):
self.myAff.read_docs()
assert len(self.myAff.doc_list) == int(self.myAff.data['coredata']['document-count'])
class TestAbsDoc:
"""Test Scopus document functionality"""
## Test data
abs_uri = "https://api.elsevier.com/content/abstract/scopus_id/84872135457"
scp_id_int = 84872135457
scp_id_str = "84872135457"
## Test initialization
def test_init_uri(self):
""" Test case: uri is set correctly during initialization with uri"""
myAbsDoc = AbsDoc(uri = self.abs_uri)
assert myAbsDoc.uri == self.abs_uri
def test_init_scp_id_int(self):
""" Test case: uri is set correctly during initialization with Scopus id as integer"""
myAbsDoc = AbsDoc(scp_id = self.scp_id_int)
assert myAbsDoc.uri == self.abs_uri
def test_init_scp_id_str(self):
""" Test case: uri is set correctly during initialization with Scopus id as string"""
myAbsDoc = AbsDoc(scp_id = self.scp_id_str)
assert myAbsDoc.uri == self.abs_uri
## Test reading/writing author profile data
bad_client = ElsClient("dummy")
good_client = ElsClient(config['apikey'], inst_token = config['insttoken'])
good_client.local_dir = str(test_path)
myAbsDoc = AbsDoc(uri = abs_uri)
def test_read_good_bad_client(self):
"""Test case: using a well-configured client leads to successful read
and using a badly-configured client does not."""
assert self.myAbsDoc.read(self.bad_client) == False
assert self.myAbsDoc.read(self.good_client) == True
def test_json_to_dict(self):
"""Test case: the JSON read by the abstract document object from the
API is parsed into a Python dictionary"""
assert type(self.myAbsDoc.data) == dict
def test_title_getter(self):
"""Test case: the title attribute is returned as a non-empty string"""
assert (type(self.myAbsDoc.title) == str and self.myAbsDoc.title != '')
def test_write(self):
"""Test case: the abstract document object's data is written to a file with the Scopus
ID in the filename"""
self.myAbsDoc.write()
assert util.file_exist_with_id(self.myAbsDoc.data['coredata']['dc:identifier'].split(':')[1])
class TestFullDoc:
"""Test ScienceDirect article functionality"""
## Test data
full_pii_uri = "https://api.elsevier.com/content/article/pii/S1674927814000082"
sd_pii = 'S1674927814000082'
full_doi_uri = "https://api.elsevier.com/content/article/doi/10.1016/S1525-1578(10)60571-5"
doi = '10.1016/S1525-1578(10)60571-5'
## Test initialization
def test_init_uri(self):
""" Test case: uri is set correctly during initialization with uri"""
myFullDoc = FullDoc(uri = self.full_pii_uri)
assert myFullDoc.uri == self.full_pii_uri
def test_init_sd_pii(self):
""" Test case: uri is set correctly during initialization with ScienceDirect PII"""
myFullDoc = FullDoc(sd_pii = self.sd_pii)
assert myFullDoc.uri == self.full_pii_uri
def test_init_doi(self):
""" Test case: uri is set correctly during initialization with DOI"""
myFullDoc = FullDoc(doi = self.doi)
assert myFullDoc.uri == self.full_doi_uri
## Test reading/writing author profile data
bad_client = ElsClient("dummy")
good_client = ElsClient(config['apikey'], inst_token = config['insttoken'])
good_client.local_dir = str(test_path)
myFullDoc = FullDoc(uri = full_pii_uri)
def test_read_good_bad_client(self):
"""Test case: using a well-configured client leads to successful read
and using a badly-configured client does not."""
assert self.myFullDoc.read(self.bad_client) == False
assert self.myFullDoc.read(self.good_client) == True
def test_json_to_dict(self):
"""Test case: the JSON read by the full article object from the
API is parsed into a Python dictionary"""
assert type(self.myFullDoc.data) == dict
def test_title_getter(self):
"""Test case: the title attribute is returned as a non-empty string"""
assert (type(self.myFullDoc.title) == str and self.myFullDoc.title != '')
def test_write(self):
"""Test case: the full article object's data is written to a file with the ID in the filename"""
self.myFullDoc.write()
## TODO: replace following (strung-together replace) with regex
assert util.file_exist_with_id(
self.myFullDoc.data['coredata']['pii'].replace('-','').replace('(','').replace(')',''))
class TestSearch:
"""Test search functionality"""
## Test data
base_url = u'https://api.elsevier.com/content/search/'
search_types = [
{"query" : "authlast(keuskamp)", "index" : "author"},
{"query" : "affil(amsterdam)", "index" : "affiliation"},
{"query" : "AFFIL(dartmouth) AND AUTHOR-NAME(lewis) AND PUBYEAR > 2011",
"index" : "scopus"},
{"query" : "star trek vs star wars", "index" : "sciencedirect"}
]
searches = [ ElsSearch(search_type["query"], search_type["index"])
for search_type in search_types]
good_client = ElsClient(config['apikey'], inst_token = config['insttoken'])
## Test initialization
def test_init_uri(self):
"""Test case: query, index and uri are set correctly during
initialization"""
match_all = True
for i in range(len(self.search_types)):
if (self.searches[i].query != self.search_types[i]['query'] or
self.searches[i].index != self.search_types[i]['index'] or
self.searches[i].uri != (self.base_url +
self.search_types[i]['index'] +
'?query=' +
url_encode(self.search_types[i]['query']))):
match_all = False
assert match_all == True
def test_execution(self):
'''Test case: all searches are executed without raising an exception.'''
for search in self.searches:
search.execute(self.good_client)
assert True