Completed
Branch master (206998)
by Paolo
02:15 queued 15s
created

validation.tests.test_helpers   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 452
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 22
eloc 230
dl 0
loc 452
rs 10
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A MetaDataValidationTestCase.test_issues_with_ebi() 0 15 1
A MetaDataValidationTestCase.test_issues_with_ruleset() 0 15 1
A SubmissionMixin.setUpClass() 0 9 1
A SubmissionTestCase.test_sample_relationship_issue() 0 26 1
A MetaDataValidationTestCase.check_biosample_id() 0 28 1
A SubmissionTestCase.test_sample_issue_organism_part() 0 31 1
A SubmissionMixin.setUp() 0 5 1
A SampleUpdateTestCase.setUp() 0 17 1
A SubmissionTestCase.test_submission() 0 19 1
A SampleUpdateTestCase.test_sample_update() 0 18 1
A RulesTestCase.test_check_ruleset() 0 9 1
A SubmissionTestCase.test_animal_relationship() 0 26 1
A SubmissionTestCase.test_sample() 0 21 1
A MetaDataValidationTestCase.test_check_biosample_id_issue() 0 9 1
A RulesTestCase.setUp() 0 2 1
A SubmissionTestCase.setUp() 0 11 1
A SubmissionTestCase.test_animal() 0 22 1
A SubmissionTestCase.test_wrong_json_structure() 0 15 1
A MetaDataValidationTestCase.test_check_biosample_id_target() 0 9 1
A ValidationSummaryTestCase.setUp() 0 13 1
A ValidationSummaryTestCase.test_initialization() 0 8 1
A ValidationSummaryTestCase.test_after_data_deletion() 0 19 1
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Tue Jan 22 14:28:16 2019
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import json
10
11
from image_validation.ValidationResult import ValidationResultRecord
12
from unittest.mock import patch, Mock
13
14
from django.test import TestCase
15
16
from image_app.models import Animal, Sample, Submission, Person, Name
17
18
from common.tests import PersonMixinTestCase
19
20
from ..helpers import (
21
    MetaDataValidation, OntologyCacheError, RulesetError)
22
23
from ..models import ValidationResult, ValidationSummary
24
25
26
class MetaDataValidationTestCase(TestCase):
27
    @patch("validation.helpers.validation.read_in_ruleset",
28
           side_effect=json.JSONDecodeError("meow", "woof", 42))
29
    def test_issues_with_ebi(self, my_issue):
30
        """
31
        Test temporary issues related with OLS EBI server during
32
        image_validation.use_ontology.OntologyCache loading"""
33
34
        # assert issues from validation.helpers.validation.read_in_ruleset
35
        self.assertRaisesMessage(
36
            OntologyCacheError,
37
            "Issue with 'https://www.ebi.ac.uk/ols/api/'",
38
            MetaDataValidation)
39
40
        # test mocked function called
41
        self.assertTrue(my_issue.called)
42
43
    @patch("validation.helpers.validation.check_ruleset",
44
           return_value=["Test for ruleset errors"])
45
    def test_issues_with_ruleset(self, my_issue):
46
        """
47
        Test errors regarding ruleset
48
        """
49
50
        # assert issues from validation.helpers.validation.read_in_ruleset
51
        self.assertRaisesMessage(
52
            RulesetError,
53
            "Test for ruleset errors",
54
            MetaDataValidation)
55
56
        # test mocked function called
57
        self.assertTrue(my_issue.called)
58
59
    @patch("requests.get")
60
    @patch("validation.helpers.validation.read_in_ruleset")
61
    @patch("validation.helpers.validation.check_ruleset",
62
           return_value=[])
63
    def check_biosample_id(self, my_check, my_read, mock_get, status_code):
64
        """Base method for checking biosample id"""
65
66
        # paching response
67
        response = Mock()
68
        response.status_code = status_code
69
        mock_get.return_value = response
70
71
        # create a fake ValidationResultRecord
72
        record_result = ValidationResultRecord(record_id="test")
73
74
        # get a metadata object
75
        metadata = MetaDataValidation()
76
77
        # check biosample object
