Completed
Push — master ( 24da64...15c423 )
by Gonzalo
65:23
created

EnvironmentTestCase.test_invalid_keys()   A

Complexity

Conditions 3

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
1
from collections import OrderedDict
2
import os
3
import random
4
import unittest
5
6
from conda.common.serialize import yaml_load
7
8
9
try:
10
    from io import StringIO
11
except ImportError:
12
    from StringIO import StringIO
13
14
from conda_env import env
15
from conda_env import exceptions
16
17
from . import support_file
18
19
20
class FakeStream(object):
21
    def __init__(self):
22
        self.output = ''
23
24
    def write(self, chunk):
25
        self.output += chunk.decode('utf-8')
26
27
28
def get_environment(filename):
29
    return env.from_file(support_file(filename))
30
31
32
def get_simple_environment():
33
    return get_environment('simple.yml')
34
35
36
def get_valid_keys_environment():
37
    return get_environment('valid_keys.yml')
38
39
40
def get_invalid_keys_environment():
41
    return get_environment('invalid_keys.yml')
42
43
44
class from_file_TestCase(unittest.TestCase):
45
    def test_returns_Environment(self):
46
        e = get_simple_environment()
47
        self.assertIsInstance(e, env.Environment)
48
49
    def test_retains_full_filename(self):
50
        e = get_simple_environment()
51
        self.assertEqual(support_file('simple.yml'), e.filename)
52
53
    def test_with_pip(self):
54
        e = env.from_file(support_file('with-pip.yml'))
55
        assert 'pip' in e.dependencies
56
        assert 'foo' in e.dependencies['pip']
57
        assert 'baz' in e.dependencies['pip']
58
59
60
class EnvironmentTestCase(unittest.TestCase):
61
    def test_has_empty_filename_by_default(self):
62
        e = env.Environment()
63
        self.assertEqual(e.filename, None)
64
65
    def test_has_filename_if_provided(self):
66
        r = random.randint(100, 200)
67
        random_filename = '/path/to/random/environment-{}.yml'.format(r)
68
        e = env.Environment(filename=random_filename)
69
        self.assertEqual(e.filename, random_filename)
70
71
    def test_has_empty_name_by_default(self):
72
        e = env.Environment()
73
        self.assertEqual(e.name, None)
74
75
    def test_has_name_if_provided(self):
76
        random_name = 'random-{}'.format(random.randint(100, 200))
77
        e = env.Environment(name=random_name)
78
        self.assertEqual(e.name, random_name)
79
80
    def test_dependencies_are_empty_by_default(self):
81
        e = env.Environment()
82
        self.assertEqual(0, len(e.dependencies))
83
84
    def test_parses_dependencies_from_raw_file(self):
85
        e = get_simple_environment()
86
        expected = OrderedDict([('conda', ['nltk'])])
87
        self.assertEqual(e.dependencies, expected)
88
89
    def test_builds_spec_from_line_raw_dependency(self):
90
        # TODO Refactor this inside conda to not be a raw string
91
        e = env.Environment(dependencies=['nltk=3.0.0=np18py27_0'])
92
        expected = OrderedDict([('conda', ['nltk==3.0.0=np18py27_0'])])
93
        self.assertEqual(e.dependencies, expected)
94
95
    def test_args_are_wildcarded(self):
96
        e = env.Environment(dependencies=['python=2.7'])
97
        expected = OrderedDict([('conda', ['python=2.7'])])
98
        self.assertEqual(e.dependencies, expected)
99
100
    def test_other_tips_of_dependencies_are_supported(self):
101
        e = env.Environment(
102
            dependencies=['nltk', {'pip': ['foo', 'bar']}]
103
        )
104
        expected = OrderedDict([
105
            ('conda', ['nltk', 'pip']),
106
            ('pip', ['foo', 'bar'])
107
        ])
108
        self.assertEqual(e.dependencies, expected)
109
110
    def test_channels_default_to_empty_list(self):
111
        e = env.Environment()
