Completed
Push — master ( 55dedd...16663f )
by Paolo
30s queued 14s
created

FetchRemovalTestCase.test_fetch_orphan_biosamples_pending()   A

Complexity

Conditions 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Mon Jan 21 14:30:04 2019
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import io
10
import json
11
from collections import Counter
12
13
from pyUSIrest.auth import Auth
14
from pyUSIrest.usi import Sample
15
from pyUSIrest.exceptions import USIDataError
16
17
from unittest.mock import patch, PropertyMock, Mock
18
19
from django.core.management import call_command
20
from django.test import TestCase
21
22
from common.constants import SUBMITTED, NEED_REVISION, ERROR, COMPLETED, READY
23
24
from ..models import ManagedTeam, OrphanSubmission, OrphanSample
25
26
from .common import BaseMixin, generate_token, BioSamplesMixin
27
28
29
class CommandsMixin():
30
    @classmethod
31
    def setUpClass(cls):
32
        # calling my base class setup
33
        super().setUpClass()
34
35
        # starting mocked objects
36
        cls.mock_auth_patcher = patch('biosample.helpers.get_manager_auth')
37
        cls.mock_auth = cls.mock_auth_patcher.start()
38
39
    @classmethod
40
    def tearDownClass(cls):
41
        cls.mock_auth_patcher.stop()
42
43
        # calling base method
44
        super().tearDownClass()
45
46
47
class CommandsTestCase(CommandsMixin, BaseMixin, TestCase):
48
    @patch('biosample.helpers.get_manager_auth')
49
    def test_fill_managed(self, my_auth):
50
        """test fill_managed command"""
51
52
        # remove a managed team
53
        managed = ManagedTeam.objects.get(pk=2)
54
        managed.delete()
55
56
        # patch get_manager_auth value
57
        my_auth.return_value = Auth(
58
            token=generate_token(
59
                domains=[
60
                    'subs.test-team-1',
61
                    'subs.test-team-2',
62
                    'subs.test-team-3']
63
            )
64
        )
65
66
        # calling commands
67
        call_command('fill_managed')
68
69
        # get all managedteams object
70
        self.assertEqual(ManagedTeam.objects.count(), 3)
71
        self.assertTrue(my_auth.called)
72
73
    def test_get_json_for_biosample(self):
74
75
        args = ["--submission", 1]
76
77
        # https://stackoverflow.com/questions/4219717/how-to-assert-output-with-nosetest-unittest-in-python
78
        with patch('sys.stdout', new_callable=io.StringIO) as handle:
79
            call_command('get_json_for_biosample', *args)
80
            handle.seek(0)
81
82
            data = json.load(handle)
83
            self.assertIsInstance(data, dict)
84
85
86
class SubmitRemovalTestCase(CommandsMixin, BioSamplesMixin, TestCase):
87
    fixtures = [
88
        'biosample/managedteam',
89
        'biosample/orphansample',
90
        'uid/dictspecie',
91
    ]
92
93
    def setUp(self):
94
        # calling my base class setup
95
        super().setUp()
96
97
        # starting mocked objects
98
        self.mock_root_patcher = patch('pyUSIrest.usi.Root')
99
        self.mock_root = self.mock_root_patcher.start()
100
101
        # start root object
102
        self.my_root = self.mock_root.return_value
103
104
        # mocking chain
105
        self.my_team = self.my_root.get_team_by_name.return_value
106
        self.my_team.name = "subs.test-team-1"
107
108
        # mocking a new submission
109
        self.new_submission = self.my_team.create_submission.return_value
110
        self.new_submission.name = "new-submission"
111
112
        # mocking sample creation: two objects: one submittable, one not
113
        my_samples = [
114
            Sample(auth=generate_token()),
115
            USIDataError("test"),
116
        ]
117
118
        self.new_submission.create_sample.side_effect = my_samples
119
120
        # set status. Because of the way mock attributes are stored you can’t
121
        # directly attach a PropertyMock to a mock object. Instead you can
122
        # attach it to the mock type object:
123
        self.new_submission.propertymock = PropertyMock(return_value='Draft')
124
        type(self.new_submission).status = self.new_submission.propertymock
125
126
    def tearDown(self):
127
        self.mock_root_patcher.stop()
128
129
        super().tearDown()