78
        record_result = metadata.check_biosample_id_target(
79
            "FAKEA123456", "test", record_result)
80
81
        # assert my methods called
82
        self.assertTrue(my_check.called)
83
        self.assertTrue(my_read.called)
84
        self.assertTrue(mock_get.called)
85
86
        return record_result
87
88
    def test_check_biosample_id_target(self):
89
        """Test fecthing biosample ids from MetaDataValidation"""
90
91
        # pacthing response
92
        record_result = self.check_biosample_id(status_code=200)
93
94
        # test pass status and no messages
95
        self.assertEqual(record_result.get_overall_status(), 'Pass')
96
        self.assertEqual(record_result.get_messages(), [])
97
98
    def test_check_biosample_id_issue(self):
99
        """No valid biosample is found for this object"""
100
101
        # pacthing response
102
        record_result = self.check_biosample_id(status_code=404)
103
104
        # test Warning status and one message
105
        self.assertEqual(record_result.get_overall_status(), 'Warning')
106
        self.assertEqual(len(record_result.get_messages()), 1)
107
108
109
class SubmissionMixin(PersonMixinTestCase):
110
    # an attribute for PersonMixinTestCase
111
    person = Person
112
113
    fixtures = [
114
        'image_app/animal',
115
        'image_app/dictbreed',
116
        'image_app/dictcountry',
117
        'image_app/dictrole',
118
        'image_app/dictsex',
119
        'image_app/dictspecie',
120
        'image_app/dictstage',
121
        'image_app/dictuberon',
122
        'image_app/name',
123
        'image_app/ontology',
124
        'image_app/organization',
125
        'image_app/publication',
126
        'image_app/sample',
127
        'image_app/submission',
128
        'image_app/user'
129
    ]
130
131
    @classmethod
132
    def setUpClass(cls):
133
        # calling my base class setup
134
        super().setUpClass()
135
136
        # drop publication for semplicity
137
        name = Name.objects.get(pk=3)
138
        publication = name.publication
139
        publication.delete()
140
141
    def setUp(self):
142
        # calling my base class setup
143
        super().setUp()
144
145
        self.metadata = MetaDataValidation()
146
147
148
class SubmissionTestCase(SubmissionMixin, TestCase):
149
    """Deal real tests using image_validation library: this want to ensure
150
    that InjectTools can work with image_validation"""
151
152
    def setUp(self):
153
        # calling my base class setup
154
        super().setUp()
155
156
        # get an animal object
157
        self.animal = Animal.objects.get(pk=1)
158
        self.animal_record = self.animal.to_biosample()
159
160
        # get a sample object
161
        self.sample = Sample.objects.get(pk=1)
162
        self.sample_record = self.sample.to_biosample()
163
164
    def test_animal(self):
165
        """Testing an animal submission"""
166
167
        # at the time of writing this reference data raise one warning
168
        reference = ("Pass", "")
169
170
        # check for usi structure
171
        usi_result = self.metadata.check_usi_structure([self.animal_record])
172
        self.assertEqual(usi_result, [])
173
174
        # validate record
175
        result = self.metadata.validate(self.animal_record)
176
177
        # assert result type
178
        self.assertIsInstance(result, ValidationResultRecord)
179
        self.assertEqual(result.get_overall_status(), reference[0])
180
181
        def search(y):
182
            return reference[1] in y
183
184
        matches = [search(message) for message in result.get_messages()]
185
        self.assertNotIn(False, matches)
186
187
    def test_animal_relationship(self):
188
        """Testing an animal with a relationship"""
189
190
        # at the time of writing this reference data raise one warning
191
        reference = ("Pass", "")
192
193
        # get a to_biosample record
194
        animal = Animal.objects.get(pk=3)
195
        animal_record = animal.to_biosample()
196
197
        # check for usi structure
198
        usi_result = self.metadata.check_usi_structure([animal_record])
199
        self.assertEqual(usi_result, [])
200
201
        # validate record
202
        result = self.metadata.validate(animal_record)
203
204
        # assert result type
205
        self.assertIsInstance(result, ValidationResultRecord)
206
        self.assertEqual(result.get_overall_status(), reference[0])
