Passed
Pull Request — master (#26)
by Paolo
01:48
created

ValidateSubmissionTest.test_validate_submission()   A

Complexity

Conditions 2

Size

Total Lines 54
Code Lines 35

Duplication

Lines 54
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 35
dl 54
loc 54
rs 9.0399
c 0
b 0
f 0
cc 2
nop 6

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Fri Oct  5 11:39:21 2018
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import json
10
11
from collections import Counter
12
from unittest.mock import patch, Mock
13
from billiard.einfo import ExceptionInfo
14
from celery.exceptions import Retry
15
from pytest import raises
16
from image_validation.ValidationResult import (
17
    ValidationResultColumn, ValidationResultRecord)
18
19
from django.core import mail
20
from django.test import TestCase
21
22
from common.constants import LOADED, ERROR, READY, NEED_REVISION, COMPLETED
23
from common.tests import PersonMixinTestCase
24
from image_app.models import Submission, Person, Name, Animal, Sample
25
26
from ..tasks import ValidateTask, ValidationError
27
from ..helpers import OntologyCacheError
28
29
30
# https://github.com/testing-cabal/mock/issues/139#issuecomment-122128815
31
class PickableMock(Mock):
32
    """Provide a __reduce__ method to allow pickling mock objects"""
33
34
    def __reduce__(self):
35
        return (Mock, ())
36
37
38
class ValidateSubmissionMixin(PersonMixinTestCase):
39
    """A mixin to define common stuff for testing data validation"""
40
41
    # an attribute for PersonMixinTestCase
42
    person = Person
43
44
    fixtures = [
45
        'image_app/animal',
46
        'image_app/dictbreed',
47
        'image_app/dictcountry',
48
        'image_app/dictrole',
49
        'image_app/dictsex',
50
        'image_app/dictspecie',
51
        'image_app/dictstage',
52
        'image_app/dictuberon',
53
        'image_app/name',
54
        'image_app/ontology',
55
        'image_app/organization',
56
        'image_app/publication',
57
        'image_app/sample',
58
        'image_app/submission',
59
        'image_app/user',
60
        "validation/validationresult"
61
    ]
62
63
    def setUp(self):
64
        # get a submission object
65
        self.submission = Submission.objects.get(pk=1)
66
67
        # set a status which I can validate
68
        self.submission.status = LOADED
69
        self.submission.save()
70
71
        # track submission ID
72
        self.submission_id = self.submission.id
73
74
        # track names
75
        self.name_qs = Name.objects.exclude(name__contains="unknown")
76
77
        # setting tasks
78
        self.my_task = ValidateTask()
79
80
81
class ValidateSubmissionTest(ValidateSubmissionMixin, TestCase):
82
83 View Code Duplication
    @patch('validation.tasks.send_message_to_websocket')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
84
    @patch('asyncio.get_event_loop')
85
    def test_on_failure(self, asyncio_mock, send_message_to_websocket_mock):
86
        """Testing on failure methods"""
87
88
        tmp = asyncio_mock.return_value
89
        tmp.run_until_complete = Mock()
90
91
        exc = Exception("Test")
92
        task_id = "test_task_id"
93
        args = [self.submission_id]
94
        kwargs = {}
95
        einfo = ExceptionInfo
96
97
        # call on_failure method
98
        self.my_task.on_failure(exc, task_id, args, kwargs, einfo)
99
100
        # check submission status and message
101
        submission = Submission.objects.get(pk=self.submission_id)
102
103
        # check submission.state changed
104
        self.assertEqual(submission.status, ERROR)
105
        self.assertEqual(
106
            submission.message,
107
            "Error in IMAGE Validation: Test")
108
109
        # test email sent
110
        self.assertEqual(len(mail.outbox), 1)
111
112
        # read email
113
        email = mail.outbox[0]
114
115
        self.assertEqual(
116
            "Error in IMAGE Validation: %s" % self.submission_id,
117
            email.subject)
118
119
        self.assertEqual(asyncio_mock.call_count, 1)
120
        self.assertEqual(tmp.run_until_complete.call_count, 1)
121
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
122
        send_message_to_websocket_mock.assert_called_with(
123
            {'message': 'Error',
124
             'notification_message': 'Error in IMAGE Validation: Test'}, 1)
125
126
    @patch('crbanim.helpers.send_message_to_websocket')
127
    @patch('asyncio.get_event_loop')
128
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
129
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
130
    @patch("validation.tasks.MetaDataValidation.validate")
131
    @patch("validation.tasks.ValidateTask.retry")
132
    def test_validate_retry(self, my_retry, my_validate, my_check, my_read,
133
                            asyncio_mock, send_message_to_websocket_mock):
134
        """Test validation with retry"""
135
        tmp = asyncio_mock.return_value
136
        tmp.run_until_complete = Mock()
137
138
        # setting check_usi_structure result
139
        my_check.return_value = []
140
141
        # Set a side effect on the patched methods
142
        # so that they raise the errors we want.
143
        my_retry.side_effect = Retry()
144
        my_validate.side_effect = Exception()
145
146
        with raises(Retry):
147
            self.my_task.run(submission_id=self.submission_id)
148
149
        self.assertTrue(my_validate.called)
150
        self.assertTrue(my_retry.called)
151
        self.assertTrue(my_check.called)
152
        self.assertTrue(my_read.called)
153
        self.assertEqual(asyncio_mock.call_count, 0)
154
        self.assertEqual(tmp.run_until_complete.call_count, 0)
155
        self.assertEqual(send_message_to_websocket_mock.call_count, 0)
156
157
    @patch('validation.tasks.send_message_to_websocket')
158
    @patch('asyncio.get_event_loop')
159
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
160
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
161
    @patch("validation.tasks.MetaDataValidation.validate")
162
    @patch("validation.tasks.ValidateTask.retry")
163
    def test_issues_with_api(self, my_retry, my_validate, my_check, my_read,
164
                             asyncio_mock, send_message_to_websocket_mock):
165
        """Test errors with validation API"""
166
167
        tmp = asyncio_mock.return_value
168
        tmp.run_until_complete = Mock()
169
170
        # Set a side effect on the patched methods
171
        # so that they raise the errors we want.
172
        my_retry.side_effect = Retry()
173
        my_check.return_value = []
174
        my_validate.side_effect = json.decoder.JSONDecodeError(
175
            msg="test", doc="test", pos=1)
176
177
        # call task. No retries with issues at EBI
178
        res = self.my_task.run(submission_id=self.submission_id)
179
180
        # assert a success with validation taks
181
        self.assertEqual(res, "success")
182
183
        # check submission status and message
184
        self.submission.refresh_from_db()
185
186
        # this is the message I want
187
        message = "Errors in EBI API endpoints. Please try again later"
188
189
        # check submission.status changed to NEED_REVISION
190
        self.assertEqual(self.submission.status, LOADED)
191
        self.assertIn(
192
            message,
193
            self.submission.message)
194
195
        # test email sent
196
        self.assertEqual(len(mail.outbox), 1)
197
198
        # read email
199
        email = mail.outbox[0]
200
201
        self.assertEqual(
202
            "Error in IMAGE Validation: %s" % message,
203
            email.subject)
204
205
        self.assertTrue(my_validate.called)
206
        self.assertFalse(my_retry.called)
207
        self.assertTrue(my_check.called)
208
        self.assertTrue(my_read.called)
209
210
        self.assertEqual(asyncio_mock.call_count, 1)
211
        self.assertEqual(tmp.run_until_complete.call_count, 1)
212
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
213
        send_message_to_websocket_mock.assert_called_with(
214
            {'message': 'Loaded',
215
             'notification_message': 'Errors in EBI API endpoints. Please try '
216
                                     'again later'}, 1)
217
218 View Code Duplication
    @patch('validation.tasks.send_message_to_websocket')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
219
    @patch('asyncio.get_event_loop')
220
    @patch("validation.helpers.validation.read_in_ruleset",
221
           side_effect=OntologyCacheError("test exception"))
222
    @patch("validation.tasks.ValidateTask.retry")
223
    def test_issues_with_ontologychache(
224
            self, my_retry, my_validate, asyncio_mock,
225
            send_message_to_websocket_mock):
226
        """Test errors with validation API when loading OntologyCache
227
        objects"""
228
229
        # mocking asyncio return value
230
        tmp = asyncio_mock.return_value
231
        tmp.run_until_complete = Mock()
232
233
        # call task. No retries with issues at EBI
234
        res = self.my_task.run(submission_id=self.submission_id)
235
236
        # assert a success with validation taks
237
        self.assertEqual(res, "success")
238
239
        # check submission status and message
240
        self.submission.refresh_from_db()
241
242
        # this is the message I want
243
        message = "Errors in EBI API endpoints. Please try again later"
244
245
        # check submission.status changed to NEED_REVISION
246
        self.assertEqual(self.submission.status, LOADED)
247
        self.assertIn(
248
            message,
249
            self.submission.message)
250
251
        # test email sent
252
        self.assertEqual(len(mail.outbox), 1)
253
254
        # read email
255
        email = mail.outbox[0]
256
257
        self.assertEqual(
258
            "Error in IMAGE Validation: %s" % message,
259
            email.subject)
260
261
        self.assertTrue(my_validate.called)
262
        self.assertFalse(my_retry.called)
263
264
        self.assertEqual(asyncio_mock.call_count, 1)
265
        self.assertEqual(tmp.run_until_complete.call_count, 1)
266
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
267
        send_message_to_websocket_mock.assert_called_with(
268
            {'message': 'Loaded',
269
             'notification_message': ('Errors in EBI API endpoints. Please '
270
                                      'try again later')},
271
            1
272
        )
273
274 View Code Duplication
    @patch('validation.tasks.send_message_to_websocket')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
275
    @patch('asyncio.get_event_loop')
276
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
277
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
278
    @patch("validation.tasks.MetaDataValidation.validate")
279
    def test_validate_submission(self, my_validate, my_check, my_read,
280
                                 asyncio_mock, send_message_to_websocket_mock):
281
        tmp = asyncio_mock.return_value
282
        tmp.run_until_complete = Mock()
283
        # setting check_usi_structure result
284
        my_check.return_value = []
285
286
        # setting a return value for check_with_ruleset
287
        validation_result = Mock()
288
        validation_result.get_overall_status.return_value = "Pass"
289
        validation_result.get_messages.return_value = ["A message"]
290
        my_validate.return_value = validation_result
291
292
        # NOTE that I'm calling the function directly, without delay
293
        # (AsyncResult). I've patched the time consuming task
294
        res = self.my_task.run(submission_id=self.submission_id)
295
296
        # assert a success with validation taks
297
        self.assertEqual(res, "success")
298
299
        # check submission status and message
300
        self.submission.refresh_from_db()
301
302
        # check submission.state changed
303
        self.assertEqual(self.submission.status, READY)
304
        self.assertEqual(
305
            self.submission.message,
306
            "Submission validated with success")
307
308
        self.assertEqual(asyncio_mock.call_count, 1)
309
        self.assertEqual(tmp.run_until_complete.call_count, 1)
310
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
311
        send_message_to_websocket_mock.assert_called_with(
312
            {'message': 'Ready',
313
             'notification_message': 'Submission validated with success'}, 1)
314
315
        # check Names (they are all ok)
316
        for name in self.name_qs:
317
            self.assertEqual(name.status, READY)
318
319
            # test for model message (usi_results)
320
            self.assertEqual(
321
                name.validationresult.messages, ["A message"])
322
            self.assertEqual(name.validationresult.status, "Pass")
323
324
        # assert validation functions called
325
        self.assertTrue(my_check.called)
326
        self.assertTrue(my_validate.called)
327
        self.assertTrue(my_read.called)
328
329 View Code Duplication
    @patch('validation.tasks.send_message_to_websocket')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
330
    @patch('asyncio.get_event_loop')
331
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
332
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
333
    @patch("validation.tasks.MetaDataValidation.validate")
334
    def test_validate_submission_wrong_json(
335
            self, my_validate, my_check, my_read, asyncio_mock,
336
            send_message_to_websocket_mock):
337
        tmp = asyncio_mock.return_value
338
        tmp.run_until_complete = Mock()
339
340
        # assign a fake response for check_usi_structure
341
        usi_result = [
342
            ('Wrong JSON structure: no title field for record with '
343
             'alias as animal_1'),
344
            ('Wrong JSON structure: the values for attribute Person '
345
             'role needs to be in an array for record animal_1')
346
        ]
347
        my_check.return_value = usi_result
348
349
        # setting a return value for check_with_ruleset
350
        rule_result = Mock()
351
        rule_result.get_overall_status.return_value = "Pass"
352
        my_validate.return_value = rule_result
353
354
        # call task
355
        res = self.my_task.run(submission_id=self.submission_id)
356
357
        # assert a success with validation taks
358
        self.assertEqual(res, "success")
359
360
        # check submission status and message
361
        self.submission.refresh_from_db()
362
363
        # check submission.state changed
364
        self.assertEqual(self.submission.status, NEED_REVISION)
365
        self.assertIn(
366
            "Wrong JSON structure",
367
            self.submission.message)
368
369
        self.assertEqual(asyncio_mock.call_count, 1)
370
        self.assertEqual(tmp.run_until_complete.call_count, 1)
371
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
372
        send_message_to_websocket_mock.assert_called_with(
373
            {'message': 'Need Revision',
374
             'notification_message': 'Validation got errors: Wrong JSON '
375
                                     'structure'}, 1)
376
377
        # check Names (they require revisions)
378
        for name in self.name_qs:
379
            self.assertEqual(name.status, NEED_REVISION)
380
381
            # test for model message (usi_results)
382
            self.assertEqual(
383
                name.validationresult.messages, usi_result)
384
            self.assertEqual(
385
                    name.validationresult.status, "Wrong JSON structure")
386
387
        # if JSON is not valid, I don't check for ruleset
388
        self.assertTrue(my_check.called)
389
        self.assertFalse(my_validate.called)
390
        self.assertTrue(my_read.called)
391
392
    @patch('validation.tasks.send_message_to_websocket')
393
    @patch('asyncio.get_event_loop')
394
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
395
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
396
    @patch("validation.tasks.MetaDataValidation.validate")
397
    def test_unsupported_status(self, my_validate, my_check, my_read,
398
                                asyncio_mock, send_message_to_websocket_mock):
399
        tmp = asyncio_mock.return_value
400
        tmp.run_until_complete = Mock()
401
        # setting check_usi_structure result
402
        my_check.return_value = []
403
404
        # setting a return value for check_with_ruleset
405
        rule_result = PickableMock()
406
        rule_result.get_overall_status.return_value = "A fake status"
407
        rule_result.get_messages.return_value = ["A fake message", ]
408
        my_validate.return_value = rule_result
409
410
        # call task
411
        self.assertRaisesRegex(
412
            ValidationError,
413
            "Error in statuses for submission",
414
            self.my_task.run,
415
            submission_id=self.submission_id)
416
417
        # check submission status and message
418
        self.submission.refresh_from_db()
419
420
        # check submission.state changed
421
        self.assertEqual(self.submission.status, ERROR)
422
        self.assertIn(
423
            "Error in statuses for submission",
424
            self.submission.message)
425
426
        # if JSON is not valid, I don't check for ruleset
427
        self.assertTrue(my_check.called)
428
        self.assertTrue(my_validate.called)
429
        self.assertTrue(my_read.called)
430
431
        self.assertEqual(asyncio_mock.call_count, 1)
432
        self.assertEqual(tmp.run_until_complete.call_count, 1)
433
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
434
        send_message_to_websocket_mock.assert_called_with(
435
            {'message': 'Error',
436
             'notification_message': (
437
                     "Validation got errors: Error in statuses "
438
                     "for submission Cryoweb "
439
                     "(United Kingdom, test): ["
440
                     "'A fake status', 'Error', 'JSON', "
441
                     "'Pass', 'Warning']")
442
             }, 1)
443
444
    @patch('validation.tasks.send_message_to_websocket')
445
    @patch('asyncio.get_event_loop')
446
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
447
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
448
    @patch("validation.tasks.MetaDataValidation.validate")
449
    def test_validate_submission_warnings(
450
            self, my_validate, my_check, my_read, asyncio_mock,
451
            send_message_to_websocket_mock):
452
        """A submission with warnings is a READY submission"""
453
        tmp = asyncio_mock.return_value
454
        tmp.run_until_complete = Mock()
455
456
        # setting check_usi_structure result
457
        my_check.return_value = []
458
459
        # setting a return value for check_with_ruleset
460
        result1 = ValidationResultRecord("animal_1")
461
        result1.add_validation_result_column(
462
            ValidationResultColumn(
463
                "warning",
464
                "warn message",
465
                "animal_1",
466
                "warn column")
467
        )
468
469
        result2 = ValidationResultRecord("animal_2")
470
        result2.add_validation_result_column(
471
            ValidationResultColumn(
472
                "pass",
473
                "a message",
474
                "animal_2",
475
                "")
476
        )
477
478
        result3 = ValidationResultRecord("animal_3")
479
        result3.add_validation_result_column(
480
            ValidationResultColumn(
481
                "pass",
482
                "a message",
483
                "animal_3",
484
                "")
485
        )
486
487
        result4 = ValidationResultRecord("sample_1")
488
        result4.add_validation_result_column(
489
            ValidationResultColumn(
490
                "pass",
491
                "a message",
492
                "sample_1",
493
                "")
494
        )
495
496
        # add results to result set
497
        responses = [result1, result2, result3, result4]
498
        my_validate.side_effect = responses
499
500
        # call task
501
        res = self.my_task.run(submission_id=self.submission_id)
502
503
        # assert a success with validation taks
504
        self.assertEqual(res, "success")
505
506
        # check submission status and message
507
        self.submission.refresh_from_db()
508
509
        # check submission.state changed
510
        self.assertEqual(self.submission.status, READY)
511
        self.assertIn(
512
            "Submission validated with some warnings",
513
            self.submission.message)
514
        self.assertEqual(asyncio_mock.call_count, 1)
515
        self.assertEqual(tmp.run_until_complete.call_count, 1)
516
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
517
        send_message_to_websocket_mock.assert_called_with(
518
            {'message': 'Ready',
519
             'notification_message': (
520
                    'Submission validated with some warnings')},
521
            1)
522
523
        # check Names (they are all ok)
524
        for i, name in enumerate(self.name_qs):
525
            # get the appropriate ValidationResultRecord
526
            result = responses[i]
527
528
            # all objects are ready for submissions
529
            self.assertEqual(name.status, READY)
530
531
            self.assertEqual(
532
                name.validationresult.messages,
533
                result.get_messages())
534
535
            self.assertEqual(
536
                name.validationresult.status,
537
                result.get_overall_status())
538
539
        # test for my methods called
540
        self.assertTrue(my_check.called)
541
        self.assertTrue(my_validate.called)
542
        self.assertTrue(my_read.called)
543
544
    @patch('validation.tasks.send_message_to_websocket')
545
    @patch('asyncio.get_event_loop')
546
    @patch("validation.tasks.MetaDataValidation.read_in_ruleset")
547
    @patch("validation.tasks.MetaDataValidation.check_usi_structure")
548
    @patch("validation.tasks.MetaDataValidation.validate")
549
    def test_validate_submission_errors(
550
            self, my_validate, my_check, my_read, asyncio_mock,
551
            send_message_to_websocket_mock):
552
        """A submission with errors is a NEED_REVISION submission"""
553
        tmp = asyncio_mock.return_value
554
        tmp.run_until_complete = Mock()
555
556
        # setting check_usi_structure result
557
        my_check.return_value = []
558
559
        # setting a return value for check_with_ruleset
560
        result1 = ValidationResultRecord("animal_1")
561
        result1.add_validation_result_column(
562
            ValidationResultColumn(
563
                "warning",
564
                "warn message",
565
                "animal_1",
566
                "warn column")
567
        )
568
569
        result2 = ValidationResultRecord("animal_2")
570
        result2.add_validation_result_column(
571
            ValidationResultColumn(
572
                "pass",
573
                "a message",
574
                "animal_2",
575
                "")
576
        )
577
578
        result3 = ValidationResultRecord("animal_3")
579
        result3.add_validation_result_column(
580
            ValidationResultColumn(
581
                "pass",
582
                "a message",
583
                "animal_3",
584
                "")
585
        )
586
587
        result4 = ValidationResultRecord("sample_1")
588
        result4.add_validation_result_column(
589
            ValidationResultColumn(
590
                "error",
591
                "error message",
592
                "sample_1",
593
                "error column")
594
        )
595
596
        # add results to result set
597
        responses = [result1, result2, result3, result4]
598
        my_validate.side_effect = responses
599
600
        # call task
601
        res = self.my_task.run(submission_id=self.submission_id)
602
603
        # assert a success with validation taks
604
        self.assertEqual(res, "success")
605
606
        # check submission status and message
607
        self.submission.refresh_from_db()
608
609
        # check submission.state changed
610
        self.assertEqual(self.submission.status, NEED_REVISION)
611
        self.assertIn(
612
            "Error in metadata",
613
            self.submission.message)
614
615
        self.assertEqual(asyncio_mock.call_count, 1)
616
        self.assertEqual(tmp.run_until_complete.call_count, 1)
617
        self.assertEqual(send_message_to_websocket_mock.call_count, 1)
618
        send_message_to_websocket_mock.assert_called_with(
619
            {'message': 'Need Revision',
620
             'notification_message': (
621
                     'Validation got errors: Error in metadata. '
622
                     'Need revisions before submit')
623
             }, 1)
624
625
        # check Names (they are all ok, except 1 - sample)
626
        for i, name in enumerate(self.name_qs):
627
            # get the appropriate ValidationResultRecord
628
            result = responses[i]
629
630
            if hasattr(name, "animal"):
631
                self.assertEqual(name.status, READY)
632
633
            else:
634
                # sample has errors
635
                self.assertEqual(name.status, NEED_REVISION)
636
637
            self.assertEqual(
638
                name.validationresult.messages,
639
                result.get_messages())
640
641
            self.assertEqual(
642
                name.validationresult.status,
643
                result.get_overall_status())
644
645
        # test for my methods called
646
        self.assertTrue(my_check.called)
647
        self.assertTrue(my_validate.called)
648
        self.assertTrue(my_read.called)
649
650
651
class ValidateSubmissionStatusTest(ValidateSubmissionMixin, TestCase):
652
    """Check database statuses after calling validation"""
653
654
    def setUp(self):
655
        # calling base setup
656
        super().setUp()
657
658
        # track an animal for testing
659
        self.animal = Animal.objects.get(pk=1)
660
        self.animal_name = self.animal.name
661
662
    def check_status(self, status, messages, name_status):
663
        """Test if I can update status for a model that pass validation"""
664
665
        result = PickableMock()
666
        result.get_overall_status.return_value = status
667
        result.get_messages.return_value = messages
668
669
        submission_statuses = Counter(
670
            {'Pass': 0,
671
             'Warning': 0,
672
             'Error': 0,
673
             'JSON': 0})
674
675
        # calling update statuses
676
        self.my_task.update_statuses(submission_statuses, self.animal, result)
677
678
        # Test for animal status
679
        self.animal_name.refresh_from_db()
680
        self.assertEqual(self.animal_name.status, name_status)
681
682
        # get validation result object
683
        validationresult = self.animal_name.validationresult
684
        self.assertEqual(validationresult.status, status)
685
        self.assertEqual(validationresult.messages, messages)
686
687
        # test submission status
688
        self.assertEqual(submission_statuses[status], 1)
689
690
    def test_update_status_pass(self):
691
        status = 'Pass'
692
        messages = ['Passed all tests']
693
        name_status = READY
694
695
        self.check_status(status, messages, name_status)
696
697
    def test_update_status_warning(self):
698
        status = 'Warning'
699
        messages = ['issued a warning']
700
        name_status = READY
701
702
        self.check_status(status, messages, name_status)
703
704
    def test_update_status_error(self):
705
        status = 'Error'
706
        messages = ['issued an error']
707
        name_status = NEED_REVISION
708
709
        self.check_status(status, messages, name_status)
710
711
712
class ValidateUpdatedSubmissionStatusTest(ValidateSubmissionMixin, TestCase):
713
    """Check database statuses after calling validation for an updated
714
    submission (a submission completed and submitted to biosample in which
715
    I want to modify a thing)"""
716
717
    def setUp(self):
718
        # call base method
719
        super().setUp()
720
721
        # take all names and set them to completed, as after a successful
722
        # submission:
723
        self.name_qs.update(status=COMPLETED)
724
725
        # take the animal name I want to update
726
        self.animal_name = Name.objects.get(pk=3)
727
728
        # update submission status. Simulate a completed submission in which
729
        # I want to update something
730
        self.submission.status = NEED_REVISION
731
        self.submission.save()
732
733
        # update name objects. In this case, animal was modified
734
        self.animal_name.status = NEED_REVISION
735
        self.animal_name.save()
736
737
    def update_status(self, status, messages, name_status):
738
        """Test if I can update status for a model that pass validation"""
739
740
        # modelling validation same result for every object
741
        result = PickableMock()
742
        result.get_overall_status.return_value = status
743
        result.get_messages.return_value = messages
744
745
        submission_statuses = Counter(
746
            {'Pass': 0,
747
             'Warning': 0,
748
             'Error': 0,
749
             'JSON': 0})
750
751
        # calling update statuses on name objects
752
        for name in self.name_qs:
753
            if hasattr(name, "animal"):
754
                self.my_task.update_statuses(
755
                    submission_statuses,
756
                    name.animal,
757
                    result)
758
            else:
759
                self.my_task.update_statuses(
760
                    submission_statuses,
761
                    name.sample,
762
                    result)
763
764
        # refreshing data from db
765
        self.animal_name.refresh_from_db()
766
767
    def test_update_status_pass(self):
768
        status = 'Pass'
769
        messages = ['Passed all tests']
770
        name_status = READY
771
772
        self.update_status(status, messages, name_status)
773
774
        # asserting status change for animal
775
        self.assertEqual(self.animal_name.status, name_status)
776
777
        # validationresult is tested outside this class
778
779
        # other statuses are unchanged
780
        for name in self.name_qs.exclude(pk=self.animal_name.pk):
781
            self.assertEqual(name.status, COMPLETED)
782
783
    def test_update_status_warning(self):
784
        status = 'Warning'
785
        messages = ['issued a warning']
786
        name_status = READY
787
788
        self.update_status(status, messages, name_status)
789
790
        # asserting status change for animal
791
        self.assertEqual(self.animal_name.status, name_status)
792
793
        # other statuses are unchanged
794
        for name in self.name_qs.exclude(pk=self.animal_name.pk):
795
            self.assertEqual(name.status, COMPLETED)
796
797
    def test_update_status_error(self):
798
        status = 'Error'
799
        messages = ['issued an error']
800
        name_status = NEED_REVISION
801
802
        self.update_status(status, messages, name_status)
803
804
        # all statuses are changed (and need revisions)
805
        for name in self.name_qs:
806
            self.assertEqual(name.status, NEED_REVISION)
807