Skip to content

Commit

Permalink
Merge pull request #416 from PyAr/update-automatic-tests
Browse files Browse the repository at this point in the history
Refreshed platforms and Python versions for automatic tests.
  • Loading branch information
facundobatista committed Mar 28, 2022
2 parents f2a1ff1 + 62fbb3c commit 703d4b0
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 92 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ jobs:
run-tests:
strategy:
matrix:
# no macos-11: https://github.com/actions/virtual-environments/issues/841
os: [ubuntu-20.04, ubuntu-18.04, macos-10.15, windows-2019, windows-2016]
python-version: [3.6, 3.7, 3.8, 3.9]
os: [ubuntu-20.04, ubuntu-18.04, macos-10.15, macos-11, windows-2019, windows-2022]
python-version: [3.8, 3.9, "3.10"]

runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion fades/pipmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def _download_pip_installer(self):
os.rename(temp_location, self.pip_installer_fname)

def _brute_force_install_pip(self):
"""A brute force install of pip itself."""
"""Check a brute force install of pip itself."""
if os.path.exists(self.pip_installer_fname):
logger.debug("Using pip installer from %r", self.pip_installer_fname)
else:
Expand Down
19 changes: 7 additions & 12 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
flake8==3.8.3
logassert>=5
pep257==0.7.0
pep8==1.7.1
pyuca==1.2
pyxdg==0.26
rst2html5==1.10.6
setuptools>=5.5
pytest==6.0.1
pytest-xdist==1.34.0
pytest-sugar==0.9.4
pytest-mock==3.2.0
flake8
logassert
pydocstyle
pytest
pyuca
pyxdg
rst2html5
29 changes: 15 additions & 14 deletions tests/test_cache/test_caches.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2019 Facundo Batista, Nicolás Demarchi
# Copyright 2015-2022 Facundo Batista, Nicolás Demarchi
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
Expand All @@ -14,43 +14,44 @@
#
# For further info, check https://github.com/PyAr/fades

from unittest.mock import patch

from fades import cache


def test_missing_file_pytest(tmp_file, mocker):
def test_missing_file_pytest(tmp_file):
venvscache = cache.VEnvsCache(str(tmp_file))
mock = mocker.patch.object(venvscache, '_select')
mock.return_value = None
resp = venvscache.get_venv('requirements', 'interpreter', uuid='', options='options')
with patch.object(venvscache, '_select', return_value=None) as mock:
resp = venvscache.get_venv('requirements', 'interpreter', uuid='', options='options')
mock.assert_called_with([], 'requirements', 'interpreter', uuid='', options='options')
assert not resp


def test_empty_file_pytest(tmp_file, mocker):
def test_empty_file_pytest(tmp_file):
open(tmp_file, 'wt', encoding='utf8').close()
venvscache = cache.VEnvsCache(tmp_file)
mock = mocker.patch.object(venvscache, '_select', return_value=None)
resp = venvscache.get_venv('requirements', 'interpreter')
with patch.object(venvscache, '_select', return_value=None) as mock:
resp = venvscache.get_venv('requirements', 'interpreter')
mock.assert_called_with([], 'requirements', 'interpreter', uuid='', options=None)
assert not resp


def test_some_file_content_pytest(tmp_file, mocker):
def test_some_file_content_pytest(tmp_file):
with open(tmp_file, 'wt', encoding='utf8') as fh:
fh.write('foo\nbar\n')
venvscache = cache.VEnvsCache(tmp_file)
mock = mocker.patch.object(venvscache, '_select', return_value="resp")
resp = venvscache.get_venv('requirements', 'interpreter', uuid='', options='options')
with patch.object(venvscache, '_select', return_value="resp") as mock:
resp = venvscache.get_venv('requirements', 'interpreter', uuid='', options='options')
mock.assert_called_with(['foo', 'bar'], 'requirements', 'interpreter', uuid='',
options='options')
assert resp == 'resp'