207
208
        def search(y):
209
            return reference[1] in y
210
211
        matches = [search(message) for message in result.get_messages()]
212
        self.assertNotIn(False, matches)
213
214
    def test_sample(self):
215
        """Test a sample submission"""
216
217
        # at the time of writing this reference pass without problems
218
        reference = ("Pass", "")
219
220
        # check for usi structure
221
        usi_result = self.metadata.check_usi_structure([self.sample_record])
222
        self.assertEqual(usi_result, [])
223
224
        result = self.metadata.validate(self.sample_record)
225
226
        # assert result type
227
        self.assertIsInstance(result, ValidationResultRecord)
228
        self.assertEqual(result.get_overall_status(), reference[0])
229
230
        def search(y):
231
            return reference[1] == y
232
233
        matches = [search(message) for message in result.get_messages()]
234
        self.assertNotIn(False, matches)
235
236
    def test_sample_relationship_issue(self):
237
        """Testing an error with related alias. Not sure if it can happen or
238
        not"""
239
240
        # get record from sample
241
        record = self.sample_record
242
243
        # change alias in relationship in order to have no a related obj
244
        record["sampleRelationships"] = [{
245
            "alias": "IMAGEA999999999",
246
            "relationshipNature": "derived from"
247
        }]
248
249
        # create a fake ValidationResultRecord
250
        record_result = ValidationResultRecord(record_id=record['title'])
251
252
        # check relationship method
253
        related, result = self.metadata.check_relationship(
254
            record, record_result)
255
256
        # this is an error in results
257
        self.assertEqual(related, [])
258
        self.assertEqual(result.get_overall_status(), 'Error')
259
        self.assertIn(
260
            "Could not locate the referenced record",
261
            result.get_messages()[0])
262
263
    def test_sample_issue_organism_part(self):
264
        """Testing a problem in metadata: organism_part lacks of term"""
265
266
        # at the time of writing, this will have Errors
267
        reference = (
268
            "Error", (
269
                "Error: No url found for the field Organism part which has "
270
                "the type of ontology_id")
271
        )
272
273
        sample_record = self.sample.to_biosample()
274
275
        # set an attribute without ontology
276
        sample_record['attributes']['Organism part'] = [{'value': 'hair'}]
277
278
        # check for usi structure
279
        usi_result = self.metadata.check_usi_structure([sample_record])
280
        self.assertEqual(usi_result, [])
281
282
        # validate record. This will result in an error object
283
        result = self.metadata.validate(sample_record)
284
285
        # assert result type
286
        self.assertIsInstance(result, ValidationResultRecord)
287
        self.assertEqual(result.get_overall_status(), reference[0])
288
289
        def search(y):
290
            return reference[1] in y
291
292
        matches = [search(message) for message in result.get_messages()]
293
        self.assertNotIn(False, matches)
294
295
    def test_submission(self):
296
        """Testing usi_structure and duplicates in a submission"""
297
298
        # get all biosample data in a list
299
        data = [self.animal_record, self.sample_record]
300
301
        # test for usi structure
302
        usi_result = self.metadata.check_usi_structure(data)
303
304
        # no errors for check usi_structure
305
        self.assertIsInstance(usi_result, list)
306
        self.assertEqual(len(usi_result), 0)
307
308
        # test for duplicated data
309
        dup_result = self.metadata.check_duplicates(data)
310
311
        # no errors for check_duplicates
312
        self.assertIsInstance(dup_result, list)
313
        self.assertEqual(len(dup_result), 0)
314
315
    def test_wrong_json_structure(self):
316
        """Test that json structure is ok"""
317
318
        reference = [
319
            ('Wrong JSON structure: no title field for record with '
320
             'alias as IMAGEA000000001'),
321
        ]
322
323
        # delete some attributes from animal data
324
        del(self.animal_record['title'])
325
326
        # test for Json structure
327
        test = self.metadata.check_usi_structure([self.animal_record])
328
329
        self.assertEqual(reference, test)
330
331
332
class SampleUpdateTestCase(SubmissionMixin, TestCase):
333
    """Testing validation for a sample update"""
