Passed
Pull Request — develop (#57)
by Angeline
01:06
created

test_py_aacgmv2   F

Complexity

Total Complexity 140

Size/Duplication

Total Lines 868
Duplicated Lines 13.13 %

Importance

Changes 0
Metric Value
wmc 140
eloc 599
dl 114
loc 868
rs 2
c 0
b 0
f 0

93 Methods

Rating   Name   Duplication   Size   Complexity  
A TestGetAACGMCoord.teardown() 0 3 1
A TestConvertLatLon.teardown() 0 3 1
A TestConvertLatLon.test_convert_latlon() 0 11 1
A TestConvertLatLon.setup() 0 7 1
A TestConvertLatLonArr.test_convert_latlon_arr_list() 0 12 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_arr_mix() 0 12 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_datetime_date() 15 15 2
A TestConvertCode.teardown() 0 2 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_maxalt_failure() 0 12 1
A TestPyLogging.setup() 0 8 1
A TestConvertLatLon.test_convert_latlon_high_lat() 0 9 1
A TestConvertLatLon.test_convert_latlon_failure() 0 10 2
A TestMLTConvert.test_inv_convert_mlt_wrapping() 0 9 1
A TestMLTConvert.test_inv_convert_mlt_arr() 0 6 1
A TestMLTConvert.test_datetime_exception() 0 4 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_list() 0 12 2
A TestMLTConvert.test_inv_convert_mlt_single() 0 6 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_arr() 13 13 2
A TestConvertLatLonArr.setup() 11 11 1
A TestHeightReturns.test_high_trace_good() 0 4 1
A TestHeightReturns.test_high_coeff_good() 0 5 1
A TestCoeffPath.setup() 0 6 1
A TestConvertLatLonArr.test_convert_latlon_arr_failure() 0 14 2
A TestConvertLatLonArr.test_convert_latlon_arr_clip() 0 8 1
A TestPyLogging.test_warning_high_coeff() 0 8 2
A TestConvertCode.setup() 0 2 1
A TestTimeReturns.test_good_time_with_nonzero_time() 0 4 1
A TestMLTConvert.test_mlt_convert_single() 0 6 2
A TestMLTConvert.teardown() 0 4 1
A TestConvertLatLonArr.test_convert_latlon_arr_badidea() 0 14 2
A TestConvertCode.test_convert_bool_to_bit() 0 15 2
A TestHeightReturns.setup() 0 5 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_list_mix() 0 12 2
A TestTimeReturns.setup() 0 5 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_list_single() 12 12 2
A TestTimeReturns.test_good_date() 0 4 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_arr_single() 12 12 2
A TestConvertLatLon.test_convert_latlon_location_failure() 0 6 1
A TestMLTConvert.test_inv_convert_mlt_list() 0 4 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_mlat_failure() 0 8 2
A TestGetAACGMCoord.test_get_aacgm_coord() 0 11 1
A TestConvertLatLonArr.test_convert_latlon_arr_maxalt_failure() 0 6 1
A TestCoeffPath.teardown() 0 3 1
A TestTimeReturns.teardown() 0 3 1
A TestGetAACGMCoord.test_get_aacgm_coord_maxalt_failure() 0 5 1
A TestTimeReturns.test_bad_time() 0 4 2
A TestGetAACGMCoord.test_get_aacgm_coord_datetime_date() 0 6 1
A TestPyLogging.test_warning_below_ground() 0 8 2
A TestMLTConvert.test_mlt_convert_change() 0 7 1
A TestPyLogging.test_warning_single_loc_in_arr() 0 8 2
A TestConvertCode.test_convert_str_to_bit_spaces() 0 5 2
A TestGetAACGMCoord.test_get_aacgm_coord_location_failure() 0 9 1
A TestGetAACGMCoordArr.teardown() 0 4 1
A TestMLTConvert.setup() 0 13 1
B TestCoeffPath.test_set_coeff_path() 0 29 8
A TestTimeReturns.test_good_time() 0 4 1
A TestMLTConvert.test_mlt_convert_list() 0 5 1
A TestConvertLatLonArr.test_convert_latlon_arr_list_mix() 0 12 2
A TestConvertLatLonArr.test_convert_latlon_arr_arr_single() 12 12 2
A TestConvertLatLonArr.test_convert_latlon_arr_arr() 13 13 2
A TestPyLogging.test_warning_magnetosphere() 0 8 2
A TestConvertLatLonArr.teardown() 0 4 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_single_val() 0 11 2
A TestConvertLatLonArr.test_convert_latlon_arr_single_val() 0 11 2
A TestHeightReturns.teardown() 0 3 1
A TestHeightReturns.test_high_trace_bad() 0 4 1
A TestGetAACGMCoord.setup() 0 7 1
A TestConvertLatLonArr.test_convert_latlon_arr_location_failure() 0 15 2
A TestMLTConvert.test_mlt_convert_arr() 0 5 1
A TestMLTConvert.test_mlt_convert_mismatch_failure() 0 5 2
A TestHeightReturns.test_high_coeff_bad() 0 5 1
A TestConvertLatLonArr.test_convert_latlon_arr_datetime_date() 0 12 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_badidea() 0 13 2
A TestConvertLatLonArr.test_convert_latlon_arr_arr_mult_and_single_element() 0 13 2
A TestConvertLatLon.test_convert_latlon_maxalt_failure() 0 5 1
A TestConvertLatLon.test_convert_latlon_datetime_date() 0 6 1
A TestMLTConvert.test_mlt_convert_multidim_failure() 0 5 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_location_failure() 0 10 1
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_mult_failure() 0 7 2
A TestGetAACGMCoordArr.test_get_aacgm_coord_arr_time_failure() 0 5 2
A TestGetAACGMCoord.test_get_aacgm_coord_raise_value_error() 0 8 2
A TestPyLogging.teardown() 0 4 1
A TestConvertCode.test_convert_str_to_bit() 0 12 2
A TestConvertLatLonArr.test_convert_latlon_arr_list_single() 12 12 2
A TestMLTConvert.test_mlt_convert_list_w_times() 0 6 1
A TestConvertLatLonArr.test_convert_latlon_arr_arr_mix() 0 12 2
A TestMLTConvert.test_date_input() 0 5 1
A TestHeightReturns.test_low_coeff_good() 0 4 1
A TestGetAACGMCoordArr.setup() 12 12 1
A TestHeightReturns.test_low_height_good() 0 4 1
A TestHeightReturns.test_low_trace_good() 0 4 1
A TestConvertCode.test_convert_str_to_bit_invalid() 0 4 2
A TestMLTConvert.test_mlt_convert_mlon_wrapping() 0 9 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like test_py_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
# -*- coding: utf-8 -*-
2
from __future__ import division, absolute_import, unicode_literals
3
4
import datetime as dt
5
from io import StringIO
6
import logging
7
import numpy as np
8
import os
9
from sys import version_info
10
import pytest
11
import warnings
12
13
import aacgmv2
14
15
16
class TestConvertLatLon:
17
    def setup(self):
18
        """Runs before every method to create a clean testing setup"""
19
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
20
        self.ddate = dt.date(2015, 1, 1)
21
        self.in_args = [60, 0]
22
        self.out = None
23
        self.rtol = 1.0e-4
24
25
    def teardown(self):
26
        """Runs after every method to clean up previous testing"""
27
        del self.out, self.in_args, self.rtol, self.dtime, self.ddate
28
29
    @pytest.mark.parametrize('alt,method_code,ref',
30
                             [(300, 'TRACE', [58.2268, 81.1613, 1.0457]),
31
                              (3000.0, "G2A|BADIDEA", [64.3578, 83.2895,
32
                                                       1.4694]),
33
                              (7000.0, "G2A|TRACE|BADIDEA",
34
                               [69.3187, 85.0845, 2.0973])])
35
    def test_convert_latlon(self, alt, method_code, ref):
36
        """Test single value latlon conversion"""
37
        self.in_args.extend([alt, self.dtime, method_code])
38
        self.out = aacgmv2.convert_latlon(*self.in_args)
39
        np.testing.assert_allclose(self.out, ref, rtol=self.rtol)
40
41
    @pytest.mark.parametrize('lat,ref',
42
                             [(90.01, [83.927161, 170.1471396, 1.04481923]),
43
                              (-90.01, [-74.9814852, 17.990332, 1.044819236])])
44
    def test_convert_latlon_high_lat(self, lat, ref):
45
        """Test single latlon conversion with latitude just out of bounds"""
46
        self.in_args[0] = lat
47
        self.in_args.extend([300, self.dtime, 'G2A'])
48
        self.out = aacgmv2.convert_latlon(*self.in_args)
49
        np.testing.assert_allclose(self.out, ref, rtol=self.rtol)
50
51
    def test_convert_latlon_datetime_date(self):
52
        """Test single latlon conversion with date and datetime input"""
53
        self.in_args.extend([300, self.ddate, 'TRACE'])
54
        self.out = aacgmv2.convert_latlon(*self.in_args)
55
        np.testing.assert_allclose(self.out, [58.2268, 81.1613, 1.0457],
56
                                   rtol=self.rtol)
57
58
    @pytest.mark.skipif(version_info.major == 2,
59
                        reason='Not raised in Python 2')
60
    def test_convert_latlon_location_failure(self):
61
        """Test single value latlon conversion with a bad location"""
62
        self.out = aacgmv2.convert_latlon(0, 0, 0, self.dtime, self.in_args[-1])
63
        assert np.all(np.isnan(np.array(self.out)))
64
65
    def test_convert_latlon_maxalt_failure(self):
66
        """test convert_latlon failure for an altitude too high for coeffs"""
67
        self.in_args.extend([2001, self.dtime, ""])
68
        self.out = aacgmv2.convert_latlon(*self.in_args)
69
        assert np.all(np.isnan(np.array(self.out)))
70
71
    @pytest.mark.parametrize('in_rep,in_irep,msg',
72
                             [(None, 3, "must be a datetime object"),
73
                              (91, 0, "unrealistic latitude"),
74
                              (-91, 0, "unrealistic latitude"),
75
                              (None, 4, "unknown method code")])
76
    def test_convert_latlon_failure(self, in_rep, in_irep, msg):
77
        self.in_args.extend([300, self.dtime, "G2A"])
78
        self.in_args[in_irep] = in_rep
79
        with pytest.raises(ValueError, match=msg):
80
            aacgmv2.convert_latlon(*self.in_args)
81
82
83
class TestConvertLatLonArr:
84 View Code Duplication
    def setup(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
85
        """Runs before every method to create a clean testing setup"""
86
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
87
        self.ddate = dt.date(2015, 1, 1)
88
        self.lat_in = [60.0, 61.0]
89
        self.lon_in = [0.0, 0.0]
90
        self.alt_in = [300.0, 300.0]
91
        self.method = 'TRACE'
92
        self.out = None
93
        self.ref = [[58.2268, 59.3184], [81.1613, 81.6080], [1.0457, 1.0456]]
94
        self.rtol = 1.0e-4
95
96
    def teardown(self):
97
        """Runs after every method to clean up previous testing"""
98
        del self.lat_in, self.lon_in, self.alt_in, self.dtime, self.ddate
99
        del self.method, self.out, self.ref, self.rtol
100
101
    def test_convert_latlon_arr_single_val(self):
102
        """Test array latlon conversion for a single value"""
103
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
104
                                              self.alt_in[0], self.dtime,
105
                                              self.method)
106
107
        assert len(self.out) == len(self.ref)
108
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
109
110
        for i, oo in enumerate(self.out):
111
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
112
113 View Code Duplication
    def test_convert_latlon_arr_list_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
114
        """Test array latlon conversion for list input of single values"""
115
        self.out = aacgmv2.convert_latlon_arr([self.lat_in[0]],
116
                                              [self.lon_in[0]],
117
                                              [self.alt_in[0]], self.dtime,
118
                                              self.method)
119
120
        assert len(self.out) == len(self.ref)
121
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
122
123
        for i, oo in enumerate(self.out):
124
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
125
126
    def test_convert_latlon_arr_list(self):
127
        """Test array latlon conversion for list input"""
128
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in,
129
                                              self.alt_in, self.dtime,
130
                                              self.method)
