Skip to content

Commit 16155c0

Browse files
authored
Unify most of the test apps into on device unit test app (#2046)
* 📦 Refactor (move) `PythonTestMixIn` into `tests.mixin` * 📦 Unify most of the test apps into one app So depending on the supplied recipes, a different test app will be ran. The supported test apps are: - kivy - flask - no-gui * 🏗️ Make test app `on_device_unit_tests` the default... for our CI providers and `rebuild_updated_recipes.py` because we recently removed the old test app that we made use of. * 📝 Update docs * ✅ Create a `x86_64` testapp for gh-actions * 📝 Fix typo errors and... Remove sentence regarding python2 compatibility... because python2 it's almost at the end of his life * ✅ Make a `flask` testapp... So we can get an apk via gh-actions Notes: - this way the reviewers can install the flask apk without making the build - these changes will be reverted in the next commit...since we want a kivy app as our default) * ✅ Revert "Make a `flask` testapp..." This reverts commit 0ed4d70. * 🔥 Remove `orientation` kwarg... in case that we detect that p4a will build an `service_only` app. Note: if we don't do this we wil get errors once we try to create our apk with the target distribution * ✅ Create a `x86` testapp for gh-actions and change gh-actions job title (because it looks better) * 🏗️ Rename test app Because it looks better and is more readable. * 📝 Fix a syntactical error at docstring * 🚚 Rename `setup_test_app.py` to `setup.py` Because reducing filename to `setup.py` will make our cli arguments shorter and source code cleaner * 🔧 Disable gh-actions `fail-fast` So our matrix gh-actions builds will not be cancelled if some arch fails which is very useful to fix specific arch issues. See also: #2073 * 💚 Add `testapps-with-numpy/%` & ... make `testapps/%` support multiple archs Notes: this completes the job started at 9ea53fc & afd4413
1 parent f2b621e commit 16155c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1785
-1799
lines changed

.github/workflows/push.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Unit tests & Build Testapp
1+
name: Unit tests & build apps
22

33
on: ['push', 'pull_request']
44

@@ -42,25 +42,26 @@ jobs:
4242
make test
4343
4444
build:
45-
name: Build testapp
45+
name: Unit test apk
4646
needs: [flake8]
4747
runs-on: ubuntu-latest
4848
strategy:
49+
fail-fast: false
4950
matrix:
50-
build-arch: ['arm64-v8a', 'armeabi-v7a']
51+
build-arch: ['arm64-v8a', 'armeabi-v7a', 'x86_64', 'x86']
5152
steps:
5253
- name: Checkout python-for-android
5354
uses: actions/checkout@v2
5455
- name: Pull docker image
5556
run: |
5657
make docker/pull
57-
- name: Build apk for Python 3 ${{ matrix.build-arch }}
58+
- name: Build apk Python 3 ${{ matrix.build-arch }}
5859
run: |
5960
mkdir -p apks
60-
make docker/run/make/with-artifact/testapps/${{ matrix.build-arch }}
61+
make docker/run/make/with-artifact/testapps-with-numpy/${{ matrix.build-arch }}
6162
- uses: actions/upload-artifact@v1
6263
with:
63-
name: bdisttest_python3_sqlite_openssl_googlendk__${{ matrix.build-arch }}-debug-1.1.apk
64+
name: bdist_test_app_unittests__${{ matrix.build-arch }}-debug-1.1.apk
6465
path: apks
6566

6667
rebuild_updated_recipes:

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
name: Python 3 arm64-v8a (with numpy)
4646
stage: build testapps
4747
before_script: make docker/pull
48-
script: make docker/run/make/testapps/arm64-v8a
48+
script: make docker/run/make/testapps-with-numpy/arm64-v8a
4949
- <<: *testapps
5050
name: Python 3 armeabi-v7a
5151
os: osx

Makefile

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,18 @@ rebuild_updated_recipes: virtualenv
3535
ANDROID_SDK_HOME=$(ANDROID_SDK_HOME) ANDROID_NDK_HOME=$(ANDROID_NDK_HOME) \
3636
$(PYTHON) ci/rebuild_updated_recipes.py
3737

38-
testapps/arm64-v8a: virtualenv
39-
. $(ACTIVATE) && cd testapps/ && \
40-
python setup_testapp_python3_sqlite_openssl.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
38+
testapps-with-numpy/%: virtualenv
39+
$(eval $@_APP_ARCH := $(shell basename $*))
40+
. $(ACTIVATE) && cd testapps/on_device_unit_tests/ && \
41+
python setup.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
4142
--requirements libffi,sdl2,pyjnius,kivy,python3,openssl,requests,sqlite3,setuptools,numpy \
42-
--arch=arm64-v8a
43+
--arch=$($@_APP_ARCH)
4344

44-
testapps/armeabi-v7a: virtualenv
45-
. $(ACTIVATE) && cd testapps/ && \
46-
python setup_testapp_python3_sqlite_openssl.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
47-
--arch=armeabi-v7a
45+
testapps/%: virtualenv
46+
$(eval $@_APP_ARCH := $(shell basename $*))
47+
. $(ACTIVATE) && cd testapps/on_device_unit_tests/ && \
48+
python setup.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
49+
--arch=$($@_APP_ARCH)
4850

4951
clean:
5052
find . -type d -name "__pycache__" -exec rm -r {} +
@@ -72,10 +74,9 @@ docker/run/make/%: docker/build
7274
docker run --rm --env-file=.env $(DOCKER_IMAGE) make $*
7375

7476
docker/run/make/with-artifact/%: docker/build
75-
$(eval $@_APP_NAME := bdisttest_python3_sqlite_openssl_googlendk)
7677
$(eval $@_APP_ARCH := $(shell basename $*))
7778
docker run --name p4a-latest --env-file=.env $(DOCKER_IMAGE) make $*
78-
docker cp p4a-latest:/home/user/app/testapps/$($@_APP_NAME)__$($@_APP_ARCH)-debug-1.1-.apk ./apks
79+
docker cp p4a-latest:/home/user/app/testapps/on_device_unit_tests/bdist_unit_tests_app__$($@_APP_ARCH)-debug-1.1-.apk ./apks
7980
docker rm -fv p4a-latest
8081

8182
docker/run/shell: docker/build

ci/rebuild_updated_recipes.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,15 @@ def build(target_python, requirements):
5252
"""
5353
if not requirements:
5454
return
55-
testapp = 'setup_testapp_python3_sqlite_openssl.py'
5655
android_sdk_home = os.environ['ANDROID_SDK_HOME']
5756
android_ndk_home = os.environ['ANDROID_NDK_HOME']
5857
requirements.add(target_python.name)
5958
requirements = ','.join(requirements)
6059
logger.info('requirements: {}'.format(requirements))
61-
with current_directory('testapps/'):
60+
with current_directory('testapps/on_device_unit_tests/'):
6261
# iterates to stream the output
6362
for line in sh.python(
64-
testapp, 'apk', '--sdk-dir', android_sdk_home,
63+
'setup.py', 'apk', '--sdk-dir', android_sdk_home,
6564
'--ndk-dir', android_ndk_home, '--requirements',
6665
requirements, _err_to_out=True, _iter=True):
6766
print(line)

doc/source/testing_pull_requests.rst

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,30 +103,31 @@ Using python-for-android commands directly from the pull request files
103103
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104104

105105
- Enter inside the directory of the cloned repository in the above
106-
step and run p4a command with proper args, eg::
106+
step and run p4a command with proper args, eg (to test an modified
107+
`pycryptodome` recipe)::
107108

108109
.. codeblock:: bash
109110

110111
cd p4a-feature-fix-numpy
111112
PYTHONPATH=. python3 -m pythonforandroid.toolchain apk \
112-
--private=testapps/testapp_sqlite_openssl \
113-
--dist-name=dist_test_app_python3_libs \
113+
--private=testapps/on_device_unit_tests/test_app \
114+
--dist-name=dist_unit_tests_app_pycryptodome \
114115
--package=org.kivy \
115-
--name=test_app_python3_sqlite_openssl \
116+
--name=unit_tests_app_pycryptodome \
116117
--version=0.1 \
117-
--requirements=requests,peewee,sdl2,pyjnius,kivy,python3 \
118+
--requirements=sdl2,pyjnius,kivy,python3,pycryptodome \
118119
--ndk-dir=/media/DEVEL/Android/android-ndk-r20 \
119120
--sdk-dir=/media/DEVEL/Android/android-sdk-linux \
120121
--android-api=27 \
121122
--arch=arm64-v8a \
122-
--permission=INTERNET \
123+
--permission=VIBRATE \
123124
--debug
124125

125126
Things that you should know:
126127

127128

128-
- The example above will build an testapp we will make use of the files of
129-
the testapp named `testapp_sqlite_openssl.py` but we don't use the setup
129+
- The example above will build an test app we will make use of the files of
130+
the `on device unit tests` test app but we don't use the setup
130131
file to build it so we must tell python-for-android what we want via
131132
arguments
132133
- be sure to at least edit the following arguments when running the above
@@ -159,19 +160,19 @@ Installing python-for-android using the github's branch of the pull request
159160
cd p4a-feature-fix-numpy
160161
pip3 install . --upgrade --user
161162

162-
- Now, go inside the `testapps` directory (we assume that you still are inside
163-
the cloned repository)::
163+
- Now, go inside the `testapps/on_device_unit_tests` directory (we assume that
164+
you still are inside the cloned repository)::
164165

165166
.. codeblock:: bash
166167

167-
cd testapps
168+
cd testapps/on_device_unit_tests
168169

169170
- Run the build of the apk via the freshly installed copy of python-for-android
170171
by running a similar command than below::
171172

172173
.. code-block:: bash
173174

174-
python3 setup_testapp_python3_sqlite_openssl.py apk \
175+
python3 setup.py apk \
175176
--ndk-dir=/media/DEVEL/Android/android-ndk-r20 \
176177
--sdk-dir=/media/DEVEL/Android/android-sdk-linux \
177178
--android-api=27 \
@@ -182,8 +183,7 @@ Installing python-for-android using the github's branch of the pull request
182183
Things that you should know:
183184

184185
- In the example above, we override some variables that are set in
185-
`setup_testapp_python3_sqlite_openssl.py`, you could also override them
186-
by editing this file
186+
`setup.py`, you could also override them by editing this file
187187
- be sure to at least edit the following arguments when running the above
188188
command, since the default set in there it's unlikely that match your
189189
installation:

testapps/on_device_unit_tests/README.rst

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,38 @@ On device unit tests
44
This test app runs a set of unit tests, to help confirm that the
55
python-for-android build is actually working properly.
66

7+
Also it's dynamic, because it will run one app or another depending on the
8+
supplied recipes at build time.
9+
10+
It currently supports three app `modes`:
11+
- `kivy app` (with sdl2 bootstrap): if kivy in recipes
12+
- `flask app` (with webview bootstrap): if flask in recipes
13+
- `no gui`: if neither of above cases is taken
14+
715
The main tests are for the recipes built in the apk. Each module (or
816
other tool) is at least imported and subject to some basic check.
917

10-
This app is experimental, it doesn't yet support things like testing
11-
only the requirements you ask for (so if you build with requirements
12-
other than those specified, the tests may fail). It also has no gui
13-
yet, the results must be checked via logcat.
18+
This test app can be build via `setup.py` or via buildozer. In both
19+
cases it will build a basic kivy app with a set of tests defined via the
20+
`requirements` keyword (specified at build time).
21+
22+
In case that you build the `test app with no-gui`, the unittests results must
23+
be checked via command `adb logcat` or some logging apk (you may need root
24+
permissions in your device to use such app).
25+
26+
Building the app with python-for-android
27+
========================================
28+
29+
You can use the provided file `setup.py`. Check our `Makefile
30+
<https://github.com/kivy/python-for-android/blob/develop/Makefile>`__ to guess
31+
how to build the test app, or also you can look at `testing pull requests documentation
32+
<https://github.com/kivy/python-for-android/blob/develop/doc/source/testing_pull_requests.rst>`__,
33+
which describes some of the methods that you can use to build the test app.
1434

15-
Building the app
16-
================
35+
Building the app with buildozer
36+
===============================
1737

18-
This app should be built using buildozer, which it also serves as a
38+
This app can be built using buildozer, which it also serves as a
1939
test for::
2040

2141
$ buildozer android debug

testapps/on_device_unit_tests/buildozer.spec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ package.domain = org.kivy
1313
source.dir = test_app
1414

1515
# (list) Source files to include (let empty to include all the files)
16-
source.include_exts = py,png,jpg,kv,atlas
16+
source.include_exts = py,png,jpg,kv,atlas,html,css,otf,txt
1717

1818
# (list) List of inclusions using pattern matching
1919
#source.include_patterns = assets/*,images/*.png
@@ -36,7 +36,7 @@ version = 0.1
3636

3737
# (list) Application requirements
3838
# comma separated e.g. requirements = sqlite3,kivy
39-
requirements = python3,kivy,openssl,numpy,sqlite3
39+
requirements = python3,kivy,libffi,openssl,numpy,sqlite3
4040

4141
# (str) Custom source folders for requirements
4242
# Sets custom source for any requirements with recipes
@@ -52,7 +52,7 @@ requirements = python3,kivy,openssl,numpy,sqlite3
5252
#icon.filename = %(source.dir)s/data/icon.png
5353

5454
# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
55-
orientation = portrait
55+
orientation = all
5656

5757
# (list) List of service to declare
5858
#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""
2+
This is the `setup.py` file for the `on device unit test app`.
3+
4+
In this module we can control how will be built our test app. Depending on
5+
our requirements we can build an kivy, flask or a non-gui app. We default to an
6+
kivy app, since the python-for-android project its a sister project of kivy.
7+
8+
The parameter `requirements` is crucial to determine the unit tests we will
9+
perform with our app, so we must explicitly name the recipe we want to test
10+
and, of course, we should have the proper test for the given recipe at
11+
`tests.test_requirements.py` or nothing will be tested. We control our default
12+
app requirements via the dictionary `options`. Here you have some examples
13+
to build the supported app modes::
14+
15+
- kivy *basic*: `sqlite3,libffi,openssl,pyjnius,kivy,python3,requests`
16+
- kivy *images/graphs*: `kivy,python3,numpy,matplotlib,Pillow`
17+
- kivy *encryption*: `kivy,python3,cryptography,pycryptodome,scrypt,
18+
m2crypto,pysha3`
19+
- flask (with webview bootstrap): `sqlite3,libffi,openssl,pyjnius,flask,
20+
python3,genericndkbuild`
21+
22+
23+
.. note:: just noting that, for the `kivy basic` app, we add the requirements:
24+
`sqlite3,libffi,openssl` so this way we will trigger the unit tests
25+
that we have for such recipes.
26+
27+
.. tip:: to force `python-for-android` generate an `flask` app without using
28+
the kwarg `bootstrap`, we add the recipe `genericndkbuild`, which will
29+
trigger the `webview bootstrap` at build time.
30+
"""
31+
32+
import os
33+
import sys
34+
from distutils.core import setup
35+
from setuptools import find_packages
36+
37+
# define a basic test app, which can be override passing the proper args to cli
38+
options = {
39+
'apk':
40+
{
41+
'requirements':
42+
'sqlite3,libffi,openssl,pyjnius,kivy,python3,requests',
43+
'android-api': 27,
44+
'ndk-api': 21,
45+
'dist-name': 'bdist_unit_tests_app',
46+
'arch': 'armeabi-v7a',
47+
'permissions': ['INTERNET', 'VIBRATE'],
48+
'orientation': 'sensor',
49+
'service': 'P4a_test_service:app_service.py',
50+
}
51+
}
52+
53+
# check if we overwrote the default test_app requirements via `cli`
54+
requirements = options['apk']['requirements'].rsplit(',')
55+
for n, arg in enumerate(sys.argv):
56+
if arg == '--requirements':
57+
print('found requirements')
58+
requirements = sys.argv[n + 1].rsplit(',')
59+
break
60+
61+
# remove `orientation` in case that we don't detect a kivy or flask app,
62+
# since the `service_only` bootstrap does not support such argument
63+
if not ({'kivy', 'flask'} & set(requirements)):
64+
options['apk'].pop('orientation')
65+
66+
# write a file to let the test_app know which requirements we want to test
67+
# Note: later, when running the app, we will guess if we have the right test.
68+
app_requirements_txt = os.path.join(
69+
os.path.split(__file__)[0],
70+
'test_app',
71+
'app_requirements.txt',
72+
)
73+
with open(app_requirements_txt, 'w') as requirements_file:
74+
for req in requirements:
75+
requirements_file.write(f'{req.split("==")[0]}\n')
76+
77+
# run the install
78+
setup(
79+
name='unit_tests_app',
80+
version='1.1',
81+
description='p4a on device unit test app',
82+
author='Alexander Taylor, Pol Canelles',
83+
84+
packages=find_packages(),
85+
options=options,
86+
package_data={
87+
'test_app': ['*.py', '*.kv', '*.txt'],
88+
'test_app/static': ['*.png', '*.css', '*.otf'],
89+
'test_app/templates': ['*.html'],
90+
'test_app/tests': ['*.py'],
91+
}
92+
)

0 commit comments

Comments
 (0)