Completed
Pull Request — develop (#73)
by Angeline
11:09
created

test_cmd.TestCommandLine.execute_command_line()   A

Complexity

Conditions 2

Size

Total Lines 24
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 24
rs 10
c 0
b 0
f 0
cc 2
nop 2
1
# -*- coding: utf-8 -*-
2
"""Unit tests for command line execution."""
3
4
import numpy as np
5
import os
6
import pytest
7
import subprocess
8
9
10
class TestCommandLine():
11
    def setup(self):
12
        """Runs before every test method to create a clean environment."""
13
        # Define the desired working paths
14
        self.startdir = os.path.abspath(os.path.curdir)
15
        split_dirs = os.path.split(os.path.dirname(os.path.abspath(__file__)))
16
        self.workdir = split_dirs[0]
17
18
        # Change directory, if needed
19
        if self.startdir != self.workdir:
20
            os.chdir(self.workdir)
21
22
        # Define the test filenames
23
        self.outfile = os.path.join(split_dirs[1], 'output.txt')
24
        self.infile = os.path.join(split_dirs[1], 'test_convert.txt')
25
        self.singlefile = os.path.join(split_dirs[1],
26
                                       'test_convert_single_line.txt')
27
28
    def teardown(self):
29
        """Runs after every method to clean up previous testing."""
30
        # Remove testing output
31
        if os.path.isfile(self.outfile):
32
            os.remove(self.outfile)
33
34
        # Return to starting directory
35
        if self.startdir != os.path.abspath(os.path.curdir):
36
            os.chdir(self.startdir)
37
38
        del self.outfile, self.infile, self.singlefile
39
40
    def execute_command_line(self, command):
41
        """Execute the command and load data from self.outfile
42
43
        Parameters
44
        ----------
45
        command : list or str
46
            List or string containing command to execute using subprocess
47
48
        Returns
49
        -------
50
        data : np.array or NoneType
51
            Numpy array of data from output file or None if no file was created
52
53
        """
54
        pipe = subprocess.Popen(command)
55
        pipe.communicate()
56
        pipe.wait()
57
58
        if os.path.isfile(self.outfile):
59
            data = np.loadtxt(self.outfile)
60
        else:
61
            data = None
62
63
        return data
64
65
    @pytest.mark.parametrize("date_str", [("2015"), ("201501"), ('20150101'),
66
                                          ('20150101000000')])
67
    def test_convert_w_datetime(self, date_str):
68
        """Test command line with different date and time specification."""
69
        # Build and execute the apexpy command line call
70
        cmd = ['python', '-m', 'apexpy', 'geo', 'apex', date_str, '--height',
71
               '300', '-i', self.infile, '-o', self.outfile]
72
        data = self.execute_command_line(cmd)
73
74
        # Test the outfile existance and values
75
        assert data is not None, 'error executing: {:s}'.format(' '.join(cmd))
76
        np.testing.assert_allclose(data, [[57.47145462, 93.62657928],
77
                                          [58.52458191, 94.03150177],
78
                                          [59.57331467, 94.46398163]],
79
                                   rtol=1e-4)
80
        return
81
82
    def test_convert_single_line(self):
83
        """Test command line with a single line of output."""
84
        # Build and execute the apexpy command line call
85
        cmd = ['python', '-m', 'apexpy', 'geo', 'apex', '20150101000000',
86
               '--height', '300', '-i', self.singlefile, '-o', self.outfile]
87
        data = self.execute_command_line(cmd)
88
89
        # Test the outfile existance and values
90
        assert data is not None, 'error executing: {:s}'.format(' '.join(cmd))
91
        np.testing.assert_allclose(data, [57.47145462, 93.62657928], rtol=1e-4)
92
        return
93
94
    @pytest.mark.parametrize("height, out_list",
95
                             [("300", [57.47145462, 93.62657928]),
96
                              ("100 --refh=300", [56.01779556, 93.35305023])])
97
    def test_convert_stdin_stdout_w_height_flags(self, height, out_list):
98
        """Test use of pipe input to command-line call with height flags."""
99
        # Build and execute the apexpy command line call
100
        pipe = subprocess.Popen(
101
            'echo 60 15 | python -m apexpy geo apex 2015 --height {:s}'.format(
102
                height), shell=True, stdout=subprocess.PIPE)
103
        stdout, _ = pipe.communicate()
104
        pipe.wait()
105
        np.testing.assert_allclose(np.array(stdout.split(b' '), dtype=float),
106
                                   out_list, rtol=1e-4)
107
        return
108
109
    def test_convert_mlt(self):
110
        """Test magnetic local time conversion."""
111
        # Build and execute the apexpy command line call
112
        cmd = ['python', '-m', 'apexpy', 'geo', 'mlt', '20150101000000',
113
               '--height', '300', '-i', self.singlefile, '-o', self.outfile]
114
        data = self.execute_command_line(cmd)
115
116
        # Test the outfile existance and values
117
        assert data is not None, 'error executing: {:s}'.format(' '.join(cmd))
118
        np.testing.assert_allclose(data, [57.469547, 1.06324], rtol=1e-4)
119
        return
120
121
    @pytest.mark.parametrize("date_str", [("201501010"), ("2015010100000")])
122
    def test_invalid_date(self, date_str):
123
        """Test raises ValueError with an invalid input date."""
124
        # Build and execute the command
125
        pipe = subprocess.Popen(
126
            'echo 60 15 | python -m apexpy geo apex {:s}'.format(date_str),
127
            shell=True, stderr=subprocess.PIPE)
128
        _, stderr = pipe.communicate()
129
        pipe.wait()
130
131
        # Evaluate the error output
132
        assert b'ValueError' in stderr, 'invalid date error not raised'
133
        return
134
135
    def test_mlt_nodatetime(self):
136
        """Test raises ValueError when time not provided for MLT calc."""
137
        # Build and execute the command
138
        pipe = subprocess.Popen(
139
            'echo 60 15 | python -m apexpy geo mlt 20150101', shell=True,
140
            stderr=subprocess.PIPE)
141
        _, stderr = pipe.communicate()
142
        pipe.wait()
143
144
        # Evaluate the error output
145
        assert b'ValueError' in stderr, 'invalid time error not raised'
146
        return
147
148
    @pytest.mark.parametrize("coords", [("foobar apex"), ("geo foobar")])
149
    def test_invalid_coord(self, coords):
150
        """Test raises error when bad coordinate input provided."""
151
        # Build and execute the command
152
        pipe = subprocess.Popen(
153
            'echo 60 15 | python -m apexpy {:s} 2015'.format(coords),
154
            shell=True, stderr=subprocess.PIPE)
155
        _, stderr = pipe.communicate()
156
        pipe.wait()
157
158
        # Evaluate the error output
159
        assert b'invalid choice' in stderr, 'invalid coord error not raised'
160
        return
161