131
132
        assert len(self.out) == len(self.ref)
133
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
134
                for i, oo in enumerate(self.out)]
135
136
        for i, oo in enumerate(self.out):
137
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
138
139 View Code Duplication
    def test_convert_latlon_arr_arr_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
140
        """Test array latlon conversion for array input of shape (1,)"""
141
        self.out = aacgmv2.convert_latlon_arr(np.array([self.lat_in[0]]),
142
                                              np.array([self.lon_in[0]]),
143
                                              np.array([self.alt_in[0]]),
144
                                              self.dtime, self.method)
145
146
        assert len(self.out) == len(self.ref)
147
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
148
149
        for i, oo in enumerate(self.out):
150
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
151
152 View Code Duplication
    def test_convert_latlon_arr_arr(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
153
        """Test array latlon conversion for array input"""
154
        self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in),
155
                                              np.array(self.lon_in),
156
                                              np.array(self.alt_in),
157
                                              self.dtime, self.method)
158
159
        assert len(self.out) == len(self.ref)
160
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
161
                for i, oo in enumerate(self.out)]
162
163
        for i, oo in enumerate(self.out):
164
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
165
166
    def test_convert_latlon_arr_list_mix(self):
167
        """Test array latlon conversion for mixed types with list"""
168
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in[0],
169
                                              self.alt_in[0], self.dtime,
