summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorholger krekel <holger@merlinux.eu>2012-12-22 21:52:46 +0100
committerholger krekel <holger@merlinux.eu>2012-12-22 21:52:46 +0100
commit4839a820a8b45fc88cc774d678cab45d6b7362aa (patch)
tree7499def9f7fc9b8f9a72482a9937f4d626d8561b
parentd930475b05d04dfcbc6796cfe9637a6790073e59 (diff)
downloadtox-4839a820a8b45fc88cc774d678cab45d6b7362aa.tar.gz
a "newconfig.txt" draft for introducing variants
and various other features to tox.
-rw-r--r--doc/newconfig.txt308
1 files changed, 308 insertions, 0 deletions
diff --git a/doc/newconfig.txt b/doc/newconfig.txt
new file mode 100644
index 0000000..84f1355
--- /dev/null
+++ b/doc/newconfig.txt
@@ -0,0 +1,308 @@
+V2: new tox multi-dimensional, platform-specific configuration
+--------------------------------------------------------------------
+
+**Abstract**: Adding multi-dimensional configuration, platform-specification
+and multiple installers to tox.ini.
+
+**Target audience**: Developers using or wanting to use tox for testing
+their python projects.
+
+Issues with current tox (1.4) configuration
+------------------------------------------------
+
+Tox is used as a tool for creating and managing virtualenv environments
+and running tests in them. As of tox-1.4 there are some issues frequenetly
+coming up with its configuration language:
+
+- there is no way to instruct tox to parametrize testenv specifications
+ other than to list all combinations by specifying a ``[testenv:...]``
+ section for each combination. Examples of real life situations
+ arising from this:
+
+ * http://code.larlet.fr/django-rest-framework/src/eed0f39a7e45/tox.ini
+
+ * https://bitbucket.org/tabo/django-treebeard/src/93b579395a9c/tox.ini
+
+- there is no way to have platform specific settings other than to
+ define specific testenvs and invoke tox with a platform-specific
+ testenv list.
+
+- there is no way to specify the platforms against which a project
+ shall successfully run.
+
+- tox always uses pip for installing packages currently. This has
+ several issues:
+
+ - no way to check if installing via easy_install works
+ - no installs of packages with compiled c-extensions (win32 standard)
+
+This document discusses a possible solution for each of these issues.
+It does so by going through examples and by transforming the above
+two
+
+- allow to more easily define and run dependency/interpreter variants
+ with testenvs, maintaining per-testenv customizability
+- allow to define settings in a platform-specific way
+- allow to define the platforms against which tests should run
+- allow to run variants of installing via easy_install or pip.
+
+
+Example: Generating and selecting variants
+----------------------------------------------
+
+Suppose you want to test your package against mypkg-1.3 and mypkg-1.4
+versions, against python2.6, 2.7 interpreters and on ``linux`` and
+``win32`` platforms. Today you would have to
+write down 2*2*2 = 8 ``[testenv*]`` sections and then instruct
+tox to on the respective platform with a respective environment name list.
+
+With tox-1.5 there is no need to write down such boilerplate stuff.
+Without further ado, here is how a suitable ``tox.ini`` would look like::
+
+Without much further introduction, here is an example ``tox.ini``::
+
+ # combination syntax gives 2 * 2 * 2 = 8 testenv names
+ #
+ envlist = [py26,py27]-[mypkg13,mypkg14]-[win,linux]
+
+ [testenv]
+ deps = pytest
+ # variant specific dependencies
+ mypkg13: mypkg<1.4
+ mypkg14: mypkg>=1.4,<1.5
+ platform=
+ win: windows
+ linux: linux
+ basepython=
+ py26: python2.6
+ py27: python2.7
+
+ commands = py.test
+
+Let's go through this step by step::
+
+ envlist = [py26,py27]-[mypkg13,mypkg14]-[windows,linux]
+
+This creates a list of ``2*2*2=8`` environment names. It is
+a short form for writing the environments down explicitely
+like this::
+
+ envlist = py26-mypkg13-windows, py26-mypkg13-linux,
+ py26-mypkg14-windows, py26-mypkg14-linux,
+ py27-mypkg13-windows, py27-mypkg13-linux,
+ py27-mypkg14-windows, py27-mypkg14-linux,
+
+Let's look at the next config item, the declaration of the generic
+testenv. All the eight testenvironments will derive from this one.
+Unlike with earlier tox versions, there is no need to write down
+eight different ``[testenv:...]`` sections::
+
+ [testenv]
+ deps = pytest
+ # variant specific dependencies
+ mypkg13: mypkg<1.4
+ mypkg14: mypkg>=1.4,<1.5
+
+This defines an unconditional dependency ``pytest`` which is going to be
+installed in all environments. It also define two conditional deps:
+
+- if ``mypkg13`` is part of the environment name, the ``mypkg<1.4`` spec
+ will be used, otherwise the line is empty.
+- if ``mypkg14`` is part of the environment name, the ``mypkg>=1.4,<1.5`` spec
+ will be used, otherwise the line is empty.
+
+The next configuration item defines the platform, depending on the
+environment name for which the ``[testenv]`` is used::
+
+ platform=
+ win: windows
+ linux: linux
+
+These two conditional settings will lead to either ``windows`` or
+``linux`` as the platform string. When the test environment is run,
+its platform string needs to be contained match the string returned
+from ``platform.platform()``. Otherwise the environment will be skipped.
+
+The next configuration item in the ``testenv`` section deals with
+the python interpreter::
+
+ basepython =
+ py26: python2.6
+ py27: python2.7
+
+This defines the two executables, depending on if ``py26`` or ``py27``
+appears in the environment name.
+
+The last config item is simply the invocation of the test runner::
+
+ commands = py.test
+
+Nothing special here :)
+
+However, as tox provides good defaults for platform and basepython
+settings, we can cut them out from our tox.ini::
+
+ envlist = [py26,py27]-[mypkg13,mypkg14]-[win,linux]
+
+ [testenv]
+ deps = pytest
+ # variant specific dependencies
+ mypkg13: mypkg<1.4
+ mypkg14: mypkg>=1.4,<1.5
+
+Voila, this ``tox.ini`` file defines 8 environments.
+
+
+The new "platform" setting
+--------------------------------------
+
+A testenv can define a new ``platform`` setting. If its value
+is not contained in the string obtained from calling ``platform.platform()``
+the environment will be skipped.
+
+Generator expressions in the envlist setting
+----------------------------------------------------------
+
+The new ``envlist`` setting allows to use ``[CSV]`` expressions
+where ``CSV`` is a list of comma-separated values. The basic
+generating algorithm works like this:
+
+- expand: for each CSV-expression in an environment name in the list
+ produce an additional environment name for each value in the CSV
+- repeat: as long as there are CSV-expressions, continue the process
+
+
+Variant specification with [variant:VARNAME]
+----------------------------------------------
+
+Apart from using conditional settings, you can also write down
+a ``[variant::VARIANTNAME]`` section, allowing to define settings
+for the respective variant. Variant settings will be merged from
+left to right so an environment name ``abc-def`` will lookup
+and merge settings from ``abc``, then from ``def``.
+
+..
+ Note that a direct ``[variant:xyz-abc]`` testenv definition
+ can override any automatically produced settings.
+
+Showing all expanded sections
+-------------------------------
+
+To help with understanding how the variants will produce section values,
+you can ask tox to show their expansion with a new option::
+
+ $ tox -l [XXX output ommitted for now]
+
+Making sure your packages installs with easy_install
+------------------------------------------------------
+
+The new "installer" testenv setting allows to specify the tool for
+installation::
+
+ [testenv]
+ installer =
+ easy_install ; "easy" in envname
+ pip ; "pip" in envname or "easy" not in envname
+
+If you want to have your package installed with both easy_install
+and pip, you can list them in your envlist likes this::
+
+ [tox]
+ envlist = py[26,27,32]-django[13,14]-[easy,pip]
+
+If no installer is specified, ``pip`` will be used.
+
+Default settings for specific names in environments
+---------------------------------------------------------------
+
+tox comes with predefined settings for certain variants, namely:
+
+* ``[easy,pip]`` use easy_install or pip respectively
+* ``[py24,py25,py26,py27,py31,py32,py33,pypy19]`` use the respective
+ pythonNN or PyPy interpreter
+* ``[win32,linux,darwin]`` defines the according ``platform``.
+
+You can use those in your “envlist” specification
+without the need to define them yourself.
+
+Transforming the examples: django-rest
+------------------------------------------------
+
+The original `tox.ini <http://code.larlet.fr/django-rest-framework/src/eed0f39a7e45/tox.ini>`_
+file has 159 lines and a lot of repetition, the new one would +have 20
+lines and almost no repetition::
+
+ [tox]
+ envlist = [py25,py26,py27]-[django12,django13]-[,example]
+
+ [testenv]
+ commands = python setup.py test
+ deps=
+ coverage==3.4
+ unittest-xml-reporting==1.2
+ Pyyaml==3.10
+ django12: django==1.2.4
+ django13: django==1.3.1
+
+ [variant:example]
+ commands = python examples/runtests.py
+ +deps =
+ wsgiref==0.1.2
+ Pygments==1.4
+ httplib2==0.6.0
+ Markdown==2.0.3
+
+Note that ``[,example]`` in the envlist denotes an empty env and the
+ "example" variant. The empty variant means that there are no specific
+settings and thus no need to define a variant name.
+
+Note also that ``+deps`` means that we are appending to dependencies,
+not substituting them.
+
+Transforming the examples: django-treebeard
+------------------------------------------------
+
+Another `tox.ini
+<https://bitbucket.org/tabo/django-treebeard/raw/93b579395a9c/tox.ini>`_
+has 233 lines and runs tests against multiple Postgres and Mysql
+engines. It also performs backend-specific test commands, passing
+different command line options to the test script. With the new tox-1.X
+we not only can do the same with 32 non-repetive configuration lines but
+we also produce 36 specific testenvs with specific dependencies and test
+commands::
+
+ [tox]
+ envlist =
+ [py24,py25,py26,py27]-[django11,django12,django13]-[nodb,pg,mysql]
+ docs
+
+ [testenv:docs]
+ changedir = docs
+ deps =
+ Sphinx
+ Django
+ commands =
+ make clean
+ make html
+
+ [testenv]
+ deps=
+ coverage
+ pysqlite
+ django11: django==1.1.4
+ django12: django==1.2.7
+ django13: django==1.3.1
+ django14: django==1.4
+ nodb: pysqlite
+ pg: psycopg2
+ mysql: MySQL-python
+
+ commands =
+ nodb: {envpython} runtests.py {posargs}
+ pg: {envpython} runtests.py {posargs} \
+ --DATABASE_ENGINE=postgresql_psycopg2 \
+ --DATABASE_USER=postgres {posargs}
+ mysql: {envpython} runtests.py --DATABASE_ENGINE=mysql \
+ --DATABASE_USER=root {posargs}
+
+It's noteworthy here that you can also use conditionals in the commands.