Passed
Pull Request — master (#26)
by Paolo
02:00
created

ValidateSubmissionMixin.check_async_called()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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