170
                                              self.method)
171
172
        assert len(self.out) == len(self.ref)
173
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
174
                for i, oo in enumerate(self.out)]
175
176
        for i, oo in enumerate(self.out):
177
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
178
179
    def test_convert_latlon_arr_arr_mix(self):
180
        """Test array latlon conversion for mixed type with an array"""
181
        self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in),
182
                                              self.lon_in[0], self.alt_in[0],
183
                                              self.dtime, self.method)
184
185
        assert len(self.out) == len(self.ref)
186
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
187
                for i, oo in enumerate(self.out)]
188
189
        for i, oo in enumerate(self.out):
190
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
191
192
    def test_convert_latlon_arr_arr_mult_and_single_element(self):
193
        """Test latlon conversion for arrays with multiple and single vals"""
194
        self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in),
195
                                              np.array([self.lon_in[0]]),
196
                                              np.array(self.alt_in),
197
                                              self.dtime, self.method)
198
199
        assert len(self.out) == len(self.ref)
200
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
201
                for i, oo in enumerate(self.out)]
202
203
        for i, oo in enumerate(self.out):
204
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
205
206
    @pytest.mark.parametrize('method_code,alt,ref',
207
                             [("BADIDEA", 3000.0, [64.3580, 83.2895, 1.4694]),
208
                              ("BADIDEA|TRACE", 7000.0,
209
                               [69.3187, 85.0845, 2.0973])])
210
    def test_convert_latlon_arr_badidea(self, method_code, alt, ref):
211
        """Test array latlon conversion for BADIDEA"""
212
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
213
                                              [alt], self.dtime, method_code)
214
215
        assert len(self.out) == len(ref)
216
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
217
218
        for i, oo in enumerate(self.out):
219
            np.testing.assert_allclose(oo, [ref[i]], rtol=self.rtol)
220
221
    @pytest.mark.skipif(version_info.major == 2,
222
                        reason='Not raised in Python 2')
223
    def test_convert_latlon_arr_location_failure(self):
224
        """Test array latlon conversion with a bad location"""
225
226
        with warnings.catch_warnings():
227
            # Causes all warnings to be surpressed
228
            warnings.simplefilter("ignore")
229
230
            # Trigger a warning
231
            self.out = aacgmv2.convert_latlon_arr([0], [0], [0], self.dtime, "")
232
233
            # Test the output
234
            assert len(self.out) == len(self.ref)
235
            assert np.any(~np.isfinite(np.array(self.out)))
236
237
    def test_convert_latlon_arr_datetime_date(self):
238
        """Test array latlon conversion with date and datetime input"""