def test_get_by_uuid_pytest(tmp_file, mocker):
def test_get_by_uuid_pytest(tmp_file):
with open(tmp_file, 'wt', encoding='utf8') as fh:
fh.write('foo\nbar\n')
venvscache = cache.VEnvsCache(tmp_file)
mock = mocker.patch.object(venvscache, '_select', return_value='resp')
resp = venvscache.get_venv(uuid='uuid')
with patch.object(venvscache, '_select', return_value='resp') as mock:
resp = venvscache.get_venv(uuid='uuid')
mock.assert_called_with(['foo', 'bar'], None, '', uuid='uuid', options=None)
assert resp == 'resp'
24 changes: 12 additions & 12 deletions tests/test_infra.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2017 Facundo Batista, Nicolás Demarchi
# Copyright 2017-2022 Facundo Batista, Nicolás Demarchi
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
Expand All @@ -18,10 +18,11 @@

import io
import logging
from unittest.mock import patch

import docutils.core
import pep257
import pydocstyle
import rst2html5_

from flake8.api.legacy import get_style_guide
from pyuca import Collator

Expand All @@ -32,33 +33,32 @@
PEP257_ROOTS = ['fades']

# avoid seeing all DEBUG logs if the test fails
pep257.log.setLevel(logging.WARNING)
for logger_name in ('flake8.plugins', 'flake8.api', 'flake8.checker', 'flake8.main'):
logging.getLogger(logger_name).setLevel(logging.CRITICAL)


def test_flake8_pytest(mocker):
def test_flake8_pytest():
python_filepaths = get_python_filepaths(FLAKE8_ROOTS)
style_guide = get_style_guide(**FLAKE8_OPTIONS)
fake_stdout = io.StringIO()
mocker.patch('sys.stdout', fake_stdout)
report = style_guide.check_files(python_filepaths)
with patch('sys.stdout', fake_stdout):
report = style_guide.check_files(python_filepaths)
assert report.total_errors == 0, "There are issues!\n" + fake_stdout.getvalue()


def test_pep257_pytest():
python_filepaths = get_python_filepaths(PEP257_ROOTS)
result = list(pep257.check(python_filepaths))
result = list(pydocstyle.check(python_filepaths))
assert len(result) == 0, "There are issues!\n" + '\n'.join(map(str, result))


def test_readme_sanity(mocker):
def test_readme_sanity():
fake_stdout = io.StringIO() # just to ignore the output
fake_stderr = io.StringIO() # will have content if there are problems
with open('README.rst', 'rt', encoding='utf8') as fh:
mocker.patch('sys.stdout', fake_stdout)
mocker.patch('sys.stderr', fake_stderr)
docutils.core.publish_file(source=fh, writer=rst2html5_.HTML5Writer())
with patch('sys.stdout', fake_stdout):
with patch('sys.stderr', fake_stderr):
docutils.core.publish_file(source=fh, writer=rst2html5_.HTML5Writer())

errors = fake_stderr.getvalue()
assert not bool(errors), "There are issues!\n" + errors
Expand Down
102 changes: 52 additions & 50 deletions tests/test_pipmanager.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2020 Facundo Batista, Nicolás Demarchi
# Copyright 2015-2022 Facundo Batista, Nicolás Demarchi
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
Expand All @@ -19,6 +19,7 @@
import os
import io
import pytest
from unittest.mock import patch, call

from fades.pipmanager import PipManager
from fades import pipmanager
Expand All @@ -27,29 +28,29 @@
BIN_PATH = "somepath"


def test_get_parsing_ok_pytest(mocker):
def test_get_parsing_ok_pytest():
mocked_stdout = [
"Name: foo",
"Version: 2.0.0",
"Location: ~/.local/share/fades/86cc492/lib/python3.4/site-packages",
"Requires: ",
]
mgr = PipManager(BIN_PATH, pip_installed=True)
mocker.patch.object(helpers, "logged_exec", return_value=mocked_stdout)
version = mgr.get_version("foo")
with patch.object(helpers, "logged_exec", return_value=mocked_stdout):
version = mgr.get_version("foo")
assert version, "2.0.0"


