Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unittest for pythonforandroid.util and... #1855

Merged
merged 8 commits into from
Jun 13, 2019
23 changes: 15 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ services:
- docker

before_install:
- travis_retry sudo apt update -qq
# to successfully send the coveralls reports we need pyOpenSSL
- travis_retry sudo apt install -qq --no-install-recommends
python2.7 python3 python3-venv python3-virtualenv python3-pip
python3-setuptools python3-openssl
# (venv/virtualenv are both used by tests/test_pythonpackage.py)
- sudo pip install tox>=2.0
- sudo pip3 install coveralls
# https://github.com/travis-ci/travis-ci/issues/6069#issuecomment-266546552
- git remote set-branches --add origin master
- git fetch
Expand All @@ -33,6 +25,21 @@ jobs:
include:
- stage: lint
name: "Tox tests and coverage"
language: python
python: 3.7
before_script:
# We need to escape virtualenv for `test_pythonpackage_basic.test_virtualenv`
# See also: https://github.com/travis-ci/travis-ci/issues/8589
- type -t deactivate && deactivate || true
- export PATH=/opt/python/3.7/bin:$PATH
# Install tox & virtualenv
# Note: venv/virtualenv are both used by tests/test_pythonpackage.py
- pip3.7 install -U virtualenv
- pip3.7 install tox>=2.0
# Install coveralls & dependencies
# Note: pyOpenSSL needed to send the coveralls reports
- pip3.7 install pyOpenSSL
- pip3.7 install coveralls
script:
# we want to fail fast on tox errors without having to `docker build` first
- tox -- tests/ --ignore tests/test_pythonpackage.py
Expand Down
75 changes: 0 additions & 75 deletions pythonforandroid/util.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import contextlib
from os.path import exists, join
from os import getcwd, chdir, makedirs, walk, uname
import io
import json
import sh
import shutil
import sys
Expand Down Expand Up @@ -62,79 +60,6 @@ def ensure_dir(filename):
makedirs(filename)


class JsonStore(object):
AndreMiras marked this conversation as resolved.
Show resolved Hide resolved
"""Replacement of shelve using json, needed for support python 2 and 3.
"""

def __init__(self, filename):
super(JsonStore, self).__init__()
self.filename = filename
self.data = {}
if exists(filename):
try:
with io.open(filename, encoding='utf-8') as fd:
self.data = json.load(fd)
except ValueError:
print("Unable to read the state.db, content will be replaced.")

def __getitem__(self, key):
return self.data[key]

def __setitem__(self, key, value):
self.data[key] = value
self.sync()

def __delitem__(self, key):
del self.data[key]
self.sync()

def __contains__(self, item):
return item in self.data

def get(self, item, default=None):
return self.data.get(item, default)

def keys(self):
return self.data.keys()

def remove_all(self, prefix):
for key in self.data.keys()[:]:
if not key.startswith(prefix):
continue
del self.data[key]
self.sync()

def sync(self):
# http://stackoverflow.com/questions/12309269/write-json-data-to-file-in-python/14870531#14870531
if IS_PY3:
with open(self.filename, 'w') as fd:
json.dump(self.data, fd, ensure_ascii=False)
else:
with io.open(self.filename, 'w', encoding='utf-8') as fd:
fd.write(unicode(json.dumps(self.data, ensure_ascii=False))) # noqa F821


def which(program, path_env):
'''Locate an executable in the system.'''
import os

def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in path_env.split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file

return None


def get_virtualenv_executable():
virtualenv = None
if virtualenv is None:
Expand Down
96 changes: 87 additions & 9 deletions tests/test_archs.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@


class ArchSetUpBaseClass(object):
"""
An class object which is intended to be used as a base class to configure
an inherited class of `unittest.TestCase`. This class will override the
`setUp` method.
"""

ctx = None

def setUp(self):
Expand All @@ -63,6 +69,12 @@ def setUp(self):


class TestArch(ArchSetUpBaseClass, unittest.TestCase):
"""
An inherited class of `ArchSetUpBaseClass` and `unittest.TestCase` which
will be used to perform tests for the base class
:class:`~pythonforandroid.archs.Arch`.
"""

def test_arch(self):
arch = Arch(self.ctx)
with self.assertRaises(AttributeError) as e1:
Expand All @@ -81,14 +93,28 @@ def test_arch(self):


class TestArchARM(ArchSetUpBaseClass, unittest.TestCase):
# Here we mock two functions:
# - `ensure_dir` because we don't want to create any directory
# - `find_executable` because otherwise we will
# get an error when trying to find the compiler (we are setting some fake
# paths for our android sdk and ndk so probably will not exist)
"""
An inherited class of `ArchSetUpBaseClass` and `unittest.TestCase` which
will be used to perform tests for :class:`~pythonforandroid.archs.ArchARM`.
"""