334
335
    def setUp(self):
336
        # calling my base class setup
337
        super().setUp()
338
339
        # get a samlple
340
        self.sample = Sample.objects.get(pk=1)
341
342
        # modify animal and sample
343
        self.animal_reference = "SAMEA4450079"
344
        self.sample.animal.name.biosample_id = self.animal_reference
345
        self.sample.animal.name.save()
346
347
        self.sample_reference = "SAMEA4450075"
348
        self.sample.name.biosample_id = self.sample_reference
349
        self.sample.name.save()
350
351
        self.record = self.sample.to_biosample()
352
353
    def test_sample_update(self):
354
        """Simulate a validation for an already submitted sample"""
355
356
        # at the time of writing this reference pass without problems
357
        reference = ("Pass", "")
358
359
        # check object
360
        result = self.metadata.validate(self.record)
361
362
        # assert result type
363
        self.assertIsInstance(result, ValidationResultRecord)
364
        self.assertEqual(result.get_overall_status(), reference[0])
365
366
        def search(y):
367
            return reference[1] == y
368
369
        matches = [search(message) for message in result.get_messages()]
370
        self.assertNotIn(False, matches)
371
372
373
class RulesTestCase(TestCase):
374
    """Assert that image rules are valid"""
375
376
    def setUp(self):
377
        self.metadata = MetaDataValidation()
378
379
    def test_check_ruleset(self):
380
        """Assert that rules are valid"""
381
382
        # get validation results
383
        ruleset_check = self.metadata.check_ruleset()
384
385
        # test image metadata rules
386
        self.assertIsInstance(ruleset_check, list)
387
        self.assertEqual(len(ruleset_check), 0)
388
389
390
class ValidationSummaryTestCase(TestCase):
391
    fixtures = [
392
        'image_app/animal',
393
        'image_app/dictbreed',
394
        'image_app/dictcountry',
395
        'image_app/dictrole',
396
        'image_app/dictsex',
397
        'image_app/dictspecie',
398
        'image_app/dictstage',
399
        'image_app/dictuberon',
400
        'image_app/name',
401
        'image_app/organization',
402
        'image_app/publication',
403
        'image_app/submission',
404
        'image_app/user',
405
        'image_app/sample',
406
        'validation/validationresult',
407
        'validation/validationsummary'
408
    ]
409
410
    def setUp(self):
411
        self.submission = Submission.objects.get(pk=1)
412
        self.validationsummary_animal = ValidationSummary.objects.get(
413
            submission=self.submission, type="animal")
414
        self.validationsummary_sample = ValidationSummary.objects.get(
415
            submission=self.submission, type="sample")
416
417
        # set names
418
        self.animal_name = Name.objects.get(pk=3)
419
        self.sample_name = Name.objects.get(pk=4)
420
421
        # track validationresult object
422
        self.validationresult = ValidationResult.objects.get(pk=1)
423
424
    def test_initialization(self):
425
        """Test that ValidationSummary is correctly initialized"""
426
427
        self.assertEqual(self.validationsummary_animal.all_count, 3)
428
        self.assertEqual(self.validationsummary_animal.issues_count, 0)
429
430
        self.assertEqual(self.validationsummary_sample.all_count, 1)
431
        self.assertEqual(self.validationsummary_sample.issues_count, 0)
432
433
    def test_after_data_deletion(self):
434
        """Ensure that all count changes after data deletion"""
435
436
        # drop one animal and one sample
437
        Animal.objects.get(pk=3).delete()
438
        Sample.objects.get(pk=1).delete()
439
440
        # call a method which updates animals and samples total count
441
        # HINT: should this number be updated when deleting animal and
442
        # samples in views?
443
        self.validationsummary_animal.reset_all_count()
444
        self.validationsummary_sample.reset_all_count()
445
446
        # test for counts
447
        self.assertEqual(self.validationsummary_animal.all_count, 2)
448
        self.assertEqual(self.validationsummary_animal.issues_count, 0)
449
450
        self.assertEqual(self.validationsummary_sample.all_count, 0)
451
        self.assertEqual(self.validationsummary_sample.issues_count, 0)
452