130
131 View Code Duplication
    def test_patch_orphan_biosamples(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
132
        """test patch_orphan_biosamples command"""
133
134
        # calling commands
135
        call_command('patch_orphan_biosamples')
136
137
        # assert a submission created
138
        self.assertTrue(self.my_root.get_team_by_name.called)
139
        self.assertTrue(self.my_team.create_submission.called)
140
        self.assertTrue(self.new_submission.create_sample.called)
141
        self.assertEqual(self.new_submission.create_sample.call_count, 2)
142
143
        # check for an object into database
144
        submissions = OrphanSubmission.objects.all()
145
        self.assertEqual(len(submissions), 1)
146
147
        # test submission attributes
148
        submission = submissions[0]
149
        self.assertEqual(submission.usi_submission_name, "new-submission")
150
        self.assertEqual(submission.samples_count, 1)
151
        self.assertEqual(submission.status, SUBMITTED)
152
153
        # assert sample status
154
        sample = OrphanSample.objects.get(pk=1)
155
        self.assertEqual(sample.status, SUBMITTED)
156
157
        # assert exactly one sample associated with this submission
158
        self.assertEqual(submission.submission_data.count(), 1)
159
        self.assertEqual(sample, submission.submission_data.get())
160
161
        # This was supposed to have a problem in this tests
162
        sample = OrphanSample.objects.get(pk=2)
163
        self.assertEqual(sample.status, ERROR)
164
165 View Code Duplication
    def test_patch_orphan_biosamples_with_limit(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
166
        """test patch_orphan_biosamples command"""
167
168
        # calling commands
169
        args = ["--limit", 1]
170
        call_command('patch_orphan_biosamples', *args)
171
172
        # assert a submission created
173
        self.assertTrue(self.my_root.get_team_by_name.called)
174
        self.assertTrue(self.my_team.create_submission.called)
175
        self.assertTrue(self.new_submission.create_sample.called)
176
        self.assertEqual(self.new_submission.create_sample.call_count, 1)
177
178
        # check for an object into database
179
        submissions = OrphanSubmission.objects.all()
180
        self.assertEqual(len(submissions), 1)
181
182
        # test submission attributes
183
        submission = submissions[0]
184
        self.assertEqual(submission.usi_submission_name, "new-submission")
185
        self.assertEqual(submission.samples_count, 1)
186
        self.assertEqual(submission.status, SUBMITTED)
187
188
        # assert sample status
189
        sample = OrphanSample.objects.get(pk=1)
190
        self.assertEqual(sample.status, SUBMITTED)
191
192
        # assert exactly one sample associated with this submission
193
        self.assertEqual(submission.submission_data.count(), 1)
194
        self.assertEqual(sample, submission.submission_data.get())
195
196
        # This was supposed to have a problem in this tests, However this
197
        # was not called by our limits
198
        sample = OrphanSample.objects.get(pk=2)
199
        self.assertEqual(sample.status, READY)
200
201
202
class FetchRemovalTestCase(CommandsMixin, BioSamplesMixin, TestCase):
203
    fixtures = [
204
        'biosample/managedteam',
205
        'biosample/orphansample',
206
        'biosample/orphansubmission',
207
        'uid/dictspecie',
208
    ]
209
210
    def setUp(self):
211
        # calling my base class setup
212
        super().setUp()
213
214
        # starting mocked objects
215
        self.mock_root_patcher = patch('pyUSIrest.usi.Root')
216
        self.mock_root = self.mock_root_patcher.start()
217
218
        # start root object
219
        self.my_root = self.mock_root.return_value
220
221
        # mocking a new submission
222
        self.submission = self.my_root.get_submission_by_name.return_value
223
        self.submission.name = "7dbb563e-c162-4df2-a48f-bbf5de8d1e35"
224
        self.submission.status = "Draft"
225
226
        # track a orphan submission
227
        self.orphan_submission_obj = OrphanSubmission.objects.get(pk=1)
228
        self.orphan_submission_obj.status = SUBMITTED
229
        self.orphan_submission_obj.save()
230
231
        # track submission in samples
232
        OrphanSample.objects.update(
233
            submission=self.orphan_submission_obj, status=SUBMITTED)
234
235
    def tearDown(self):
236
        self.mock_root_patcher.stop()
237
238
        super().tearDown()
239
240
    def common_tests(self, status=SUBMITTED, args=[]):
241
        """Assert stuff for each test"""
242
243
        # calling commands
244
        call_command('fetch_orphan_biosamples', *args)
245
246
        # UID submission status remain the same
247
        self.orphan_submission_obj.refresh_from_db()
248
        self.assertEqual(self.orphan_submission_obj.status, status)
249
250
        self.assertTrue(self.mock_auth.called)
251
        self.assertTrue(self.mock_root.called)
252
        self.assertTrue(self.my_root.get_submission_by_name.called)
253
254
    def test_fetch_orphan_biosamples_pending(self):
255
        """test fetch_orphan_biosamples command"""
256
257
        # update submission status
258
        self.submission.status = 'Draft'
259
        self.submission.has_errors.return_value = Counter({False: 2})
260
        self.submission.get_status.return_value = Counter({'Pending': 2})
261
262
        # asserting things
263
        self.common_tests()
264
265
        # testing a not finalized biosample condition
266
        self.assertFalse(self.submission.finalize.called)
267
268
    def test_fetch_orphan_biosamples_complete(self):
269
        """test fetch_orphan_biosamples command"""
270
271
        # update submission status
272
        self.submission.status = 'Draft'
273
        self.submission.has_errors.return_value = Counter({False: 2})
274
        self.submission.get_status.return_value = Counter({'Complete': 2})
275
276
        # asserting things
277
        self.common_tests(args=['--finalize'])
278
279
        # testing a not finalized biosample condition
280
        self.assertTrue(self.submission.finalize.called)
281
282
    def test_fetch_orphan_biosamples_complete_ignore(self):
283
        """test fetch_orphan_biosamples command"""
284
285
        # update submission status
286
        self.submission.status = 'Draft'
287
        self.submission.has_errors.return_value = Counter({False: 2})
288
        self.submission.get_status.return_value = Counter({'Complete': 2})
289
290
        # asserting things
291
        self.common_tests()
292
293
        # testing a not finalized biosample condition
294
        self.assertFalse(self.submission.finalize.called)
295
296
    def test_fetch_orphan_biosamples_errors(self):
297
        """test fetch_orphan_biosamples command with issues in USI"""
298
299
        # a draft submission with errors
300
        self.submission.status = 'Draft'
301
        self.submission.has_errors.return_value = Counter(
302
            {True: 1, False: 1})
303
        self.submission.get_status.return_value = Counter({'Complete': 2})
304
305
        # Add samples. Suppose that first failed, second is ok
306
        my_validation_result1 = Mock()
307
        my_validation_result1.errorMessages = {
308
            'Ena': [
309
                'a sample message',
310
            ]
311
        }
312
313
        my_sample1 = Mock()
314
        my_sample1.accession = "SAMEA6376980"
315
        my_sample1.alias = "IMAGEA000005611"
316
        my_sample1.name = "test-animal"
317
        my_sample1.has_errors.return_value = True
318
        my_sample1.get_validation_result.return_value = my_validation_result1
319
320
        # sample2 is ok
321
        my_validation_result2 = Mock()
322
        my_validation_result2.errorMessages = None
323
324
        my_sample2 = Mock()
325
        my_sample2.accession = "SAMEA6376982"
326
        my_sample2.alias = "IMAGES000006757"
327
        my_sample2.name = "test-sample"
328
        my_sample2.has_errors.return_value = False
329
        my_sample2.get_validation_result.return_value = my_validation_result2
330
331
        # simulate that IMAGEA000000001 has errors
332
        self.submission.get_samples.return_value = [my_sample1, my_sample2]
333
334
        # track other objects
335
        self.my_sample1 = my_sample1
336
        self.my_sample2 = my_sample2
337
338
        # asserting things
339
        self.common_tests(args=['--finalize'], status=NEED_REVISION)
340
341
        # testing a not finalized biosample condition
342
        self.assertFalse(self.submission.finalize.called)
343
344
        # assert custom mock attributes called
345
        self.assertTrue(self.my_sample1.has_errors.called)
346
        self.assertTrue(self.my_sample1.get_validation_result.called)
347
348
        # if sample has no errors, no all methods will be called
349
        self.assertTrue(self.my_sample2.has_errors.called)
350
        self.assertFalse(self.my_sample2.get_validation_result.called)
351
352
        # assert sample status in db.
353
        sample = OrphanSample.objects.get(pk=1)
354
        self.assertEqual(sample.status, SUBMITTED)
355
356
        # Same logic of FetchStatusHelper
357
        sample = OrphanSample.objects.get(pk=2)
358
        self.assertEqual(sample.status, NEED_REVISION)
359
360
    def test_fetch_orphan_complete(self):
361
        """Test fetch status for a complete submission"""
362
363
        # a completed submission with two samples
364
        self.submission.status = 'Completed'
365
366
        # Add samples
367
        my_sample1 = Mock()
368
        my_sample1.accession = "SAMEA6376980"
369
        my_sample1.alias = "IMAGEA000005611"
370
        my_sample1.name = "test-animal"
371
        my_sample2 = Mock()
372
        my_sample2.accession = "SAMEA6376982"
373
        my_sample2.alias = "IMAGES000006757"
374
        my_sample2.name = "test-sample"
375
        self.submission.get_samples.return_value = [my_sample1, my_sample2]
376
377
        # assert auth, root and get_submission by name called
378
        self.common_tests(status=COMPLETED)
379
380
        # assert sample status in db.
381
        count = OrphanSample.objects.filter(status=COMPLETED).count()
382
        self.assertEqual(count, 2)
383
384
        # assert that flag are changed
385
        count = OrphanSample.objects.filter(removed=True).count()
386
        self.assertEqual(count, 2)
387
388
    def test_fetch_status_no_accession(self):
389
        """Test fetch status for a submission which doens't send accession
390
        no updates in such case"""
391
392
        # a completed submission with two samples
393
        self.submission.status = 'Completed'
394
395
        # Add samples
396
        my_sample1 = Mock()
397
        my_sample1.name = "test-animal"
398
        my_sample1.alias = "IMAGEA000005611"
399
        my_sample1.accession = None
400
        my_sample2 = Mock()
401
        my_sample2.name = "test-sample"
402
        my_sample2.alias = "IMAGES000006757"
403
        my_sample2.accession = None
404
        self.submission.get_samples.return_value = [my_sample1, my_sample2]
405
406
        # assert auth, root and get_submission by name called
407
        self.common_tests()
408
409
        # assert sample status in db. Same logich of FetchStatusHelper
410
        count = OrphanSample.objects.filter(status=SUBMITTED).count()
411
        self.assertEqual(count, 2)
412
413
        # assert that flag are changed
414
        count = OrphanSample.objects.filter(removed=False).count()
415
        self.assertEqual(count, 2)
416