Skip to content

Commit 601f03c

Browse files
committed
WIP Unit tests Recipe download feature
Currently unit tests the following: - `Recipe.download_if_necessary()` - `Recipe.download()` Next up is `Recipe.download_file()`
1 parent e21cd8b commit 601f03c

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

pythonforandroid/recipe.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ def report_hook(index, blksize, size):
156156
while True:
157157
try:
158158
urlretrieve(url, target, report_hook)
159-
except OSError as e:
159+
except OSError:
160160
attempts += 1
161161
if attempts >= 5:
162-
raise e
162+
raise
163163
stdout.write('Download failed retrying in a second...')
164164
time.sleep(1)
165165
continue

tests/test_recipe.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
11
import os
2+
import tempfile
23
import types
34
import unittest
45
import warnings
6+
import mock
57
from pythonforandroid.build import Context
68
from pythonforandroid.recipe import Recipe, import_recipe
79

810

11+
def patch_recipe_download():
12+
return mock.patch.object(Recipe, 'download')
13+
14+
15+
def patch_os_environ(env_dict):
16+
return mock.patch.dict(os.environ, env_dict)
17+
18+
19+
def patch_logger(level):
20+
return mock.patch('pythonforandroid.recipe.{}'.format(level))
21+
22+
23+
def patch_logger_info():
24+
return patch_logger('info')
25+
26+
27+
def patch_logger_debug():
28+
return patch_logger('debug')
29+
30+
31+
def patch_sh_touch():
32+
return mock.patch('pythonforandroid.recipe.sh.touch')
33+
34+
35+
class DummyRecipe(Recipe):
36+
pass
37+
38+
939
class TestRecipe(unittest.TestCase):
1040

1141
def test_recipe_dirs(self):
@@ -58,3 +88,48 @@ def test_import_recipe(self):
5888
module = import_recipe(name, pathname)
5989
assert module is not None
6090
assert recorded_warnings == []
91+
92+
def test_download_if_necessary(self):
93+
"""
94+
Download should happen via `Recipe.download()` only if the recipe
95+
specific environment variable is not set.
96+
"""
97+
# download should happen as the environment variable is not set
98+
recipe = DummyRecipe()
99+
with mock.patch.object(Recipe, 'download') as m_download:
100+
recipe.download_if_necessary()
101+
assert m_download.call_args_list == [mock.call()]
102+
# after setting it the download should be skipped
103+
env_var = 'P4A_test_recipe_DIR'
104+
env_dict = {env_var: '1'}
105+
with patch_recipe_download() as m_download, patch_os_environ(env_dict):
106+
recipe.download_if_necessary()
107+
assert m_download.call_args_list == []
108+
109+
def test_download(self):
110+
"""
111+
Verifies the actual download gets triggered when the URL is set.
112+
"""
113+
# test with no URL set
114+
recipe = DummyRecipe()
115+
with patch_logger_info() as m_info:
116+
recipe.download()
117+
assert m_info.call_args_list == [
118+
mock.call('Skipping test_recipe download as no URL is set')]
119+
# when the URL is set `Recipe.download_file()` should be called
120+
filename = 'Python-3.7.4.tgz'
121+
url = 'https://www.python.org/ftp/python/3.7.4/{}'.format(filename)
122+
recipe._url = url
123+
context = Context()
124+
context.setup_dirs(tempfile.gettempdir())
125+
recipe.ctx = context
126+
# TODO: this will actually mkdir on file system, we should discard it
127+
with patch_logger_debug() as m_debug, mock.patch.object(Recipe, 'download_file') as m_download_file, \
128+
patch_sh_touch() as m_touch:
129+
recipe.download()
130+
assert m_download_file.call_args_list == [mock.call(url, filename)]
131+
assert m_debug.call_args_list == [
132+
mock.call(
133+
'Downloading test_recipe from '
134+
'https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz')]
135+
assert m_touch.call_count == 1

0 commit comments

Comments
 (0)