239
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in,
240
                                              self.alt_in, self.ddate,
241
                                              self.method)
242
243
        assert len(self.out) == len(self.ref)
244
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
245
                for i, oo in enumerate(self.out)]
246
247
        for i, oo in enumerate(self.out):
248
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
249
250
    def test_convert_latlon_arr_clip(self):
251
        """Test array latlon conversion with latitude clipping"""
252
        self.lat_in = [90.01, -90.01]
253
        self.ref = [[83.92716, -75.09343], [170.14714, 17.81937],
254
                    [1.044819, 1.052667]]
255
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in,
256
                                              self.alt_in, self.ddate,
257
                                              self.method)
258
259
    def test_convert_latlon_arr_maxalt_failure(self):
260
        """test convert_latlon_arr failure for altitudes too high for coeffs"""
261
        self.method = ""
262
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
263
                                              [2001], self.dtime, self.method)
264
        assert np.all(np.isnan(np.array(self.out)))
265
266
    @pytest.mark.parametrize('in_rep,in_irep,msg',
267
                             [(None, 3, "must be a datetime object"),
268
                              ([np.full(shape=(3, 2), fill_value=50.0), 0],
269
                               [0, 1], "unable to process multi-dimensional"),
270
                              ([50, 60, 70], 0, "arrays are mismatched"),
271
                              ([[91, 60, -91], 0, 300], [0, 1, 2],
272
                               "unrealistic latitude"),
273
                              (None, 4, "unknown method code")])
274
    def test_convert_latlon_arr_failure(self, in_rep, in_irep, msg):
275
        in_args = np.array([self.lat_in, self.lon_in, self.alt_in, self.dtime,
276
                            "G2A"], dtype=object)
277
        in_args[in_irep] = in_rep
278
        with pytest.raises(ValueError, match=msg):
279
            aacgmv2.convert_latlon_arr(*in_args)
280
281
282
class TestGetAACGMCoord:
283
    def setup(self):
284
        """Runs before every method to create a clean testing setup"""
285
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
286
        self.ddate = dt.date(2015, 1, 1)
287
        self.in_args = [60, 0]
288
        self.out = None
289
        self.rtol = 1.0e-4
290
291
    def teardown(self):
292
        """Runs after every method to clean up previous testing"""
293
        del self.out, self.in_args, self.rtol, self.dtime, self.ddate
294
295
    @pytest.mark.parametrize('alt,method_code,ref',
296
                             [(300, 'TRACE', [58.2268, 81.1613, 0.1888]),
297
                              (3000.0, "G2A|BADIDEA", [64.3578, 83.2895,
298
                                                       0.3307]),
299
                              (7000.0, "G2A|TRACE|BADIDEA",
300
                               [69.3187, 85.0845, 0.4503])])
301
    def test_get_aacgm_coord(self, alt, method_code, ref):
302
        """Test single value AACGMV2 calculation, defaults to TRACE"""
303
        self.in_args.extend([alt, self.dtime, method_code])
304
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
305
        np.testing.assert_allclose(self.out, ref, rtol=self.rtol)
306
307
    def test_get_aacgm_coord_datetime_date(self):
308
        """Test single AACGMV2 calculation with date and datetime input"""
309
        self.in_args.extend([300.0, self.ddate, 'TRACE'])
310
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
311
        np.testing.assert_allclose(self.out, [58.2268, 81.1613, 0.1888],
312
                                   rtol=self.rtol)
313
314
    @pytest.mark.skipif(version_info.major == 2,
315
                        reason='Not raised in Python 2')
316
    def test_get_aacgm_coord_location_failure(self):
317
        """Test single value AACGMV2 calculation with a bad location"""
318
        self.in_args.extend([0.0, self.dtime, 'TRACE'])
319
        self.in_args[0] = 0.0
320
321
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
322
        np.all(np.isnan(np.array(self.out)))
323
324
    def test_get_aacgm_coord_maxalt_failure(self):
325
        """test get_aacgm_coord failure for an altitude too high for coeffs"""
326
        self.in_args.extend([2001, self.dtime, ""])
327
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
328
        assert np.all(np.isnan(np.array(self.out)))
329
330
    @pytest.mark.parametrize('in_index,value',
331
                             [(3, None), (0, 91.0), (0, -91.0)])
332
    def test_get_aacgm_coord_raise_value_error(self, in_index, value):
333
        """Test different ways to raise a ValueError"""
334
        self.in_args.extend([300.0, self.dtime])
335
        self.in_args[in_index] = value
336
        with pytest.raises(ValueError):
337
            self.out = aacgmv2.get_aacgm_coord(*self.in_args)
338
339
340
class TestGetAACGMCoordArr:
341 View Code Duplication
    def setup(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
342
        """Runs before every method to create a clean testing setup"""
343
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
344
        self.ddate = dt.date(2015, 1, 1)
345
        self.lat_in = [60.0, 61.0]
346
        self.lon_in = [0.0, 0.0]
347
        self.alt_in = [300.0, 300.0]
348
        self.method = 'TRACE'
349
        self.out = None
350
        self.ref = [[58.22676, 59.31847], [81.16135, 81.60797],
351
                    [0.18880, 0.21857]]
352
        self.rtol = 1.0e-4
353
354
    def teardown(self):
355
        """Runs after every method to clean up previous testing"""
356
        del self.out, self.ref, self.lat_in, self.dtime, self.ddate
357
        del self.lon_in, self.alt_in, self.method, self.rtol
358
359
    def test_get_aacgm_coord_arr_single_val(self):
360
        """Test array AACGMV2 calculation for a single value"""
361
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in[0], self.lon_in[0],
362
                                               self.alt_in[0], self.dtime,
363
                                               self.method)
