Passed
Pull Request — develop (#90)
by Angeline
01:29
created

aacgmv2.tests.test_struct_aacgmv2   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 269
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 148
dl 0
loc 269
rs 8.8798
c 0
b 0
f 0
wmc 44

31 Methods

Rating   Name   Duplication   Size   Complexity  
A TestTopVariables.test_top_parameters() 0 17 2
A TestPyStructure.teardown_method() 0 3 1
A TestUtilsStructure.test_dep_functions() 0 4 1
A TestTopVariables.test_high_alt_variables() 0 19 2
A TestTopStructure.setup_method() 0 4 1
A TestTopStructure.teardown_method() 0 3 1
A TestTopStructure.test_top_existence() 0 4 1
A TestDepStructure.test_dep_existence() 0 4 1
A TestUtilsStructure.setup_method() 0 4 1
A TestModuleStructure.test_module_existence() 0 12 3
A TestModuleStructure.test_modules() 0 13 3
A TestUtilsStructure.teardown_method() 0 3 1
A TestTopVariables.test_module_logger() 0 4 2
A TestUtilsStructure.test_dep_existence() 0 4 1
A TestModuleStructure.setup_method() 0 7 3
A TestDepStructure.teardown_method() 0 3 1
A TestModuleStructure.teardown_method() 0 3 1
A TestTopStructure.test_top_modules() 0 6 1
A TestPyStructure.setup_method() 0 8 1
A TestDepStructure.test_dep_functions() 0 4 1
A TestModuleStructure.test_module_functions() 0 22 5
A TestPyStructure.test_py_functions() 0 4 1
A TestCStructure.test_c_existence() 0 4 1
A TestPyStructure.test_py_existence() 0 4 1
A TestCStructure.setup_method() 0 7 1
A TestTopStructure.test_top_functions() 0 8 1
A TestCStructure.test_c_functions() 0 4 1
A TestDepStructure.setup_method() 0 4 1
A TestTopVariables.teardown_method() 0 3 1
A TestCStructure.teardown_method() 0 3 1
A TestTopVariables.setup_method() 0 8 1

How to fix   Complexity   

Complexity

Complex classes like aacgmv2.tests.test_struct_aacgmv2 often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""Unit tests for the AACGMV2 module structure."""
2
3
import logging
4
import numpy as np
5
import os
6
import pkgutil
7
import pytest
8
9
import aacgmv2
10
11
12
class TestModuleStructure(object):
13
    """Class for testing the module structure."""
14
15
    def setup_method(self):
16
        """Create a clean test environment."""
17
        # Define the acceptable output
18
        if not hasattr(self, "reference_list"):
19
            self.reference_list = list()
20
        if not hasattr(self, "module_name"):
21
            self.module_name = None
22
23
    def teardown_method(self):
24
        """Clean up the test environment."""
25
        del self.reference_list, self.module_name
26
27
    def test_module_existence(self):
28
        """Test the module existence."""
29
        # Get the dictionary of functions for the specified module
30
        retrieved_dict = aacgmv2.__dict__
31
32
        # Submodules only go one level down
33
        if self.module_name is None:
34
            assert True
35
        elif self.module_name != "aacgmv2":
36
            assert self.module_name in retrieved_dict.keys()
37
        else:
38
            assert isinstance(retrieved_dict, dict)
39
40
    def test_module_functions(self):
41
        """Test module function structure."""
42
        # Get the dictionary of functions for the specified module
43
        retrieved_dict = aacgmv2.__dict__
44
45
        if self.module_name is None:
46
            assert True
47
        else:
48
            if self.module_name != "aacgmv2":
49
                assert self.module_name in retrieved_dict.keys()
50
                retrieved_dict = retrieved_dict[self.module_name].__dict__
51
52
            # Get the functions attached to this module and make sure they
53
            # are supposed to be there
54
            retrieved_list = list()
55
            for name in retrieved_dict.keys():
56
                if callable(retrieved_dict[name]):
57
                    assert name in self.reference_list
58
                    retrieved_list.append(name)
59
60
            # Test to see if all of the modules match
61
            assert len(retrieved_list) == len(self.reference_list)
62
63
    def test_modules(self):
64
        """Test module submodule structure."""
65
        if self.module_name is None:
66
            assert True
67
        else:
68
            # Get the submodules and make sure they are supposed to be there
69
            retrieved_list = list()
70
            for imp, name, ispkg in pkgutil.iter_modules(path=aacgmv2.__path__):
71
                assert name in self.reference_list
72
                retrieved_list.append(name)
73
74
            # Test to see if all of the modules match
75
            assert len(retrieved_list) == len(self.reference_list)
76
77
78
class TestDepStructure(TestModuleStructure):
79
    """Test the deprecated structure."""
80
81
    def setup_method(self):
82
        """Create a clean test environment."""
83
        self.module_name = None
84
        self.reference_list = ["subsol", "igrf_dipole_axis", "gc2gd_lat"]
85
86
    def teardown_method(self):
87
        """Clean up the test environment."""
88
        del self.module_name, self.reference_list
89
90
    def test_dep_existence(self):
91
        """Test the deprecated functions."""
92
        self.module_name = "deprecated"
93
        self.test_module_existence()
94
95
    def test_dep_functions(self):
96
        """Test the deprecated functions."""
97
        self.module_name = "deprecated"
98
        self.test_module_functions()
99
100
101
class TestUtilsStructure(TestModuleStructure):
102
    """Test the utility structure."""
103
104
    def setup_method(self):
105
        """Create a clean test environment."""
106
        self.module_name = None
107
        self.reference_list = ["subsol", "igrf_dipole_axis", "gc2gd_lat"]
108
109
    def teardown_method(self):
110
        """Clean up the test environment."""
111
        del self.module_name, self.reference_list
112
113
    def test_dep_existence(self):
114
        """Test the utility functions."""
115
        self.module_name = "utils"
116
        self.test_module_existence()
117
118
    def test_dep_functions(self):
119
        """Test the utility functions."""
120
        self.module_name = "utils"
121
        self.test_module_functions()
122
123
124
class TestCStructure(TestModuleStructure):
125
    """Test the C structure."""
126
127
    def setup_method(self):
128
        """Create a clean test environment."""
129
        self.module_name = None
130
        self.reference_list = ["set_datetime", "convert", "inv_mlt_convert",
131
                               "inv_mlt_convert_yrsec", "mlt_convert",
132
                               "mlt_convert_yrsec", "inv_mlt_convert_arr",
133
                               "mlt_convert_arr", "convert_arr"]
134
135
    def teardown_method(self):
136
        """Clean up the test environment."""
137
        del self.module_name, self.reference_list
138
139
    def test_c_existence(self):
140
        """Test the C module existence."""
141
        self.module_name = "_aacgmv2"
142
        self.test_module_existence()
143
144
    def test_c_functions(self):
145
        """Test the C functions."""
146
        self.module_name = "_aacgmv2"
147
        self.test_module_functions()
148
149
150
class TestPyStructure(TestModuleStructure):
151
    """Test the Python structure."""
152
153
    def setup_method(self):
154
        """Create a clean test environment."""
155
        self.module_name = None
156
        self.reference_list = ["convert_bool_to_bit", "convert_str_to_bit",
157
                               "convert_mlt", "convert_latlon", "test_height",
158
                               "convert_latlon_arr", "get_aacgm_coord",
159
                               "get_aacgm_coord_arr", "set_coeff_path",
160
                               "test_time"]
161
162
    def teardown_method(self):
163
        """Clean up the test environment."""
164
        del self.module_name, self.reference_list
165
166
    def test_py_existence(self):
167
        """Test the python module existence."""
168
        self.module_name = "wrapper"
169
        self.test_module_existence()
170
171
    def test_py_functions(self):
172
        """Test the python functions."""
173
        self.module_name = "wrapper"
174
        self.test_module_functions()
175
176
177
class TestTopStructure(TestModuleStructure):
178
    """Test the top-level structure."""
179
180
    def setup_method(self):
181
        """Create a clean test environment."""
182
        self.module_name = None
183
        self.reference_list = list()
184
185
    def teardown_method(self):
186
        """Clean up the test environment."""
187
        del self.module_name, self.reference_list
188
189
    def test_top_existence(self):
190
        """Test the top level existence."""
191
        self.module_name = "aacgmv2"
192
        self.test_module_existence()
193
194
    def test_top_functions(self):
195
        """Test the deprecated functions."""
196
        self.module_name = "aacgmv2"
197
        self.reference_list = ["convert_bool_to_bit", "convert_str_to_bit",
198
                               "convert_mlt", "convert_latlon",
199
                               "convert_latlon_arr", "get_aacgm_coord",
200
                               "get_aacgm_coord_arr"]
201
        self.test_module_functions()
202
203
    def test_top_modules(self):
204
        """Test the deprecated functions."""
205
        self.module_name = "aacgmv2"
206
        self.reference_list = ["_aacgmv2", "wrapper", "utils",
207
                               "deprecated", "__main__", 'tests']
208
        self.test_modules()
209
210
211
class TestTopVariables(object):
212
    """Test the top-level variables."""
213
214
    def setup_method(self):
215
        """Create a clean test environment."""
216
        self.alt_limits = {"coeff": 2000.0, "trace": 6378.0}
217
        self.coeff_file = {"coeff": os.path.join("aacgmv2", "aacgmv2",
218
                                                 "aacgm_coeffs",
219
                                                 "aacgm_coeffs-14-"),
220
                           "igrf": os.path.join("aacgmv2", "aacgmv2",
221
                                                "magmodel_1590-2025.txt")}
222
223
    def teardown_method(self):
224
        """Clean up the test environment."""
225
        del self.alt_limits, self.coeff_file
226
227
    @pytest.mark.parametrize("env_var,fkey",
228
                             [(aacgmv2.AACGM_v2_DAT_PREFIX, "coeff"),
229
                              (aacgmv2.IGRF_COEFFS, "igrf")])
230
    def test_top_parameters(self, env_var, fkey):
231
        """Test module constants.
232
233
        Parameters
234
        ----------
235
        env_var : str
236
            Environment variable
237
        fkey : str
238
            Corresponding dict key
239
240
        """
241
        if env_var.find(self.coeff_file[fkey]) < 0:
242
            raise AssertionError("Bad env variable: {:} not {:}".format(
243
                self.coeff_file[fkey], env_var))
244
245
    @pytest.mark.parametrize("alt_var,alt_ref",
246
                             [(aacgmv2.high_alt_coeff, "coeff"),
247
                              (aacgmv2.high_alt_trace, "trace")])
248
    def test_high_alt_variables(self, alt_var, alt_ref):
249
        """Test that module altitude limits exist and are appropriate.
250
251
        Parameters
252
        ----------
253
        alt_var : float
254
            Altitude variable with float output
255
        alt_ref : str
256
            Output dict key
257
258
        """
259
        if not isinstance(alt_var, type(self.alt_limits[alt_ref])):
260
            raise TypeError("Altitude limit variable isn't a float")
261
262
        np.testing.assert_almost_equal(alt_var, self.alt_limits[alt_ref],
263
                                       decimal=4)
264
265
    def test_module_logger(self):
266
        """Test the module logger instance."""
267
        if not isinstance(aacgmv2.logger, logging.Logger):
268
            raise TypeError("Logger incorrect type")
269