@mock.patch("pythonforandroid.archs.find_executable")
@mock.patch("pythonforandroid.build.ensure_dir")
def test_arch_arm(self, mock_ensure_dir, mock_find_executable):
"""
Test that class :class:`~pythonforandroid.archs.ArchARM` returns some
expected attributes and environment variables.

.. note::
Here we mock two methods:

- `ensure_dir` because we don't want to create any directory
- `find_executable` because otherwise we will
get an error when trying to find the compiler (we are setting
some fake paths for our android sdk and ndk so probably will
not exist)

"""
mock_find_executable.return_value = "arm-linux-androideabi-gcc"
mock_ensure_dir.return_value = True

Expand Down Expand Up @@ -147,16 +173,30 @@ def test_arch_arm(self, mock_ensure_dir, mock_find_executable):


class TestArchARMv7a(ArchSetUpBaseClass, unittest.TestCase):
# Here we mock the same functions than the previous tests plus `glob`,
# so we make sure that the glob result is the expected even if the folder
# doesn't exist, which is probably the case. This has to be done because
# here we tests the `get_env` with clang
"""
An inherited class of `ArchSetUpBaseClass` and `unittest.TestCase` which
will be used to perform tests for
:class:`~pythonforandroid.archs.ArchARMv7_a`.
"""

@mock.patch("pythonforandroid.archs.glob")
@mock.patch("pythonforandroid.archs.find_executable")
@mock.patch("pythonforandroid.build.ensure_dir")
def test_arch_armv7a(
self, mock_ensure_dir, mock_find_executable, mock_glob
):
"""
Test that class :class:`~pythonforandroid.archs.ArchARMv7_a` returns
some expected attributes and environment variables.

.. note::
Here we mock the same functions than
:meth:`TestArchARM.test_arch_arm` plus `glob`, so we make sure that
the glob result is the expected even if the folder doesn't exist,
which is probably the case. This has to be done because here we
tests the `get_env` with clang

"""
mock_find_executable.return_value = "arm-linux-androideabi-gcc"
mock_ensure_dir.return_value = True
mock_glob.return_value = ["llvm"]
Expand Down Expand Up @@ -197,9 +237,21 @@ def test_arch_armv7a(


class TestArchX86(ArchSetUpBaseClass, unittest.TestCase):
"""
An inherited class of `ArchSetUpBaseClass` and `unittest.TestCase` which
will be used to perform tests for :class:`~pythonforandroid.archs.Archx86`.
"""

@mock.patch("pythonforandroid.archs.find_executable")
@mock.patch("pythonforandroid.build.ensure_dir")
def test_arch_x86(self, mock_ensure_dir, mock_find_executable):
"""
Test that class :class:`~pythonforandroid.archs.Archx86` returns
some expected attributes and environment variables.

.. note:: Here we mock the same functions than
:meth:`TestArchARM.test_arch_arm`
"""
mock_find_executable.return_value = "arm-linux-androideabi-gcc"
mock_ensure_dir.return_value = True

Expand All @@ -220,9 +272,22 @@ def test_arch_x86(self, mock_ensure_dir, mock_find_executable):


class TestArchX86_64(ArchSetUpBaseClass, unittest.TestCase):
"""
An inherited class of `ArchSetUpBaseClass` and `unittest.TestCase` which
will be used to perform tests for
:class:`~pythonforandroid.archs.Archx86_64`.
"""

@mock.patch("pythonforandroid.archs.find_executable")
@mock.patch("pythonforandroid.build.ensure_dir")
def test_arch_x86_64(self, mock_ensure_dir, mock_find_executable):
"""
Test that class :class:`~pythonforandroid.archs.Archx86_64` returns
some expected attributes and environment variables.

.. note:: Here we mock the same functions than
:meth:`TestArchARM.test_arch_arm`
"""
mock_find_executable.return_value = "arm-linux-androideabi-gcc"
mock_ensure_dir.return_value = True

Expand All @@ -242,9 +307,22 @@ def test_arch_x86_64(self, mock_ensure_dir, mock_find_executable):


class TestArchAArch64(ArchSetUpBaseClass, unittest.TestCase):
"""
An inherited class of `ArchSetUpBaseClass` and `unittest.TestCase` which
will be used to perform tests for
:class:`~pythonforandroid.archs.ArchAarch_64`.
"""

@mock.patch("pythonforandroid.archs.find_executable")
@mock.patch("pythonforandroid.build.ensure_dir")
def test_arch_aarch_64(self, mock_ensure_dir, mock_find_executable):
"""
Test that class :class:`~pythonforandroid.archs.ArchAarch_64` returns
some expected attributes and environment variables.

.. note:: Here we mock the same functions than
:meth:`TestArchARM.test_arch_arm`
"""
mock_find_executable.return_value = "arm-linux-androideabi-gcc"
mock_ensure_dir.return_value = True

Expand Down
Loading