364
365
        assert len(self.out) == len(self.ref)
366
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
367
368
        for i, oo in enumerate(self.out):
369
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
370
371 View Code Duplication
    def test_get_aacgm_coord_arr_list_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
372
        """Test array AACGMV2 calculation for list input of single values"""
373
        self.out = aacgmv2.get_aacgm_coord_arr([self.lat_in[0]],
374
                                               [self.lon_in[0]],
375
                                               [self.alt_in[0]], self.dtime,
376
                                               self.method)
377
378
        assert len(self.out) == len(self.ref)
379
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
380
381
        for i, oo in enumerate(self.out):
382
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
383
384
    def test_get_aacgm_coord_arr_list(self):
385
        """Test array AACGMV2 calculation for list input"""
386
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
387
                                               self.alt_in, self.dtime,
388
                                               self.method)
389
390
        assert len(self.out) == len(self.ref)
391
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
392
                for oo in self.out]
393
394
        for i, oo in enumerate(self.out):
395
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
396
397 View Code Duplication
    def test_get_aacgm_coord_arr_arr_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
398
        """Test array AACGMV2 calculation for array with a single value"""
399
        self.out = aacgmv2.get_aacgm_coord_arr(np.array([self.lat_in[0]]),
400
                                               np.array([self.lon_in[0]]),
401
                                               np.array([self.alt_in[0]]),
402
                                               self.dtime, self.method)
403
404
        assert len(self.out) == len(self.ref)
405
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
406
407
        for i, oo in enumerate(self.out):
408
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
409
410 View Code Duplication
    def test_get_aacgm_coord_arr_arr(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
411
        """Test array AACGMV2 calculation for an array"""
412
        self.out = aacgmv2.get_aacgm_coord_arr(np.array(self.lat_in),
413
                                               np.array(self.lon_in),
414
                                               np.array(self.alt_in),
415
                                               self.dtime, self.method)
416
417
        assert len(self.out) == len(self.ref)
418
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
419
                for oo in self.out]
420
421
        for i, oo in enumerate(self.out):
422
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
423
424
    def test_get_aacgm_coord_arr_list_mix(self):
425
        """Test array AACGMV2 calculation for a list and floats"""
426
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in[0],
427
                                               self.alt_in[0], self.dtime,
428
                                               self.method)
429
430
        assert len(self.out) == len(self.ref)
431
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
432
                for oo in self.out]
433
434
        for i, oo in enumerate(self.out):
435
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
436
437
    def test_get_aacgm_coord_arr_arr_mix(self):
438
        """Test array AACGMV2 calculation for an array and floats"""
439
        self.out = aacgmv2.get_aacgm_coord_arr(np.array(self.lat_in),
440
                                               self.lon_in[0], self.alt_in[0],
441
                                               self.dtime, self.method)
442
443
        assert len(self.out) == len(self.ref)
444
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
445
                for oo in self.out]
446
447
        for i, oo in enumerate(self.out):
448
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
449
450
    def test_get_aacgm_coord_arr_mult_failure(self):
451
        """Test aacgm_coord_arr failure with multi-dim array input"""
452
453
        with pytest.raises(ValueError):
454
            (self.mlat_out, self.mlon_out,
455
             self.mlt_out) = aacgmv2.get_aacgm_coord_arr(
456
                 np.array([[60, 61, 62], [63, 64, 65]]), 0, 300, self.dtime)
457
458
    def test_get_aacgm_coord_arr_badidea(self):
459
        """Test array AACGMV2 calculation for BADIDEA"""
460
        self.method = "|".join([self.method, "BADIDEA"])
461
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in[0], self.lon_in[0],
462
                                               [3000.0], self.dtime,
463
                                               self.method)
464
465
        assert len(self.out) == len(self.ref)
466
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
467
468
        self.ref = [64.3481, 83.2885, 0.3306]
469
        for i, oo in enumerate(self.out):
470
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
471
472
    @pytest.mark.skipif(version_info.major == 2,
473
                        reason='Not raised in Python 2')
474
    def test_get_aacgm_coord_arr_location_failure(self):
475
        """Test array AACGMV2 calculation with a bad location"""
476
        self.out = aacgmv2.get_aacgm_coord_arr([0], [0], [0], self.dtime,
477
                                               self.method)
478
479
        assert len(self.out) == len(self.ref)
480
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
481
        assert np.any([np.isnan(oo) for oo in self.out])
482
483
    def test_get_aacgm_coord_arr_time_failure(self):
484
        """Test array AACGMV2 calculation with a bad time"""
485
        with pytest.raises(ValueError):
486
            aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in, self.alt_in,
487
                                        None, self.method)
488
489
    def test_get_aacgm_coord_arr_mlat_failure(self):
490
        """Test error return for co-latitudes above 90 for an array"""
491
492
        self.lat_in = [91, 60, -91]
493
        with pytest.raises(ValueError):
494
            self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in[0],
495
                                                   self.alt_in[0], self.dtime,
496
                                                   self.method)
497
498 View Code Duplication
    def test_get_aacgm_coord_arr_datetime_date(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
499
        """Test array AACGMV2 calculation with date and datetime input"""
500
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
501
                                               self.alt_in, self.ddate,
502
                                               self.method)
