Completed
Pull Request — devel (#6)
by Paolo
01:33
created

tests.test_submissions   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 357
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 236
dl 0
loc 357
rs 8.8798
c 0
b 0
f 0
wmc 44

21 Methods

Rating   Name   Duplication   Size   Complexity  
A SampleTest.setup_class() 0 10 1
A SampleTest.test_delete() 0 6 1
A SubmissionTest.test_get_empty_samples() 0 5 1
A SubmissionTest.test_create_sample() 0 6 1
A SubmissionTest.test_delete() 0 6 1
A SubmissionTest.setup_class() 0 16 1
A SampleTest.teardown_class() 0 5 1
A SampleTest.test_patch() 0 10 1
A SubmissionTest.teardown_class() 0 7 1
A SubmissionTest.mocked_get_empty_samples() 0 25 3
A SubmissionTest.test_str() 0 10 2
C SubmissionTest.mocked_finalize() 0 52 9
A SubmissionTest.test_get_samples() 0 10 1
A SubmissionTest.test_finalize() 0 8 1
A SubmissionTest.setUp() 0 46 3
A SampleTest.test_str() 0 3 1
B SubmissionTest.mocked_get_samples() 0 40 7
A SubmissionTest.test_check_ready() 0 11 2
A SampleTest.setUp() 0 7 2
A SubmissionTest.create_sample() 0 13 2
A SubmissionTest.test_get_status() 0 10 2

How to fix   Complexity   

Complexity

Complex classes like tests.test_submissions often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Thu Jul 12 14:23:09 2018
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import os
10
import json
11
import types
12
13
from unittest.mock import patch, Mock
14
from unittest import TestCase
15
16
from pyUSIrest.auth import Auth
17
from pyUSIrest.client import Document
18
from pyUSIrest.usi import Submission, Sample
19
20
from .common import DATA_PATH
21
from .test_auth import generate_token
22
23
24
class SubmissionTest(TestCase):
25
    @classmethod
26
    def setup_class(cls):
27
        cls.mock_get_patcher = patch('requests.Session.get')
28
        cls.mock_get = cls.mock_get_patcher.start()
29
30
        cls.mock_post_patcher = patch('requests.Session.post')
31
        cls.mock_post = cls.mock_post_patcher.start()
32
33
        cls.mock_put_patcher = patch('requests.Session.put')
34
        cls.mock_put = cls.mock_put_patcher.start()
35
36
        cls.mock_patch_patcher = patch('requests.Session.patch')
37
        cls.mock_patch = cls.mock_patch_patcher.start()
38
39
        cls.mock_delete_patcher = patch('requests.Session.delete')
40
        cls.mock_delete = cls.mock_delete_patcher.start()
41
42
    @classmethod
43
    def teardown_class(cls):
44
        cls.mock_get_patcher.stop()
45
        cls.mock_post_patcher.stop()
46
        cls.mock_put_patcher.stop()
47
        cls.mock_patch_patcher.stop()
48
        cls.mock_delete_patcher.stop()
49
50
    def setUp(self):
51
        self.auth = Auth(token=generate_token())
52
53
        with open(os.path.join(DATA_PATH, "newSubmission.json")) as handle:
54
            data = json.load(handle)
55
56
        self.submission = Submission(self.auth, data=data)
57
58
        with open(os.path.join(DATA_PATH, "contents.json")) as handle:
59
            self.content = json.load(handle)
60
61
        # defining samples
62
        self.sample1 = {
63
            'alias': 'animal_1',
64
            'title': 'animal_title',
65
            'releaseDate': '2018-07-13',
66
            'taxonId': 9940,
67
            'attributes': {
68
                'material': [
69
                    {'value': 'organism',
70
                     'terms': [
71
                        {'url': 'http://purl.obolibrary.org/obo/OBI_0100026'}
72
                     ]}
73
                ],
74
                'project': [{'value': 'test'}]
75
            },
76
            'sampleRelationships': []}
77
78
        self.sample2 = {
79
            'alias': 'sample_1',
80
            'title': 'sample_title',
81
            'releaseDate': '2018-07-13',
82
            'taxonId': 9940,
83
            'description': 'a description',
84
            'attributes': {
85
                'material': [
86
                    {'value': 'specimen from organism',
87
                     'terms': [
88
                        {'url': 'http://purl.obolibrary.org/obo/OBI_0001479'}
89
                     ]}
90
                ],
91
                'project': [{'value': 'test'}]
92
            },
93
            'sampleRelationships': [{
94
                'alias': 'animal_1',
95
                'relationshipNature': 'derived from'}]
96
            }
97
98
    def test_str(self):
99
        with open(os.path.join(DATA_PATH, "submissionStatus1.json")) as handle:
100
            data = json.load(handle)
101
102
        self.mock_get.return_value = Mock()
103
        self.mock_get.return_value.json.return_value = data
104
        self.mock_get.return_value.status_code = 200
105
106
        test = self.submission.__str__()
107
        self.assertIsInstance(test, str)
108
109
    def create_sample(self, sample):
110
        self.mock_get.return_value = Mock()
111
        self.mock_get.return_value.json.return_value = self.content
112
        self.mock_get.return_value.status_code = 200
113
114
        with open(os.path.join(DATA_PATH, "%s.json" % (sample))) as handle:
115
            data = json.load(handle)
116
117
        self.mock_post.return_value = Mock()
118
        self.mock_post.return_value.json.return_value = data
119
        self.mock_post.return_value.status_code = 201
120
121
        return self.submission.create_sample(getattr(self, sample))
122
123
    def test_create_sample(self):
124
        sample1 = self.create_sample("sample1")
125
        self.assertIsInstance(sample1, Sample)
126
127
        sample2 = self.create_sample("sample2")
128
        self.assertIsInstance(sample2, Sample)
129
130
    def mocked_get_samples(*args, **kwargs):
131
        class MockResponse:
132
            def __init__(self, json_data, status_code):
133
                self.json_data = json_data
134
                self.status_code = status_code
135
                self.text = "MockResponse not implemented: %s" % (args[0])
136
137
            def json(self):
138
                return self.json_data
139
140
        get_samples_link = (
141
            "https://submission-test.ebi.ac.uk/api/submissions/"
142
            "c8c86558-8d3a-4ac5-8638-7aa354291d61/contents/samples")
143
144
        with open(os.path.join(DATA_PATH, "samples.json")) as handle:
145
            samples = json.load(handle)
146
147
        with open(os.path.join(DATA_PATH, "validation1.json")) as handle:
148
            validation1 = json.load(handle)
149
150
        with open(os.path.join(DATA_PATH, "validation2.json")) as handle:
151
            validation2 = json.load(handle)
152
153
        # followin content -> samples
154
        if args[0] == get_samples_link:
155
            return MockResponse(samples, 200)
156
157
        # sample1 validation result
158
        elif args[0] == (
159
                'https://submission-test.ebi.ac.uk/api/samples/90c8f449-'
160
                'b3c2-4238-a22b-fd03bc02a5d2/validationResult'):
161
            return MockResponse(validation1, 200)
162
163
        # sample1 validtation result
164
        elif args[0] == (
165
                'https://submission-test.ebi.ac.uk/api/samples/58cb010a-'
166
                '3a89-42b7-8ccd-67b6f8b6dd4c/validationResult'):
167
            return MockResponse(validation2, 200)
168
169
        return MockResponse(None, 404)
170
171
    # We patch 'requests.Session.get' with our own method. The mock object is
172
    # passed in to our test case method.
173
    @patch('requests.Session.get', side_effect=mocked_get_samples)
174
    def test_get_samples(self, mock_get):
175
        samples = self.submission.get_samples(validationResult='Complete')
176
177
        # samples is now a generator
178
        self.assertIsInstance(samples, types.GeneratorType)
179
180
        # convert it into a list
181
        samples = list(samples)
182
        self.assertEqual(len(samples), 2)
183
184
    def mocked_get_empty_samples(*args, **kwargs):
185
        """Simulate a submission with no samples at all"""
186
187
        class MockResponse:
188
            def __init__(self, json_data, status_code):
189
                self.json_data = json_data
190
                self.status_code = status_code
191
                self.text = "MockResponse not implemented: %s" % (args[0])
192
193
            def json(self):
194
                return self.json_data
195
196
        get_samples_link = (
197
            "https://submission-test.ebi.ac.uk/api/submissions/"
198
            "c8c86558-8d3a-4ac5-8638-7aa354291d61/contents/samples")
199
200
        with open(os.path.join(DATA_PATH, "empty_samples.json")) as handle:
201
            samples = json.load(handle)
202
203
        # followin content -> samples
204
        if args[0] == get_samples_link:
205
            return MockResponse(samples, 200)
206
207
        # default response
208
        return MockResponse(None, 404)
209
210
    # patch a request.get to return 0 samples for a submission
211
    @patch('requests.Session.get', side_effect=mocked_get_empty_samples)
212
    def test_get_empty_samples(self, mock_get):
213
        samples = self.submission.get_samples(validationResult='Complete')
214
215
        self.assertRaises(StopIteration, next, samples)
216
217
    def test_get_status(self):
218
        with open(os.path.join(DATA_PATH, "validationResults.json")) as handle:
219
            data = json.load(handle)
220
221
        self.mock_get.return_value = Mock()
222
        self.mock_get.return_value.json.return_value = data
223
        self.mock_get.return_value.status_code = 200
224
225
        statuses = self.submission.get_status()
226
        self.assertEqual(statuses['Complete'], 2)
227
228
    def test_check_ready(self):
229
        with open(os.path.join(
230
                DATA_PATH, "availableSubmissionStatuses.json")) as handle:
231
            data = json.load(handle)
232
233
        self.mock_get.return_value = Mock()
234
        self.mock_get.return_value.json.return_value = data
235
        self.mock_get.return_value.status_code = 200
236
237
        check = self.submission.check_ready()
238
        self.assertTrue(check)
239
240
    def mocked_finalize(*args, **kwargs):
241
        class MockResponse:
242
            def __init__(self, json_data, status_code):
243
                self.json_data = json_data
244
                self.status_code = status_code
245
                self.text = "MockResponse not implemented: %s" % (args[0])
246
247
            def json(self):
248
                return self.json_data
249
250
        check_ready_link = (
251
            "https://submission-test.ebi.ac.uk/api/submissions/c8c86558-"
252
            "8d3a-4ac5-8638-7aa354291d61/availableSubmissionStatuses")
253
254
        with open(os.path.join(
255
                DATA_PATH, "availableSubmissionStatuses.json")) as handle:
256
            check_ready_data = json.load(handle)
257
258
        validation_link = (
259
            "https://submission-test.ebi.ac.uk/api/validationResults/search/"
260
            "by-submission?submissionId=c8c86558-8d3a-4ac5-8638-7aa354291d61")
261
262
        with open(os.path.join(DATA_PATH, "validationResults.json")) as handle:
263
            validation_data = json.load(handle)
264
265
        self_link = (
266
            "https://submission-test.ebi.ac.uk/api/submissions/"
267
            "c8c86558-8d3a-4ac5-8638-7aa354291d61")
268
269
        with open(os.path.join(DATA_PATH, "newSubmission.json")) as handle:
270
            self_data = json.load(handle)
271
272
        status_link = (
273
            "https://submission-test.ebi.ac.uk/api/submissions/c8c86558-"
274
            "8d3a-4ac5-8638-7aa354291d61/submissionStatus")
275
276
        with open(os.path.join(DATA_PATH, "submissionStatus2.json")) as handle:
277
            status_data = json.load(handle)
278
279
        if args[0] == check_ready_link:
280
            return MockResponse(check_ready_data, 200)
281
282
        elif args[0] == validation_link:
283
            return MockResponse(validation_data, 200)
284
285
        elif args[0] == self_link:
286
            return MockResponse(self_data, 200)
287
288
        elif args[0] == status_link:
289
            return MockResponse(status_data, 200)
290
291
        return MockResponse(None, 404)
292
293
    @patch('requests.Session.get', side_effect=mocked_finalize)
294
    def test_finalize(self, mock_get):
295
        self.mock_put.return_value = Mock()
296
        self.mock_put.return_value.json.return_value = {}
297
        self.mock_put.return_value.status_code = 200
298
299
        document = self.submission.finalize()
300
        self.assertIsInstance(document, Document)
301
302
    def test_delete(self):
303
        self.mock_delete.return_value = Mock()
304
        self.mock_delete.return_value.last_response = ''
305
        self.mock_delete.return_value.status_code = 204
306
307
        self.submission.delete()
308
309
310
class SampleTest(TestCase):
311
    @classmethod
312
    def setup_class(cls):
313
        cls.mock_get_patcher = patch('requests.Session.get')
314
        cls.mock_get = cls.mock_get_patcher.start()
315
316
        cls.mock_patch_patcher = patch('requests.Session.patch')
317
        cls.mock_patch = cls.mock_patch_patcher.start()
318
319
        cls.mock_delete_patcher = patch('requests.Session.delete')
320
        cls.mock_delete = cls.mock_delete_patcher.start()
321
322
    @classmethod
323
    def teardown_class(cls):
324
        cls.mock_get_patcher.stop()
325
        cls.mock_patch_patcher.stop()
326
        cls.mock_delete_patcher.stop()
327
328
    def setUp(self):
329
        self.auth = Auth(token=generate_token())
330
331
        with open(os.path.join(DATA_PATH, "sample2.json")) as handle:
332
            self.data = json.load(handle)
333
334
        self.sample = Sample(self.auth, data=self.data)
335
336
    def test_str(self):
337
        test = self.sample.__str__()
338
        self.assertIsInstance(test, str)
339
340
    def test_patch(self):
341
        self.mock_patch.return_value = Mock()
342
        self.mock_patch.return_value.json.return_value = self.data
343
        self.mock_patch.return_value.status_code = 200
344
345
        self.mock_get.return_value = Mock()
346
        self.mock_get.return_value.json.return_value = self.data
347
        self.mock_get.return_value.status_code = 200
348
349
        self.sample.patch(sample_data={'title': 'new title'})
350
351
    def test_delete(self):
352
        self.mock_delete.return_value = Mock()
353
        self.mock_delete.return_value.last_response = ''
354
        self.mock_delete.return_value.status_code = 204
355
356
        self.sample.delete()
357