112
        self.assertIsInstance(e.channels, list)
113
        self.assertEqual(e.channels, [])
114
115
    def test_add_channels(self):
116
        e = env.Environment()
117
        e.add_channels(['dup', 'dup', 'unique'])
118
        self.assertEqual(e.channels, ['dup', 'unique'])
119
120
    def test_remove_channels(self):
121
        e = env.Environment(channels=['channel'])
122
        e.remove_channels()
123
        self.assertEqual(e.channels, [])
124
125
    def test_channels_are_provided_by_kwarg(self):
126
        random_channels = (random.randint(100, 200), random)
127
        e = env.Environment(channels=random_channels)
128
        self.assertEqual(e.channels, random_channels)
129
130
    def test_to_dict_returns_dictionary_of_data(self):
131
        random_name = 'random{}'.format(random.randint(100, 200))
132
        e = env.Environment(
133
            name=random_name,
134
            channels=['javascript'],
135
            dependencies=['nodejs']
136
        )
137
138
        expected = {
139
            'name': random_name,
140
            'channels': ['javascript'],
141
            'dependencies': ['nodejs']
142
        }
143
        self.assertEqual(e.to_dict(), expected)
144
145
    def test_to_dict_returns_just_name_if_only_thing_present(self):
146
        e = env.Environment(name='simple')
147
        expected = {'name': 'simple'}
148
        self.assertEqual(e.to_dict(), expected)
149
150
    def test_to_yaml_returns_yaml_parseable_string(self):
151
        random_name = 'random{}'.format(random.randint(100, 200))
152
        e = env.Environment(
153
            name=random_name,
154
            channels=['javascript'],
155
            dependencies=['nodejs']
156
        )
157
158
        expected = {
159
            'name': random_name,
160
            'channels': ['javascript'],
161
            'dependencies': ['nodejs']
162
        }
163
164
        actual = yaml_load(StringIO(e.to_yaml()))
165
        self.assertEqual(expected, actual)
166
167
    def test_to_yaml_returns_proper_yaml(self):
168
        random_name = 'random{}'.format(random.randint(100, 200))
169
        e = env.Environment(
170
            name=random_name,
171
            channels=['javascript'],
172
            dependencies=['nodejs']
173
        )
174
175
        expected = '\n'.join([
176
            "name: %s" % random_name,
177
            "channels:",
178
            "  - javascript",
179
            "dependencies:",
180
            "  - nodejs",
181
            ""
182
        ])
183
184
        actual = e.to_yaml()
185
        self.assertEqual(expected, actual)
186
187
    def test_to_yaml_takes_stream(self):
188
        random_name = 'random{}'.format(random.randint(100, 200))
189
        e = env.Environment(
190
            name=random_name,
191
            channels=['javascript'],
192
            dependencies=['nodejs']
193
        )
194
195
        s = FakeStream()
196
        e.to_yaml(stream=s)
197
198
        expected = "\n".join([
199
            'name: %s' % random_name,
200
            'channels:',
201
            '  - javascript',
202
            'dependencies:',
203
            '  - nodejs',
204
            '',
205
        ])
206
        self.assertEqual(expected, s.output)
207
208
    def test_can_add_dependencies_to_environment(self):
209
        e = get_simple_environment()
210
        e.dependencies.add('bar')
211
212
        s = FakeStream()
213
        e.to_yaml(stream=s)
214
215
        expected = "\n".join([
216
            'name: nlp',
217
            'dependencies:',
218
            '  - nltk',
219
            '  - bar',
220
            ''
221
        ])
222
        self.assertEqual(expected, s.output)
223
224
    def test_dependencies_update_after_adding(self):
225
        e = get_simple_environment()
226
        assert 'bar' not in e.dependencies['conda']
227
        e.dependencies.add('bar')
228
        assert 'bar' in e.dependencies['conda']
229
230
    def test_valid_keys(self):
231
        e = get_valid_keys_environment()
232
        e_dict = e.to_dict()
233
        for key in env.VALID_KEYS:
234
            assert key in e_dict
235
236
    def test_invalid_keys(self):
237
        e = get_invalid_keys_environment()
238
        e_dict = e.to_dict()
239
        assert 'name' in e_dict
240
        assert len(e_dict) == 1
241
242
243
class DirectoryTestCase(unittest.TestCase):
244
    directory = support_file('example')
245
246
    def setUp(self):
247
        self.original_working_dir = os.getcwd()
248
        self.env = env.load_from_directory(self.directory)
249
250
    def tearDown(self):
251
        os.chdir(self.original_working_dir)
252
253
    def test_returns_env_object(self):
254
        self.assertIsInstance(self.env, env.Environment)
255
256
    def test_has_expected_name(self):
257
        self.assertEqual('test', self.env.name)
258
259
    def test_has_dependencies(self):
260
        self.assertEqual(1, len(self.env.dependencies['conda']))
261
        assert 'numpy' in self.env.dependencies['conda']
262
263
264
class load_from_directory_example_TestCase(DirectoryTestCase):
265
    directory = support_file('example')
266
267
268
class load_from_directory_example_yaml_TestCase(DirectoryTestCase):
269
    directory = support_file('example-yaml')
270
271
272
class load_from_directory_recursive_TestCase(DirectoryTestCase):
273
    directory = support_file('foo/bar')
274
275
276
class load_from_directory_recursive_two_TestCase(DirectoryTestCase):
277
    directory = support_file('foo/bar/baz')
278
279
280
class load_from_directory_trailing_slash_TestCase(DirectoryTestCase):
281
    directory = support_file('foo/bar/baz/')
282
283
284
class load_from_directory_TestCase(unittest.TestCase):
285
    def test_raises_when_unable_to_find(self):
286
        with self.assertRaises(exceptions.EnvironmentFileNotFound):
287
            env.load_from_directory('/path/to/unknown/env-spec')
288
289
    def test_raised_exception_has_environment_yml_as_file(self):
290
        with self.assertRaises(exceptions.EnvironmentFileNotFound) as e:
291
            env.load_from_directory('/path/to/unknown/env-spec')
292
        self.assertEqual(e.exception.filename, 'environment.yml')
293
294
295
class LoadEnvFromFileAndSaveTestCase(unittest.TestCase):
296
    env_path = support_file(os.path.join('saved-env', 'environment.yml'))
297
298
    def setUp(self):
299
        with open(self.env_path, "rb") as fp:
300
            self.original_file_contents = fp.read()
301
        self.env = env.load_from_directory(self.env_path)
302
303
    def tearDown(self):
304
        with open(self.env_path, "wb") as fp:
305
            fp.write(self.original_file_contents)
306
307
    def test_expected_default_conditions(self):
308
        self.assertEqual(1, len(self.env.dependencies['conda']))
309
310
    def test(self):
311
        self.env.dependencies.add('numpy')
312
        self.env.save()
313
314
        e = env.load_from_directory(self.env_path)
315
        self.assertEqual(2, len(e.dependencies['conda']))
316
        assert 'numpy' in e.dependencies['conda']
317
318
319
class EnvironmentSaveTestCase(unittest.TestCase):
320
    env_file = support_file('saved.yml')
321
322
    def tearDown(self):
323
        if os.path.exists(self.env_file):
324
            os.unlink(self.env_file)
325
326
    def test_creates_file_on_save(self):
327
        self.assertFalse(os.path.exists(self.env_file), msg='sanity check')
328
329
        e = env.Environment(filename=self.env_file, name='simple')
330
        e.save()
331
332
        self.assertTrue(os.path.exists(self.env_file))
333
334
    def _test_saves_yaml_representation_of_file(self):
335
        e = env.Environment(filename=self.env_file, name='simple')
336
        e.save()
337
338
        with open(self.env_file, "rb") as fp:
339
            actual = fp.read()
340
341
        self.assert_(len(actual) > 0, msg='sanity check')
342
        self.assertEqual(e.to_yaml(), actual)
343