503
        self.ref = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
504
                                               self.alt_in, self.dtime,
505
                                               self.method)
506
507
        assert len(self.out) == len(self.ref)
508
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
509
                for oo in self.out]
510
511
        for i, oo in enumerate(self.out):
512
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
513
514
    def test_get_aacgm_coord_arr_maxalt_failure(self):
515
        """test aacgm_coord_arr failure for an altitude too high for coeff"""
516
        self.method = ""
517
        self.alt_in = [2001 for ll in self.lat_in]
518
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
519
                                               self.alt_in, self.dtime,
520
                                               self.method)
521
522
        assert len(self.out) == len(self.ref)
523
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
524
                for oo in self.out]
525
        assert np.all(np.isnan(np.array(self.out)))
526
527
528
class TestConvertCode:
529
    def setup(self):
530
        self.c_method_code = None
531
532
    def teardown(self):
533
        del self.c_method_code
534
535
    @pytest.mark.parametrize('method_code',
536
                             [('G2A'), ('A2G'), ('TRACE'), ('ALLOWTRACE'),
537
                              ('BADIDEA'), ('GEOCENTRIC'), ('g2a')])
538
    def test_convert_str_to_bit(self, method_code):
539
        """Test conversion from string code to bit"""
540
        if hasattr(aacgmv2._aacgmv2, method_code.upper()):
541
            self.c_method_code = getattr(aacgmv2._aacgmv2, method_code.upper())
542
        else:
543
            raise ValueError('cannot find method in C code: {:}'.format(
544
                method_code))
545
546
        assert aacgmv2.convert_str_to_bit(method_code) == self.c_method_code
547
548
    def test_convert_str_to_bit_spaces(self):
549
        """Test conversion from string code to bit for a code with spaces"""
550
        if(aacgmv2.convert_str_to_bit("G2A | trace")
551
           != aacgmv2._aacgmv2.G2A + aacgmv2._aacgmv2.TRACE):
552
            raise AssertionError()
553
554
    def test_convert_str_to_bit_invalid(self):
555
        """Test conversion from string code to bit for an invalid code"""
556
        if aacgmv2.convert_str_to_bit("ggoogg|") != aacgmv2._aacgmv2.G2A:
557
            raise AssertionError()
558
559
    @pytest.mark.parametrize('bool_dict,method_code',
560
                             [({}, 'G2A'), ({'a2g': True}, 'A2G'),
561
                              ({'trace': True}, 'TRACE'),
562
                              ({'allowtrace': True}, 'ALLOWTRACE'),
563
                              ({'badidea': True}, 'BADIDEA'),
564
                              ({'geocentric': True}, 'GEOCENTRIC')])
565
    def test_convert_bool_to_bit(self, bool_dict, method_code):
566
        """Test conversion from Boolean code to bit"""
567
        if hasattr(aacgmv2._aacgmv2, method_code.upper()):
568
            self.c_method_code = getattr(aacgmv2._aacgmv2, method_code.upper())
569
        else:
570
            raise ValueError('cannot find method in C code: {:}'.format(
571
                method_code))
572
573
        assert aacgmv2.convert_bool_to_bit(**bool_dict) == self.c_method_code
574
575
576
class TestMLTConvert:
577
    def setup(self):
578
        """Runs before every method to create a clean testing setup"""
579
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
580
        self.dtime2 = dt.datetime(2015, 1, 1, 10, 0, 0)
581
        self.ddate = dt.date(2015, 1, 1)
582
        self.mlon_out = None
583
        self.mlt_out = None
584
        self.mlt_diff = None
585
        self.mlon_list = [270.0, 80.0, -95.0]
586
        self.mlt_list = [12.0, 25.0, -1.0]
587
        self.mlon_comp = [-101.670617955439, 93.329382044561, 63.329382044561]
588
        self.mlt_comp = [12.7780412, 0.11137453, 12.44470786]
589
        self.diff_comp = np.ones(shape=(3,)) * -10.52411552
590
591
    def teardown(self):
592
        """Runs after every method to clean up previous testing"""
593
        del self.mlon_out, self.mlt_out, self.mlt_list, self.mlon_list
594
        del self.mlon_comp, self.mlt_comp, self.mlt_diff, self.diff_comp
595
596
    def test_date_input(self):
597
        """Test to see that the date input works"""
598
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.ddate,
599
                                           m2a=False)
600
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
601
602
    def test_datetime_exception(self):
603
        """Test to see that a value error is raised with bad time input"""
604
        with pytest.raises(ValueError):
605
            self.mlt_out = aacgmv2.wrapper.convert_mlt(self.mlon_list, 1997)
606
607
    def test_inv_convert_mlt_single(self):
608
        """Test MLT inversion for a single value"""
609
        for i, mlt in enumerate(self.mlt_list):
610
            self.mlon_out = aacgmv2.convert_mlt(mlt, self.dtime, m2a=True)
611
            np.testing.assert_almost_equal(self.mlon_out, self.mlon_comp[i],
612
                                           decimal=4)
613
614
    def test_inv_convert_mlt_list(self):
615
        """Test MLT inversion for a list"""
616
        self.mlon_out = aacgmv2.convert_mlt(self.mlt_list, self.dtime, m2a=True)
617
        np.testing.assert_allclose(self.mlon_out, self.mlon_comp, rtol=1.0e-4)
618
619
    def test_inv_convert_mlt_arr(self):