def test_get_parsing_error(mocker, logs):
def test_get_parsing_error(logs):
mocked_stdout = [
"Name: foo",
"Release: 2.0.0",
"Location: ~/.local/share/fades/86cc492/lib/python3.4/site-packages",
"Requires: ",
]
mgr = PipManager(BIN_PATH, pip_installed=True)
mocker.patch.object(helpers, "logged_exec", return_value=mocked_stdout)
version = mgr.get_version("foo")
with patch.object(helpers, "logged_exec", return_value=mocked_stdout):
version = mgr.get_version("foo")

assert version == ""
assert (
Expand All @@ -58,134 +59,135 @@ def test_get_parsing_error(mocker, logs):
) in logs.error


def test_real_case_levenshtein(mocker):
def test_real_case_levenshtein():
mocked_stdout = [
"Metadata-Version: 1.1",
"Name: python-Levenshtein",
"Version: 0.12.0",
"License: GPL",
]
mgr = PipManager(BIN_PATH, pip_installed=True)
mocker.patch.object(helpers, "logged_exec", return_value=mocked_stdout)
version = mgr.get_version("foo")
with patch.object(helpers, "logged_exec", return_value=mocked_stdout):
version = mgr.get_version("foo")
assert version == "0.12.0"


def test_install(mocker):
def test_install():
mgr = PipManager(BIN_PATH, pip_installed=True)
pip_path = os.path.join(BIN_PATH, "pip")
mock = mocker.patch.object(helpers, "logged_exec")
mgr.install("foo")
with patch.object(helpers, "logged_exec") as mock:
mgr.install("foo")

# check it always upgrades pip, and then the proper install
python_path = os.path.join(BIN_PATH, "python")
c1 = mocker.call([python_path, "-m", "pip", "install", "pip", "--upgrade"])
c2 = mocker.call([pip_path, "install", "foo"])
c1 = call([python_path, "-m", "pip", "install", "pip", "--upgrade"])
c2 = call([pip_path, "install", "foo"])
assert mock.call_args_list == [c1, c2]


def test_install_without_pip_upgrade(mocker):
def test_install_without_pip_upgrade():
mgr = PipManager(BIN_PATH, pip_installed=True, avoid_pip_upgrade=True)
pip_path = os.path.join(BIN_PATH, "pip")
mock = mocker.patch.object(helpers, "logged_exec")
mgr.install("foo")
with patch.object(helpers, "logged_exec") as mock:
mgr.install("foo")
mock.assert_called_with([pip_path, "install", "foo"])


def test_install_multiword_dependency(mocker):
def test_install_multiword_dependency():
mgr = PipManager(BIN_PATH, pip_installed=True)
pip_path = os.path.join(BIN_PATH, "pip")
mock = mocker.patch.object(helpers, "logged_exec")
mgr.install("foo bar")
with patch.object(helpers, "logged_exec") as mock:
mgr.install("foo bar")
mock.assert_called_with([pip_path, "install", "foo", "bar"])


def test_install_with_options(mocker):
def test_install_with_options():
mgr = PipManager(BIN_PATH, pip_installed=True, options=["--bar baz"])
pip_path = os.path.join(BIN_PATH, "pip")
mock = mocker.patch.object(helpers, "logged_exec")
mgr.install("foo")
with patch.object(helpers, "logged_exec") as mock:
mgr.install("foo")
mock.assert_called_with([pip_path, "install", "foo", "--bar", "baz"])


def test_install_with_options_using_equal(mocker):
def test_install_with_options_using_equal():
mgr = PipManager(BIN_PATH, pip_installed=True, options=["--bar=baz"])
pip_path = os.path.join(BIN_PATH, "pip")
mock = mocker.patch.object(helpers, "logged_exec")
mgr.install("foo")
with patch.object(helpers, "logged_exec") as mock:
mgr.install("foo")
mock.assert_called_with([pip_path, "install", "foo", "--bar=baz"])


def test_install_raise_error(mocker, logs):
def test_install_raise_error(logs):
mgr = PipManager(BIN_PATH, pip_installed=True)
mocker.patch.object(helpers, "logged_exec", side_effect=['ok', Exception("Kapow!")])
with pytest.raises(Exception):
mgr.install("foo")
with patch.object(helpers, "logged_exec", side_effect=['ok', Exception("Kapow!")]):
with pytest.raises(Exception):
mgr.install("foo")

