Passed
Pull Request — master (#40)
by Paolo
01:37
created

ExcelTemplateTestCase.test_check_sex()   A

Complexity

Conditions 1

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 16
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 Tue Jul  2 10:58:42 2019
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import types
10
from collections import defaultdict
11
from unittest.mock import patch, Mock
12
13
from django.test import TestCase
14
15
from common.tests import WebSocketMixin
16
from image_app.models import DictCountry, DictSpecie, DictSex
17
from image_app.tests.mixins import DataSourceMixinTestCase
18
19
from ..helpers import ExcelTemplate, upload_template, TEMPLATE_COLUMNS
20
from .common import BaseExcelMixin
21
22
23
class ExcelTemplateTestCase(
24
        DataSourceMixinTestCase, BaseExcelMixin, TestCase):
25
    """Test excel class upload"""
26
27
    def setUp(self):
28
        # calling my base class setup
29
        super().setUp()
30
31
        self.maxDiff = None
32
33
        # crate a Excel Template object
34
        self.reader = ExcelTemplate()
35
36
        # get filenames for DataSourceMixinTestCase.dst_path
37
        self.reader.read_file(self.dst_path)
38
39
    def test_check_sheets(self):
40
        # test check sheets method
41
        status, not_found = self.reader.check_sheets()
42
43
        self.assertTrue(status)
44
        self.assertEqual(not_found, [])
45
46
        # override sheet names
47
        self.reader.sheet_names = []
48
49
        # check method
50
        status, not_found = self.reader.check_sheets()
51
52
        self.assertFalse(status)
53
        self.assertEqual(not_found, ['breed', 'animal', 'sample'])
54
55
    def test_check_columns(self):
56
        # test check sheets method
57
        status, not_found = self.reader.check_columns()
58
59
        self.assertTrue(status)
60
        self.assertIsInstance(not_found, defaultdict)
61
        self.assertEqual(len(not_found), 0)
62
63
    @patch('xlrd.open_workbook')
64
    def test_check_columns_issue(self, mock_open):
65
        """Test a file with columns issues"""
66
67
        # creating a mock excel book
68
        mock_book = Mock()
69
70
        # customizing the mock object
71
        mock_book.sheet_names.return_value = ['breed', 'animal', 'sample']
72
73
        # creating a mock sheet for breed
74
        breed_sheet = Mock()
75
        breed_sheet.nrows = 1
76
77
        # now setting rows to a fake sheet
78
        breed_sheet.row_values.return_value = []
79
80
        # creating a mock sheet for animal
81
        animal_sheet = Mock()
82
        animal_sheet.nrows = 1
83
84
        # now setting rows to a fake sheet
85
        animal_sheet.row_values.return_value = []
86
87
        # creating a mock sheet for sample
88
        sample_sheet = Mock()
89
        sample_sheet.nrows = 1
90
91
        # now setting rows to a fake sheet
92
        sample_sheet.row_values.return_value = []
93
94
        # finally setting sheet to the fabe excel object
95
        mock_book.sheet_by_name.side_effect = [
96
            breed_sheet, animal_sheet, sample_sheet]
97
98
        # returning the mock object when opening a workbook
99
        mock_open.return_value = mock_book
100
101
        # now calling methods
102
        reader = ExcelTemplate()
103
        reader.read_file("fake file")
104
105
        # create the reference error output
106
        reference = defaultdict(list)
107
        reference['breed'] += TEMPLATE_COLUMNS['breed']
108
        reference['animal'] += TEMPLATE_COLUMNS['animal']
109
        reference['sample'] += TEMPLATE_COLUMNS['sample']
110
111
        status, test = reader.check_columns()
112
113
        self.assertFalse(status)
114
        self.assertIsInstance(test, defaultdict)
115
        self.assertDictEqual(reference, test)
116
117
    def check_generator(self, records, length):
118
        self.assertIsInstance(records, types.GeneratorType)
119
        self.assertEqual(len(list(records)), length)
120
121
    def test_get_breed_records(self):
122
        """get_breed_records returns an iterator"""
123
124
        breeds = self.reader.get_breed_records()
125
        self.check_generator(breeds, 2)
126
127
    def test_get_animal_records(self):
128
        """get_animal_records returns an iterator"""
129
130
        animals = self.reader.get_animal_records()
131
        self.check_generator(animals, 3)
132
133
    def test_get_sample_records(self):
134
        """get_sample_records returns an iterator"""
135
136
        samples = self.reader.get_sample_records()
137
        self.check_generator(samples, 3)
138
139
    # TODO: pretty similar to CRBanim - move to a common mixin
140 View Code Duplication
    def test_check_species(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
141
        """Test check species method"""
142
143
        # get a country
144
        country = DictCountry.objects.get(label="United Kingdom")
145
146
        check, not_found = self.reader.check_species(country)
147
148
        self.assertTrue(check)
149
        self.assertEqual(len(not_found), 0)
150
151
        # changing species set
152
        DictSpecie.objects.filter(label='Sus scrofa').delete()
153
154
        check, not_found = self.reader.check_species(country)
155
156
        # the read species are not included in fixtures
157
        self.assertFalse(check)
158
        self.assertGreater(len(not_found), 0)
159
160
    # TODO: identical to CRBanim - move to a common mixin
161
    def test_check_sex(self):
162
        """Test check sex method"""
163
164
        check, not_found = self.reader.check_sex()
165
166
        self.assertTrue(check)
167
        self.assertEqual(len(not_found), 0)
168
169
        # changing sex set
170
        DictSex.objects.filter(label='female').delete()
171
172
        check, not_found = self.reader.check_sex()
173
174
        # the read species are not included in fixtures
175
        self.assertFalse(check)
176
        self.assertGreater(len(not_found), 0)
177
178
    def test_check_accuracies(self):
179
        """Test check accuracies method"""
180
181
        check, not_found = self.reader.check_accuracies()
182
183
        self.assertTrue(check)
184
        self.assertEqual(len(not_found), 0)
185
186
    @patch('xlrd.open_workbook')
187
    def test_check_accuracies_issue(self, mock_open):
188
        """Checking issues with accuracy in excels data"""
189
190
        # creating a mock excel book
191
        mock_book = Mock()
192
193
        # customizing the mock object
194
        mock_book.sheet_names.return_value = ['breed', 'animal', 'sample']
195
196
        # creating a mock sheet for animal
197
        animal_sheet = Mock()
198
        animal_sheet.nrows = 2
199
200
        # creating a fake row of data
201
        fake_row = ["" for col in TEMPLATE_COLUMNS['animal']]
202
203
        # get birth location accuracy index
204
        accuracy_idx = TEMPLATE_COLUMNS['animal'].index(
205
            "Birth location accuracy")
206
207
        # set a fake accuracy item
208
        fake_row[accuracy_idx] = "Fake"
209
210
        # now setting rows to a fake sheet
211
        animal_sheet.row_values.side_effect = [
212
            TEMPLATE_COLUMNS['animal'],
213
            fake_row]
214
215
        # creating a mock sheet for sample
216
        sample_sheet = Mock()
217
        sample_sheet.nrows = 2
218
219
        # creating a fake row of data
220
        fake_row = ["" for col in TEMPLATE_COLUMNS['sample']]
221
222
        # get birth location accuracy index
223
        accuracy_idx = TEMPLATE_COLUMNS['sample'].index(
224
            "Collection place accuracy")
225
226
        # set a fake accuracy item
227
        fake_row[accuracy_idx] = "Fake"
228
229
        # now setting rows to a fake sheet
230
        sample_sheet.row_values.side_effect = [
231
            TEMPLATE_COLUMNS['sample'],
232
            fake_row]
233
234
        # finally setting sheet to the fabe excel object
235
        mock_book.sheet_by_name.side_effect = [animal_sheet, sample_sheet]
236
237
        # returning the mock object when opening a workbook
238
        mock_open.return_value = mock_book
239
240
        # now calling methods
241
        reader = ExcelTemplate()
242
        reader.read_file("fake file")
243
244
        # define the expected value
245
        reference = (False, set(["Fake"]))
246
        test = reader.check_accuracies()
247
248
        self.assertEqual(reference, test)
249
250
251
class ExcelMixin(DataSourceMixinTestCase, WebSocketMixin, BaseExcelMixin):
252
    """Common tests for Excel classes"""
253
254
    # define the method to upload data from. Since the function is now inside
255
    # a class it becomes a method, specifically a bound method and is supposed
256
    # to receive the self attribute by default. If we don't want to get the
257
    # self attribute, we have to declare function as a staticmetho
258
    # https://stackoverflow.com/a/35322635/4385116
259
    upload_method = staticmethod(upload_template)
260
261
    def test_upload_template(self):
262
        """Testing uploading and importing data from excel template to UID"""
263
264
        # test data loaded
265
        message = "Template import completed for submission"
266
        self.upload_datasource(message)
267
268
        # check async message called
269
        notification_message = (
270
            'Template import completed for submission: 1')
271
        validation_message = {
272
            'animals': 3, 'samples': 3,
273
            'animal_unkn': 3, 'sample_unkn': 3,
274
            'animal_issues': 0, 'sample_issues': 0}
275
276
        # check async message called using WebSocketMixin.check_message
277
        self.check_message('Loaded', notification_message, validation_message)
278
279
    def check_errors(self, my_check, message, notification_message):
280
        """Common stuff for error in excel template loading"""
281
282
        super().check_errors(my_check, message)
283
284
        # check async message called using WebSocketMixin.check_message
285
        self.check_message('Error', notification_message)
286
287
288
class UploadTemplateTestCase(ExcelMixin, TestCase):
289
    """Test uploading data for Template excel path"""
290
291
    pass
292