620
        """Test MLT inversion for an array"""
621
        self.mlon_out = aacgmv2.convert_mlt(np.array(self.mlt_list), self.dtime,
622
                                            m2a=True)
623
624
        np.testing.assert_allclose(self.mlon_out, self.mlon_comp, rtol=1.0e-4)
625
626
    def test_inv_convert_mlt_wrapping(self):
627
        """Test MLT wrapping"""
628
        self.mlon_out = aacgmv2.convert_mlt(np.array([1, 25, -1, 23]),
629
                                            self.dtime, m2a=True)
630
631
        np.testing.assert_almost_equal(self.mlon_out[0], self.mlon_out[1],
632
                                       decimal=6)
633
        np.testing.assert_almost_equal(self.mlon_out[2], self.mlon_out[3],
634
                                       decimal=6)
635
636
    def test_mlt_convert_mlon_wrapping(self):
637
        """Test mlon wrapping"""
638
        self.mlt_out = aacgmv2.convert_mlt(np.array([270, -90, 1, 361]),
639
                                           self.dtime, m2a=False)
640
641
        np.testing.assert_almost_equal(self.mlt_out[0], self.mlt_out[1],
642
                                       decimal=6)
643
        np.testing.assert_almost_equal(self.mlt_out[2], self.mlt_out[3],
644
                                       decimal=6)
645
646
    def test_mlt_convert_single(self):
647
        """Test MLT calculation for a single value"""
648
        for i, mlon in enumerate(self.mlon_list):
649
            self.mlt_out = aacgmv2.convert_mlt(mlon, self.dtime, m2a=False)
650
            np.testing.assert_almost_equal(self.mlt_out, self.mlt_comp[i],
651
                                           decimal=4)
652
653
    def test_mlt_convert_list(self):
654
        """Test MLT calculation for a list"""
655
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.dtime,
656
                                           m2a=False)
657
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
658
659
    def test_mlt_convert_arr(self):
660
        """Test MLT calculation for an array"""
661
        self.mlt_out = aacgmv2.convert_mlt(np.array(self.mlon_list),
662
                                           self.dtime, m2a=False)
663
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
664
665
    def test_mlt_convert_list_w_times(self):
666
        """Test MLT calculation for data and time arrays"""
667
        self.dtime = [self.dtime for dd in self.mlon_list]
668
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.dtime,
669
                                           m2a=False)
670
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
671
672
    def test_mlt_convert_change(self):
673
        """Test that MLT changes with UT"""
674
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.dtime)
675
        self.mlt_diff = np.array(self.mlt_out) \
676
            - np.array(aacgmv2.convert_mlt(self.mlon_list, self.dtime2))
677
678
        np.testing.assert_allclose(self.mlt_diff, self.diff_comp, rtol=1.0e-4)
679
680
    def test_mlt_convert_multidim_failure(self):
681
        """Test MLT calculation failure for multi-dimensional arrays"""
682
        self.mlon_list = np.full(shape=(3, 2), fill_value=50.0)
683
        with pytest.raises(ValueError):
684
            aacgmv2.convert_mlt(self.mlon_list, self.dtime, m2a=False)
685
686
    def test_mlt_convert_mismatch_failure(self):
687
        """Test MLT calculation failure for mismatched array input"""
688
        with pytest.raises(ValueError):
689
            aacgmv2.convert_mlt(self.mlon_list, [self.dtime, self.dtime2],
690
                                m2a=False)
691
692
693
class TestCoeffPath:
694
695
    def setup(self):
696
        """Runs before every method to create a clean testing setup"""
697
        os.environ['IGRF_COEFFS'] = "default_igrf"
698
        os.environ['AACGM_v2_DAT_PREFIX'] = "default_coeff"
699
        self.ref = {"igrf_file": os.environ['IGRF_COEFFS'],
700
                    "coeff_prefix": os.environ['AACGM_v2_DAT_PREFIX']}
701
702
    def teardown(self):
703
        """Runs after every method to clean up previous testing"""
704
        del self.ref
705
706
    @pytest.mark.parametrize("in_coeff",
707
                             [({}),
708
                              ({"igrf_file": "hi", "coeff_prefix": "bye"}),
709
                              ({"igrf_file": True, "coeff_prefix": True}),
710
                              ({"coeff_prefix": "hi"}),
711
                              ({"igrf_file": "hi"}),
712
                              ({"igrf_file": None, "coeff_prefix": None})])
713
    def test_set_coeff_path(self, in_coeff):
714
        """Test the coefficient path setting using default values"""
715
        # Update the reference key, if needed
716
        for ref_key in in_coeff.keys():
717
            if in_coeff[ref_key] is True or in_coeff[ref_key] is None:
718
                if ref_key == "igrf_file":
719
                    self.ref[ref_key] = aacgmv2.IGRF_COEFFS
720
                elif ref_key == "coeff_prefix":
721
                    self.ref[ref_key] = aacgmv2.AACGM_v2_DAT_PREFIX
722
            else:
723
                self.ref[ref_key] = in_coeff[ref_key]
724
725
        # Run the routine
726
        aacgmv2.wrapper.set_coeff_path(**in_coeff)
727
728
        # Ensure the environment variables were set correctly
729
        if os.environ['IGRF_COEFFS'] != self.ref['igrf_file']:
730
            raise AssertionError("{:} != {:}".format(os.environ['IGRF_COEFFS'],
731
                                                     self.ref['igrf_file']))