assert "Error installing foo: Kapow!" in logs.error


def test_install_without_pip(mocker):
def test_install_without_pip():
mgr = PipManager(BIN_PATH, pip_installed=False)
pip_path = os.path.join(BIN_PATH, "pip")
mocked_exec = mocker.patch.object(helpers, "logged_exec")
mocked_install_pip = mocker.patch.object(mgr, "_brute_force_install_pip")
mgr.install("foo")
with patch.object(helpers, "logged_exec") as mocked_exec:
with patch.object(mgr, "_brute_force_install_pip") as mocked_install_pip:
mgr.install("foo")
assert mocked_install_pip.call_count == 1
mocked_exec.assert_called_with([pip_path, "install", "foo"])


def test_brute_force_install_pip_installer_exists(mocker, tmp_path):
def test_brute_force_install_pip_installer_exists(tmp_path):
tmp_file = str(tmp_path / "hello.txt")
mgr = PipManager(BIN_PATH, pip_installed=False)
python_path = os.path.join(BIN_PATH, "python")
mocked_exec = mocker.patch.object(helpers, "logged_exec")
download_installer = mocker.patch.object(mgr, "_download_pip_installer")

# get the tempfile but leave it there to be found
open(tmp_file, 'wt', encoding='utf8').close()
mgr.pip_installer_fname = tmp_file
mgr._brute_force_install_pip()

with patch.object(helpers, "logged_exec") as mocked_exec:
with patch.object(mgr, "_download_pip_installer") as download_installer:
mgr._brute_force_install_pip()

assert not download_installer.called
mocked_exec.assert_called_with([python_path, mgr.pip_installer_fname, "-I"])
assert mgr.pip_installed


def test_brute_force_install_pip_no_installer(mocker, tmp_path):
def test_brute_force_install_pip_no_installer(tmp_path):
tmp_file = str(tmp_path / "hello.txt")
mgr = PipManager(BIN_PATH, pip_installed=False)
python_path = os.path.join(BIN_PATH, "python")
mocked_exec = mocker.patch.object(helpers, "logged_exec")
download_installer = mocker.patch.object(mgr, "_download_pip_installer")

mgr.pip_installer_fname = tmp_file
mgr._brute_force_install_pip()
with patch.object(helpers, "logged_exec") as mocked_exec:
with patch.object(mgr, "_download_pip_installer") as download_installer:
mgr._brute_force_install_pip()

download_installer.assert_called_once_with()
mocked_exec.assert_called_with([python_path, mgr.pip_installer_fname, "-I"])
assert mgr.pip_installed


def test_download_pip_installer(mocker, tmp_path):
def test_download_pip_installer(tmp_path):
tmp_file = str(tmp_path / "hello.txt")
mgr = PipManager(BIN_PATH, pip_installed=False)

mgr.pip_installer_fname = tmp_file
urlopen = mocker.patch("fades.pipmanager.request.urlopen", return_value=io.BytesIO(b"hola"))
mgr._download_pip_installer()
with patch("fades.pipmanager.request.urlopen", return_value=io.BytesIO(b"hola")) as urlopen:
mgr._download_pip_installer()
assert os.path.exists(mgr.pip_installer_fname)
urlopen.assert_called_once_with(pipmanager.PIP_INSTALLER)


def test_freeze(mocker, tmp_path):
def test_freeze(tmp_path):
tmp_file = str(tmp_path / "reqtest.txt")
mock = mocker.patch.object(helpers, "logged_exec")
mock.return_value = ['moño>11', 'foo==1.2'] # "bad" order, on purpose

# call and check pip was executed ok
mgr = PipManager(BIN_PATH)
mgr.freeze(tmp_file)
with patch.object(helpers, "logged_exec") as mock:
mock.return_value = ['moño>11', 'foo==1.2'] # "bad" order, on purpose
mgr.freeze(tmp_file)

pip_path = os.path.join(BIN_PATH, "pip")
mock.assert_called_with([pip_path, "freeze", "--all", "--local"])
Expand Down

0 comments on commit 703d4b0

Please sign in to comment.