732
        if os.environ['AACGM_v2_DAT_PREFIX'] != self.ref['coeff_prefix']:
733
            raise AssertionError("{:} != {:}".format(
734
                os.environ['AACGM_v2_DAT_PREFIX'], self.ref['coeff_prefix']))
735
736
737
class TestHeightReturns:
738
    def setup(self):
739
        """Runs before every method to create a clean testing setup"""
740
        self.code = aacgmv2._aacgmv2.A2G
741
        self.bad_code = aacgmv2._aacgmv2.BADIDEA
742
        self.trace_code = aacgmv2._aacgmv2.TRACE
743
744
    def teardown(self):
745
        """Runs after every method to clean up previous testing"""
746
        del self.code, self.bad_code
747
748
    def test_low_height_good(self):
749
        """ Test to see that a very low height is still accepted"""
750
751
        assert aacgmv2.wrapper.test_height(-1, self.code)
752
753
    def test_high_coeff_bad(self):
754
        """ Test to see that a high altitude for coefficent use fails"""
755
756
        assert not aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff + 10.0,
757
                                               self.code)
758
759
    def test_high_coeff_good(self):
760
        """ Test a high altitude for coefficent use with badidea """
761
762
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff + 10.0,
763
                                           self.bad_code)
764
765
    def test_low_coeff_good(self):
766
        """ Test that a normal height succeeds"""
767
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff * 0.5,
768
                                           self.code)
769
770
    def test_high_trace_bad(self):
771
        """ Test that a high trace height fails"""
772
        assert not aacgmv2.wrapper.test_height(aacgmv2.high_alt_trace + 10.0,
773
                                               self.code)
774
775
    def test_low_trace_good(self):
776
        """ Test that a high coefficient height succeeds with trace"""
777
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff + 10.0,
778
                                           self.trace_code)
779
780
    def test_high_trace_good(self):
781
        """ Test that a high trace height succeeds with badidea"""
782
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_trace + 10.0,
783
                                           self.bad_code)
784
785
786
class TestPyLogging:
787
    def setup(self):
788
        """Runs before every method to create a clean testing setup"""
789
790
        self.lwarn = u""
791
        self.lout = u""
792
        self.log_capture = StringIO()
793
        aacgmv2.logger.addHandler(logging.StreamHandler(self.log_capture))
794
        aacgmv2.logger.setLevel(logging.INFO)
795
796
    def teardown(self):
797
        """Runs after every method to clean up previous testing"""
798
        self.log_capture.close()
799
        del self.lwarn, self.lout, self.log_capture
800
801
    def test_warning_below_ground(self):
802
        """ Test that a warning is issued if height < 0 for height test """
803
        self.lwarn = u"conversion not intended for altitudes < 0 km"
804
805
        aacgmv2.wrapper.test_height(-1, 0)
806
        self.lout = self.log_capture.getvalue()
807
        if self.lout.find(self.lwarn) < 0:
808
            raise AssertionError()
809
810
    def test_warning_magnetosphere(self):
811
        """ Test that a warning is issued if altitude is very high"""
812
        self.lwarn = u"coordinates are not intended for the magnetosphere"
813
814
        aacgmv2.wrapper.test_height(70000, aacgmv2._aacgmv2.TRACE)
815
        self.lout = self.log_capture.getvalue()
816
        if self.lout.find(self.lwarn) < 0:
817
            raise AssertionError()
818
819
    def test_warning_high_coeff(self):
820
        """ Test that a warning is issued if altitude is very high"""
821
        self.lwarn = u"must either use field-line tracing (trace=True"
822
823
        aacgmv2.wrapper.test_height(3000, 0)
824
        self.lout = self.log_capture.getvalue()
825
        if self.lout.find(self.lwarn) < 0:
826
            raise AssertionError()
827
828
    def test_warning_single_loc_in_arr(self):
829
        """ Test that user is warned they should be using simpler routine"""
830
        self.lwarn = u"for a single location, consider using"
831
832
        aacgmv2.convert_latlon_arr(60, 0, 300, dt.datetime(2015, 1, 1, 0, 0, 0))
833
        self.lout = self.log_capture.getvalue()
834
        if self.lout.find(self.lwarn) < 0:
835
            raise AssertionError()
836
837
838
class TestTimeReturns:
839
    def setup(self):
840
        """Runs before every method to create a clean testing setup"""
841
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
842
        self.dtime2 = dt.datetime(2015, 1, 1, 10, 10, 10)
843
        self.ddate = dt.date(2015, 1, 1)
844
845
    def teardown(self):
846
        """Runs after every method to clean up previous testing"""
847
        del self.dtime, self.ddate, self.dtime2
848
849
    def test_good_time(self):
850
        """ Test to see that a good datetime is accepted"""
851
852
        assert self.dtime == aacgmv2.wrapper.test_time(self.dtime)
853
854
    def test_good_time_with_nonzero_time(self):
855
        """ Test to see that a good datetime with h/m/s is accepted"""
856
857
        assert self.dtime2 == aacgmv2.wrapper.test_time(self.dtime2)
858
859
    def test_good_date(self):
860
        """ Test to see that a good date has a good datetime output"""
861
862
        assert self.dtime == aacgmv2.wrapper.test_time(self.dtime)
863
864
    def test_bad_time(self):
865
        """ Test to see that a warning is raised with a bad time input"""
866
        with pytest.raises(ValueError):
867
            aacgmv2.wrapper.test_time(2015)
868