[py-dev] merge of conftest branch / 0.9 todos
holger krekel
holger at merlinux.de
Thu Jan 18 08:07:21 CET 2007
Hi folks,
i just merged my conftest cleanup works, see the
below commit and log message.
Regarding configuration and option handling
there still is more work to do, particularly
for configuring remote sessions (both the terminal
based one and the rssession ones).
In this vein, currently --looponfailing is not working
properly thanks to my conftest merge but that was
expected and will receive fixing.
For the 0.9 release i'd like to have the configuration/option
handling as seen from user-level (so including command line
options and conftest.py options and possibilities) be transparent,
systematic and documented because changing it later is
cumbersome.
This issue and also the API documentation generation
which is "in-progress" make it likely that the
release will drag on a bit still.
I'd be glad if some of you can check from time to time
if things break badly for you and report here
as soon as possible. If you look into py/doc/todo.txt
you'll notice that there are some changes pending
that might affect your usages of the py lib.
best & thanks,
holger
----- Forwarded message from hpk at codespeak.net -----
From: hpk at codespeak.net
To: py-svn at codespeak.net
Date: Thu, 18 Jan 2007 08:00:50 +0100 (CET)
Subject: [py-svn] r36902 - in py/dist/py: . apigen apigen/testing doc
doc/example/pytest test test/rsession test/rsession/testing
test/terminal test/testing test/testing/data test/tkinter
test/tkinter/testing
X-Spambayes-Classification: ham; 0.00
Author: hpk
Date: Thu Jan 18 08:00:43 2007
New Revision: 36902
Added:
py/dist/py/test/conftesthandle.py
- copied unchanged from r36901, py/branch/conftest/py/test/conftesthandle.py
py/dist/py/test/testing/setupdata.py
- copied unchanged from r36901, py/branch/conftest/py/test/testing/setupdata.py
py/dist/py/test/testing/test_conftesthandle.py
- copied unchanged from r36901, py/branch/conftest/py/test/testing/test_conftesthandle.py
py/dist/py/test/todo-cleanup.txt
- copied unchanged from r36901, py/branch/conftest/py/test/todo-cleanup.txt
Removed:
py/dist/py/test/testing/data/
Modified:
py/dist/py/__init__.py
py/dist/py/apigen/conftest.py
py/dist/py/apigen/testing/test_apigen_functional.py
py/dist/py/conftest.py
py/dist/py/doc/conftest.py
py/dist/py/doc/example/pytest/test_failures.py
py/dist/py/doc/test.txt
py/dist/py/doc/test_conftest.py
py/dist/py/test/cmdline.py
py/dist/py/test/collect.py
py/dist/py/test/config.py
py/dist/py/test/defaultconftest.py
py/dist/py/test/item.py
py/dist/py/test/rsession/conftest.py
py/dist/py/test/rsession/rest.py
py/dist/py/test/rsession/rsession.py
py/dist/py/test/rsession/testing/test_config.py
py/dist/py/test/rsession/testing/test_executor.py
py/dist/py/test/rsession/testing/test_lsession.py
py/dist/py/test/rsession/testing/test_master.py
py/dist/py/test/rsession/testing/test_reporter.py
py/dist/py/test/rsession/testing/test_rest.py
py/dist/py/test/rsession/testing/test_rsession.py
py/dist/py/test/rsession/testing/test_slave.py
py/dist/py/test/rsession/testing/test_web.py
py/dist/py/test/rsession/testing/test_webjs.py
py/dist/py/test/session.py
py/dist/py/test/terminal/remote.py
py/dist/py/test/terminal/terminal.py
py/dist/py/test/testing/test_collect.py
py/dist/py/test/testing/test_config.py
py/dist/py/test/testing/test_session.py
py/dist/py/test/tkinter/backend.py
py/dist/py/test/tkinter/reportsession.py
py/dist/py/test/tkinter/testing/test_backend.py
py/dist/py/test/tkinter/testing/test_capture_out_err.py
Log:
* svn merge -r 36833:36901 http://codespeak.net/svn/py/branch/conftest/py
* merging in the first bunch of cleanups from
the conftest branch, main visible changes:
* implemented and localized conftest handling code
(in py/test/conftesthandle.py)
* removed redundancies while setting up config
and session objects
* refactored config objects methods and attributes,
you now use 'py.test.config' instead of 'py.test.Config'
as you are now dealing with an instance and not a class
anymore. py.test.config is a singleton-per-process
(tests have the _reparse() method to get to additional
config instances in a someone safe manner)
* cleaned up documentation, added some
docstrings to py.test objects
Modified: py/dist/py/__init__.py
==============================================================================
--- py/dist/py/__init__.py (original)
+++ py/dist/py/__init__.py Thu Jan 18 08:00:43 2007
@@ -32,7 +32,7 @@
'test.compat.TestCase' : ('./test/compat.py', 'TestCase'),
# configuration/initialization related test api
- 'test.Config' : ('./test/config.py', 'Config'),
+ 'test.config' : ('./test/config.py', 'config'),
'test.ensuretemp' : ('./test/config.py', 'ensuretemp'),
'test.cmdline.main' : ('./test/cmdline.py', 'main'),
Modified: py/dist/py/apigen/conftest.py
==============================================================================
--- py/dist/py/apigen/conftest.py (original)
+++ py/dist/py/apigen/conftest.py Thu Jan 18 08:00:43 2007
@@ -1,7 +1,7 @@
import py
-Option = py.test.Config.Option
-option = py.test.Config.addoptions("apigen test options",
+Option = py.test.config.Option
+option = py.test.config.addoptions("apigen test options",
Option('', '--webcheck',
action="store_true", dest="webcheck", default=False,
help="run XHTML validation tests"
Modified: py/dist/py/apigen/testing/test_apigen_functional.py
==============================================================================
--- py/dist/py/apigen/testing/test_apigen_functional.py (original)
+++ py/dist/py/apigen/testing/test_apigen_functional.py Thu Jan 18 08:00:43 2007
@@ -7,6 +7,7 @@
from test_apigen_example import setup_fs_project
def test_apigen_functional():
+ py.test.skip("needs fixing with respect to rev 36800 and probably other problems")
fs_root, package_name = setup_fs_project(
'test_apigen_functional')
tempdir = py.test.ensuretemp('test_apigen_functional_results')
Modified: py/dist/py/conftest.py
==============================================================================
--- py/dist/py/conftest.py (original)
+++ py/dist/py/conftest.py Thu Jan 18 08:00:43 2007
@@ -17,9 +17,9 @@
nomagic = False
import py
-Option = py.test.Config.Option
+Option = py.test.config.Option
-option = py.test.Config.addoptions("execnet options",
+option = py.test.config.addoptions("execnet options",
Option('-S', '',
action="store", dest="sshtarget", default=None,
help=("target to run tests requiring ssh, e.g. "
Modified: py/dist/py/doc/conftest.py
==============================================================================
--- py/dist/py/doc/conftest.py (original)
+++ py/dist/py/doc/conftest.py Thu Jan 18 08:00:43 2007
@@ -2,8 +2,8 @@
import py
from py.__.misc import rest
-Option = py.test.Config.Option
-option = py.test.Config.addoptions("documentation check options",
+Option = py.test.config.Option
+option = py.test.config.addoptions("documentation check options",
Option('-R', '--checkremote',
action="store_true", dest="checkremote", default=False,
help="check remote links in ReST files"
Modified: py/dist/py/doc/example/pytest/test_failures.py
==============================================================================
--- py/dist/py/doc/example/pytest/test_failures.py (original)
+++ py/dist/py/doc/example/pytest/test_failures.py Thu Jan 18 08:00:43 2007
@@ -3,9 +3,9 @@
failure_demo = py.magic.autopath().dirpath('failure_demo.py')
def test_failure_demo_fails_properly():
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([failure_demo])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([failure_demo])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 21
l = session.getitemoutcomepairs(py.test.Item.Passed)
Modified: py/dist/py/doc/test.txt
==============================================================================
--- py/dist/py/doc/test.txt (original)
+++ py/dist/py/doc/test.txt Thu Jan 18 08:00:43 2007
@@ -358,6 +358,7 @@
.. _`basicpicture`:
+
Collecting and running tests / implementation remarks
======================================================
@@ -396,7 +397,7 @@
------------------------------------------
The collecting process is iterative, i.e. the session
-traverses the *collector tree*. Here is an example of such
+traverses and generates a *collector tree*. Here is an example of such
a tree, generated with the command ``py.test --collectonly py/xmlobj``::
<Directory 'xmlobj'>
@@ -421,38 +422,6 @@
.. _`collector API`:
-collector API invoked by sessions
----------------------------------
-
-Apart from initialization the default session object invokes
-a very uniform API on collectors and test items:
-
-*colitem.run()*
-
- returns a list of names available from this collector.
- You can return an empty list. Callers of this method
- must take care to catch exceptions properly. The session
- object guards its calls to ``colitem.run()`` in its
- ``session.runtraced(colitem)`` method, including
- catching of stdout.
-
-*colitem.join(name)*
-
- return a child item from the given name. Usually the
- session feeds the join method with each name obtained
- from ``colitem.run()``. If the return value is None
- it means the ``colitem`` was not able to resolve
- with the given name.
-
-*colitem.parent*
-
- attribute pointing to the parent collector.
-
-*colitem.name*
-
- name of this sub item. This is the name that is
- passed to ``colitem.join()`` above.
-
test items are collectors as well
---------------------------------
@@ -477,7 +446,8 @@
on a path object (which returns the parent directory
as a path object).
-* insert this base directory into sys.path as its first item
+* insert this base directory into the sys.path list
+ as its first element
* import the root package
@@ -485,10 +455,11 @@
at ``path`` ...
* if the imported root package has a __package__ object
- then call its ``getimportname(path)``
+ then call ``__package__.getimportname(path)``
* otherwise use the relative path of the module path to
- the base dir and turn slashes into dots.
+ the base dir and turn slashes into dots and strike
+ the trailing ``.py``.
The Module collector will eventually trigger
``__import__(mod_fqdnname, ...)`` to finally get to
@@ -504,48 +475,16 @@
and test classes and methods. Test functions and methods
are prefixed ``test`` by default. Test classes must
start with a capitalized ``Test`` prefix.
-
-Reporting hooks of the session object
--------------------------------------
-
-Part of the default session API deals with reporting
-test outcomes and collection details. These methods
-are reponsible for representing the testing process
-to the user or other programs:
-
-*session.header()*
-
- invoked once by ``session.run()`` before the whole
- test session starts.
-*session.footer()*
-
- invoked once by ``session.run()`` after the collection
- and running process finished.
-
-
-*session.start(colitem)*
-
- invoked before each ``colitem.run()`` invocation
-
-
-*session.finish(colitem, outcome)*
-
- invoked after each ``colitem.run()`` invocation
+Customizing the testing process
+===============================
+writing conftest.py files
+-----------------------------------
-XXX the names of these session objects are likely to change
-soon because the session object now has too many names that
-aren't easily distinguishable regarding their purposes. It is
-also likely that collectors/test items will become more
-self-responsible for presenting outcomes in textual ways.
-Currently, session object have to know too much about the
-representation of failures/successes to the user which makes
-it harder than neccessary to write custom test items.
+XXX
-Customizing the testing process
-===============================
customizing the collecting and running process
-----------------------------------------------
@@ -666,33 +605,17 @@
machines accessible through SSH, ``py.test`` can distribute
tests across the machines. It does not require any particular
installation on the remote machine sides as it uses `py.execnet`_
-mechanisms to distribute execution.
-
-*Warning*: support for distributed testing is in alpha state
-and its mechanics and configuration options may change without
-prior notice.
-
-Benefits
---------
-
-The main benefit for using distributed testing is speed. There
-is some runtime overhead required to setup the test environment on the
-remote machines, but if the project has a lot of tests and
-several machines available, the speed up should be significant
-in most cases. The more machines available, the better results
-you will get.
-
-Automatically distributing the tests can be also be useful if you
-need to use remote resouces which you do not have locally (perhaps
-a server has much more RAM or disk available).
-Of course, you could also just ssh into the remote server,
-rsync or checkout your source code and run py.test
-but that is obviously more cumbersome for the development
-process.
-
-The distributed testing part of ``py.test`` also provides
-a web server interface which tells you about the progress
-of your distributed test run interactively.
+mechanisms to distribute execution. Using distributed testing
+can speed up your development process considerably and it
+may also be useful where you need to use a remote server
+that has more resources (e.g. RAM/diskspace) than your
+local machine.
+
+*WARNING*: support for distributed testing is experimental,
+its mechanics and configuration options may change without
+prior notice. Particularly, not all reporting features
+of the in-process py.test have been integrated into
+the distributed testing approach.
Requirements
------------
@@ -702,23 +625,23 @@
* ssh client
* python
-Remote requirements:
+requirements for remote machines:
* ssh daemon running
* ssh keys setup to allow login without a password
* python (2.3 or 2.4 should work)
-* unix like machine (``os.fork``)
+* unix like machine (reliance on ``os.fork``)
-How it works
-------------
+Hot to use it
+-----------------------
When you issue ``py.test --session=R`` then your computer becomes
-the distributor of tests ("master") and will start distributing tests
-to several machines which need to be specified in a ``conftest.py``
-file.
+the distributor of tests ("master") and will start collecting
+and distributing tests to several machines. The machines
+need to be specified in a ``conftest.py`` file.
-At start up, the master connects to each node using `py.execnet`_ and
-its SSHGateways and *rsyncs* all specified python packages to all nodes.
+At start up, the master connects to each node using `py.execnet.SshGateway`_
+and *rsyncs* all specified python packages to all nodes.
Then the master collects all of the tests and immediately sends test item
descriptions to its connected nodes. Each node has a local queue of tests
to run and begins to execute the tests, following the setup and teardown
@@ -730,6 +653,7 @@
from the testing nodes: command line, rest output and ajaxy web based.
.. _`py.execnet`: execnet.html
+.. _`py.execnet.SshGateway`: execnet.html
Differences from local tests
----------------------------
@@ -745,19 +669,21 @@
The options that you need to specify in that conftest.py file are:
-* `disthosts` - a list of ssh addresses (including a specific path if it
+* `dist_hosts` - a list of ssh addresses (including a specific path if it
should be different than the default: ``$HOME/pytestcache-hostname``)
-* `distrsync_roots` - a list of packages to copy to the remote machines.
+* `dist_rsync_roots` - a list of packages to copy to the remote machines.
* `dist_remotepython` - the remote python to run.
* `SessionOptions` - containing some specific tuning options
Sample configuration::
- disthosts = ['localhost', 'user at someserver:/tmp/somedir']
- distrsync_roots = ['pypy', 'py']
+ dist_hosts = ['localhost', 'user at someserver:/tmp/somedir']
+ dist_rsync_roots = ['pypy', 'py']
dist_remotepython = 'python2.4'
- class SessionOptions:
- nice_level = 10
+ dist_nicelevel = 10
+ dist_boxing = True
+ dist_maxwait = 100
+ dist_taskspernode = 10
Running server is done by ``-w`` command line option or ``--startserver``
(the former might change at some point due to conflicts).
@@ -767,8 +693,8 @@
* `nice_level` - Level of nice under which tests are run
* `runner_policy` - (for `LSession` only) - contains policy for the test boxig.
`"plain_runner"` means no boxing, `"box_runner"` means boxing.
-* `waittime` - Default waiting time for remote host to finish tests (after
- that period we consider node as dead, default to 100s).
+* `waittime` - Default maximum waiting time for remote host to execute
+ one test.
* `max_tasks_per_node` - Maximum number of tasks which can be send to one node.
* `import_pypy` - Flag to control pypy importing for js regeneration (defaults
to False)
Modified: py/dist/py/doc/test_conftest.py
==============================================================================
--- py/dist/py/doc/test_conftest.py (original)
+++ py/dist/py/doc/test_conftest.py Thu Jan 18 08:00:43 2007
@@ -28,9 +28,9 @@
end
"""))
- config, args = py.test.Config.parse([str(xtxt)])
+ config = py.test.config._reparse([xtxt])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([xtxt])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 0
l = session.getitemoutcomepairs(py.test.Item.Passed)
@@ -46,9 +46,9 @@
.. _`blah`: javascript:some_function()
"""))
- config, args = py.test.Config.parse([str(xtxt)])
+ config = py.test.config._reparse([xtxt])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([xtxt])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 0
l = session.getitemoutcomepairs(py.test.Item.Passed)
Modified: py/dist/py/test/cmdline.py
==============================================================================
--- py/dist/py/test/cmdline.py (original)
+++ py/dist/py/test/cmdline.py Thu Jan 18 08:00:43 2007
@@ -10,7 +10,8 @@
args = py.std.sys.argv[1:]
elif isinstance(args, basestring):
args = args.split(" ")
- config, args = py.test.Config.parse(args)
+ config = py.test.config
+ config.parse(args)
sessionclass = config.getsessionclass()
# ok, some option checks
@@ -31,17 +32,8 @@
session = sessionclass(config)
- if config.option.runbrowser and not config.option.startserver:
- print "Cannot point browser when not starting server"
- config.option.startserver = True
- try:
- if config.getinitialvalue('startserver'):
- py.std.warnings.warn("Startserver flag in config is deprecated, use commandline option instead")
- except ValueError:
- pass
-
try:
- failures = session.main(args)
+ failures = session.main()
if failures:
raise SystemExit, 1
except KeyboardInterrupt:
Modified: py/dist/py/test/collect.py
==============================================================================
--- py/dist/py/test/collect.py (original)
+++ py/dist/py/test/collect.py Thu Jan 18 08:00:43 2007
@@ -29,7 +29,7 @@
def configproperty(name):
def fget(self):
#print "retrieving %r property from %s" %(name, self.fspath)
- return py.test.Config.getvalue(name, self.fspath)
+ return py.test.config.getvalue(name, self.fspath)
return property(fget)
def getfscollector(fspath):
@@ -43,7 +43,7 @@
pkgpath = fspath
else:
pkgpath = fspath.dirpath()
- Directory = py.test.Config.getvalue('Directory', pkgpath)
+ Directory = py.test.config.getvalue('Directory', pkgpath)
current = Directory(pkgpath)
#print "pkgpath", pkgpath
names = filter(None, fspath.relto(pkgpath).split(fspath.sep))
@@ -55,6 +55,14 @@
return current
class Collector(object):
+ """ Collector instances are iteratively generated
+ (through their run() and join() methods)
+ and form a tree. attributes::
+
+ parent: attribute pointing to the parent collector
+ (or None if it is the root collector)
+ name: basename of this collector object
+ """
def __init__(self, name, parent=None):
self.name = name
self.parent = parent
@@ -113,6 +121,25 @@
#print "cmp", s1, s2
return cmp(s1, s2)
+
+ def run(self):
+ """ returns a list of names available from this collector.
+ You can return an empty list. Callers of this method
+ must take care to catch exceptions properly. The session
+ object guards its calls to ``colitem.run()`` in its
+ ``session.runtraced(colitem)`` method, including
+ catching of stdout.
+ """
+ raise NotImplementedError("abstract")
+
+ def join(self, name):
+ """ return a child item for the given name. Usually the
+ session feeds the join method with each name obtained
+ from ``colitem.run()``. If the return value is None
+ it means the ``colitem`` was not able to resolve
+ with the given name.
+ """
+
def obj():
def fget(self):
try:
@@ -287,7 +314,7 @@
elif p.ext == '.txt':
res = self.DoctestFile(p, parent=self)
elif p.check(dir=1):
- Directory = py.test.Config.getvalue('Directory', p)
+ Directory = py.test.config.getvalue('Directory', p)
res = Directory(p, parent=self)
name2items[name] = res
return res
@@ -364,7 +391,7 @@
return res
def startcapture(self):
- if not self.option.nocapture and not self.option.usepdb:
+ if not self.option.nocapture:
assert not hasattr(self, '_capture')
#self._capture = py.io.OutErrCapture()
# XXX integrate this into py.io / refactor
@@ -454,7 +481,7 @@
Collector.Function.__get__(self)) # XXX for python 2.2
Function = property(Function)
-class Generator(Collector, PyCollectorMixin):
+class Generator(PyCollectorMixin, Collector):
def run(self):
self._prepare()
itemlist = self._name2items
Modified: py/dist/py/test/config.py
==============================================================================
--- py/dist/py/test/config.py (original)
+++ py/dist/py/test/config.py Thu Jan 18 08:00:43 2007
@@ -1,16 +1,9 @@
from __future__ import generators
import py
-optparse = py.compat.optparse
-
-defaultconfig = py.magic.autopath().dirpath('defaultconftest.py')
-dummy = object()
-
-#
-# configuration file handling
-#
-configbasename = 'conftest.py'
+from conftesthandle import Conftest
+optparse = py.compat.optparse
# XXX move to Config class
basetemp = None
@@ -22,113 +15,90 @@
if basetemp is None:
basetemp = py.path.local.make_numbered_dir(prefix='pytest-')
return basetemp.ensure(string, dir=dir)
-
+
+class CmdOptions(object):
+ """ pure container instance for holding cmdline options
+ as attributes.
+ """
+ def __repr__(self):
+ return "<CmdOptions %r>" %(self.__dict__,)
+
class Config(object):
""" central hub for dealing with configuration/initialization data. """
Option = optparse.Option
- _configs_cache = {}
+ conftest = Conftest()
def __init__(self):
- self.option = optparse.Values()
- self._parser = optparse.OptionParser(usage="usage: %prog [options] [query] [filenames of tests]")
- self._initialconfigmodules = []
-
- # class level attributes
- def _reset(cls):
- cls._config = cls()
- _reset = classmethod(_reset)
-
- def getvalue(cls, name, path=None, default=dummy, trydefaultconfig=True):
- """ return 'name' value looked up from the first conftest file
- found up the path (including the path itself).
- """
- configpaths = guessconfigpaths(path)
- if trydefaultconfig:
- configpaths.append(defaultconfig)
- for p in configpaths:
- try:
- mod = cls._configs_cache[p]
- except (KeyError, IndexError):
- mod = importconfig(p)
- cls._configs_cache[p] = mod
- try:
- return getattr(mod, name)
- except AttributeError:
- pass
- if default is not dummy:
- return default
- raise ValueError("config value not found: %r, path=%r" % (name, path))
- getvalue = classmethod(getvalue)
-
- def parse(cls, args):
- """ return Config object and remaining arguments from parsing
- command line arguments.
+ self.option = CmdOptions()
+ self._parser = optparse.OptionParser(
+ usage="usage: %prog [options] [query] [filenames of tests]")
+ self._parsed = False
+
+ def parse(self, args):
+ """ parse cmdline arguments into this config object.
+ Note that this can only be called once per testing process.
"""
- configpaths = guessconfigpaths(*getanchorpaths(args))
- config = bootstrapconfig(configpaths)
- config._origargs = args
- cmdlineoption, remaining = config._parser.parse_args(args)
- for name, value in vars(cmdlineoption).items():
- setattr(config.option, name, value)
- fixoptions(config.option)
+ assert not self._parsed, (
+ "can only parse cmdline args once per Config object")
+ self._parsed = True
+ self.conftest.setinitial(args)
+ self.conftest.lget('adddefaultoptions')()
+ args = [str(x) for x in args]
+ self._origargs = args
+ cmdlineoption, remaining = self._parser.parse_args(args)
+ self.option.__dict__.update(vars(cmdlineoption))
+ fixoptions(self.option) # XXX fixing should be moved to sessions
if not remaining:
remaining.append(py.std.os.getcwd())
- config.remaining = remaining
- return config, remaining
- parse = classmethod(parse)
+ self.remaining = remaining
- def addoptions(cls, groupname, *specs):
+ def addoptions(self, groupname, *specs):
""" add a named group of options to the current testing session.
This function gets invoked during testing session initialization.
"""
- parser = cls._config._parser
- optgroup = optparse.OptionGroup(parser, groupname)
+ optgroup = optparse.OptionGroup(self._parser, groupname)
optgroup.add_options(specs)
- parser.add_option_group(optgroup)
+ self._parser.add_option_group(optgroup)
for opt in specs:
if hasattr(opt, 'default') and opt.dest:
- setattr(cls._config.option, opt.dest, opt.default)
- return cls._config.option
- addoptions = classmethod(addoptions)
-
- # instance methods dealing with initial config module handling
-
- def loadconfig(self, configpath):
- """ load configpath as an initial config module. """
- mod = importconfig(configpath)
- self._initialconfigmodules.append(mod)
- return mod
-
- def getinitialvalue(self, name, default=dummy):
- """ return first value found in initial config modules. """
- for confmodule in self._initialconfigmodules:
- if hasattr(confmodule, name):
- return getattr(confmodule, name)
- if default is not dummy:
- return default
- raise ValueError("initial config value not found: %r" % name)
+ setattr(self.option, opt.dest, opt.default)
+ return self.option
+
+ def getvalue(self, name, path=None):
+ """ return 'name' value looked up from the first conftest file
+ found up the path (including the path itself).
+ if path is None, lookup the value in the initial
+ conftest modules found during command line parsing.
+ """
+ return self.conftest.rget(name, path)
def getsessionclass(self):
""" return Session class determined from cmdline options
and looked up in initial config modules.
"""
- # we need to import all the sessions here
- from py.__.test.session import Session
- from py.__.test.rsession.rsession import RSession, LSession
- from py.__.test.terminal.terminal import TerminalSession
- from py.__.test.tkinter.reportsession import ReportSession
- sessions = {'RSession':RSession, 'LSession':LSession,
- 'TerminalSession':TerminalSession,
- 'TkinterSession':ReportSession}
-
- name = self.option.session
- name += 'Session'
- try:
- return self.getinitialvalue(name)
- except ValueError:
- return sessions[name]
+ sessionname = self.option.session + 'Session'
+ try:
+ return self.conftest.lget(sessionname)
+ except KeyError:
+ pass
+ sessionimportpaths = self.conftest.lget('sessionimportpaths')
+ importpath = sessionimportpaths[sessionname]
+ mod = __import__(importpath, None, None, ['__doc__'])
+ return getattr(mod, sessionname)
+
+ def _reparse(self, args):
+ """ this is used from tests that want to re-invoke parse(). """
+ global config
+ oldconfig = py.test.config
+ try:
+ config = py.test.config = Config()
+ config.parse(args)
+ return config
+ finally:
+ config = py.test.config = oldconfig
-Config._reset()
+# this is the one per-process instance of py.test configuration
+config = Config()
#
# helpers
@@ -153,6 +123,11 @@
else:
option.executable = py.std.sys.executable
+ if option.usepdb:
+ if not option.nocapture:
+ print "--usepdb currently implies --nocapture"
+ option.nocapture = True
+
# make information available about wether we should/will be remote
option._remote = remote or option.looponfailing
option._fromremote = False
@@ -167,75 +142,7 @@
name = name.capitalize()
option.session = name
-def bootstrapconfig(configpaths):
- """ return 'current' config object, after initializing
- it with the given configpaths.
- """
- # XXX Config._config holds all options that are added from
- # conftest's py.test.Config.addoptions() invocations. This "global state"
- # manipulation is unfortunate but how else could we allow
- # applications to add cmdline options and provide them
- # access to the resulting config values?
-
- config = Config._config
- # trigger loading conftest files which might add options!
- config.loadconfig(defaultconfig).adddefaultoptions()
- for configpath in configpaths:
- config.loadconfig(configpath)
- # each time we make a config object (which assembled cmdline
- # options through py.test.addoptions() invocations)
- # we want to reset and clean up the global state
- Config._reset()
- return config
-
-_config_paths_cache = {}
-
-def guessconfigpaths(*paths):
- """ return test configuration paths from skimming the args. """
- key = tuple(paths)
- try:
- return _config_paths_cache[key]
- except KeyError:
- pass
- d = {}
- l = []
- for anchor in paths:
- if anchor:
- for p in anchor.parts():
- x = p.join(configbasename)
- if x not in d and x.check(file=1):
- d[x] = True
- l.append(x)
- l.reverse()
- _config_paths_cache[key] = l
- return l
-
-def getanchorpaths(args):
- """ yield "anchors" from skimming the args for existing files/dirs. """
- current = py.path.local()
- l = []
- for arg in args:
- anchor = current.join(arg, abs=1)
- if anchor.check():
- l.append(anchor)
- if not l:
- l = [current]
- return l
-
-def importconfig(configpath):
- if not configpath.dirpath('__init__.py').check(file=1):
- # HACK: we don't want a "globally" imported conftest.py,
- # prone to conflicts and subtle problems
- modname = str(configpath).replace('.', configpath.sep)
- return configpath.pyimport(modname=modname)
- else:
- return configpath.pyimport()
+ if option.runbrowser and not option.startserver:
+ print "Cannot point browser when not starting server"
+ option.startserver = True
-
-#XXX was needed for extracting defaults, not needed anymore?
-#def flattenoptions(parser):
-# for group in parser.option_groups:
-# for y in group.option_list:
-# yield y
-# for x in parser.option_list:
-# yield x
Modified: py/dist/py/test/defaultconftest.py
==============================================================================
--- py/dist/py/test/defaultconftest.py (original)
+++ py/dist/py/test/defaultconftest.py Thu Jan 18 08:00:43 2007
@@ -10,9 +10,17 @@
additionalinfo = None
+Option = py.test.config.Option
+
+sessionimportpaths = {
+ 'RSession': 'py.__.test.rsession.rsession',
+ 'LSession': 'py.__.test.rsession.rsession',
+ 'TerminalSession': 'py.__.test.terminal.terminal',
+ 'TkinterSession': 'py.__.test.tkinter.reportsession',
+}
+
def adddefaultoptions():
- Option = py.test.Config.Option
- py.test.Config.addoptions('general options',
+ py.test.config.addoptions('general options',
Option('-v', '--verbose',
action="count", dest="verbose", default=0,
help="increase verbosity."),
@@ -53,7 +61,8 @@
help="generate api documentation while testing (requires"
"argument pointing to a script)."),
)
- py.test.Config.addoptions('test-session related options',
+
+ py.test.config.addoptions('test-session related options',
Option('', '--tkinter',
action="store_true", dest="tkinter", default=False,
help="use tkinter test session frontend."),
Modified: py/dist/py/test/item.py
==============================================================================
--- py/dist/py/test/item.py (original)
+++ py/dist/py/test/item.py Thu Jan 18 08:00:43 2007
@@ -31,7 +31,7 @@
class Item(py.test.collect.Collector):
def startcapture(self):
- if not self.option.nocapture and not self.option.usepdb:
+ if not self.option.nocapture:
# XXX refactor integrate capturing
#self._capture = py.io.OutErrCapture()
from py.__.misc.simplecapture import SimpleOutErrCapture
Modified: py/dist/py/test/rsession/conftest.py
==============================================================================
--- py/dist/py/test/rsession/conftest.py (original)
+++ py/dist/py/test/rsession/conftest.py Thu Jan 18 08:00:43 2007
@@ -1,7 +1,7 @@
import py
-Option = py.test.Config.Option
+Option = py.test.config.Option
-option = py.test.Config.addoptions("boxing test options",
+option = py.test.config.addoptions("boxing test options",
Option('', '--skip-kill-test', action='store_true', default=False,
dest='skip_kill_test',
help='skip a certain test that checks for os.kill results, this '
Modified: py/dist/py/test/rsession/rest.py
==============================================================================
--- py/dist/py/test/rsession/rest.py (original)
+++ py/dist/py/test/rsession/rest.py Thu Jan 18 08:00:43 2007
@@ -19,7 +19,7 @@
def get_linkwriter(self):
if self.linkwriter is None:
- self.linkwriter = self.config.getinitialvalue('linkwriter')
+ self.linkwriter = self.config.getvalue('linkwriter')
return self.linkwriter
def report_unknown(self, what):
Modified: py/dist/py/test/rsession/rsession.py
==============================================================================
--- py/dist/py/test/rsession/rsession.py (original)
+++ py/dist/py/test/rsession/rsession.py Thu Jan 18 08:00:43 2007
@@ -45,8 +45,8 @@
def getvalue(self, opt):
try:
- return getattr(self.config.getinitialvalue('SessionOptions'), opt)
- except (ValueError, AttributeError):
+ return getattr(self.config.getvalue('SessionOptions'), opt)
+ except (KeyError, AttributeError):
try:
return self.defaults[opt]
except KeyError:
@@ -56,8 +56,8 @@
self.config = config
# copy to remote session options
try:
- ses_opt = self.config.getinitialvalue('SessionOptions').__dict__
- except ValueError:
+ ses_opt = self.config.getvalue('SessionOptions').__dict__
+ except KeyError:
ses_opt = self.defaults
for key in self.defaults:
try:
@@ -184,10 +184,9 @@
class RSession(AbstractSession):
""" Remote version of session
"""
- def main(self, args, reporter=None):
+ def main(self, reporter=None):
""" main loop for running tests. """
- if not args:
- args = [py.path.local()]
+ args = self.config.remaining
session_options.bind_config(self.config)
sshhosts, remotepython, rsync_roots = self.read_distributed_config()
@@ -216,14 +215,14 @@
def read_distributed_config(self):
try:
- rsync_roots = self.config.getinitialvalue("distrsync_roots")
+ rsync_roots = self.config.getvalue("distrsync_roots")
except:
rsync_roots = None # all files and directories in the pkgdir
sshhosts = [HostInfo(i) for i in
- self.config.getinitialvalue("disthosts")]
+ self.config.getvalue("disthosts")]
parse_directories(sshhosts)
try:
- remotepython = self.config.getinitialvalue("dist_remotepython")
+ remotepython = self.config.getvalue("dist_remotepython")
except:
remotepython = None
return sshhosts, remotepython, rsync_roots
@@ -246,11 +245,9 @@
class LSession(AbstractSession):
""" Local version of session
"""
- def main(self, args, reporter=None, runner=None):
+ def main(self, reporter=None, runner=None):
# check out if used options makes any sense
-
- if not args:
- args = [py.path.local()]
+ args = self.config.remaining
sshhosts = [HostInfo('localhost')] # this is just an info to reporter
Modified: py/dist/py/test/rsession/testing/test_config.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_config.py (original)
+++ py/dist/py/test/rsession/testing/test_config.py Thu Jan 18 08:00:43 2007
@@ -14,11 +14,11 @@
""")
tmp2 = py.test.ensuretemp("xxx")
args = [str(tmpdir)]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
session_options.bind_config(config)
assert session_options.max_tasks_per_node == 5
assert remote_options.nice_level == 10
- config, args = py.test.Config.parse([str(tmp2)])
+ config = py.test.config._reparse([str(tmp2)])
session_options.bind_config(config)
assert session_options.max_tasks_per_node == \
SessionOptions.defaults['max_tasks_per_node']
Modified: py/dist/py/test/rsession/testing/test_executor.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_executor.py (original)
+++ py/dist/py/test/rsession/testing/test_executor.py Thu Jan 18 08:00:43 2007
@@ -100,7 +100,7 @@
outcome_repr = ex.execute()
outcome = ReprOutcome(outcome_repr)
assert outcome.passed
- assert outcome.stdout == "samfing\n"
+ assert outcome.stdout.find("samfing") != -1
def test_box_executor_stdout_error():
rootcol = py.test.collect.Directory(rootdir)
@@ -109,7 +109,7 @@
outcome_repr = ex.execute()
outcome = ReprOutcome(outcome_repr)
assert not outcome.passed
- assert outcome.stdout == "samfing elz\n"
+ assert outcome.stdout.find("samfing elz") != -1
def test_cont_executor():
rootcol = py.test.collect.Directory(rootdir)
@@ -120,4 +120,4 @@
outcome_repr = cont()
outcome = ReprOutcome(outcome_repr)
assert not outcome.passed
- assert outcome.stdout == "samfing elz\n"
+ assert outcome.stdout.find("samfing elz") != -1
Modified: py/dist/py/test/rsession/testing/test_lsession.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_lsession.py (original)
+++ py/dist/py/test/rsession/testing/test_lsession.py Thu Jan 18 08:00:43 2007
@@ -32,10 +32,10 @@
# os.kill(os.getpid(), 11)
"""))
args = [str(tmpdir.join(dirname))]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
- lsession.main(args, reporter=allevents.append, runner=runner)
+ lsession.main(reporter=allevents.append, runner=runner)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents)
@@ -85,11 +85,11 @@
pdb.post_mortem = some_fun
args = [str(tmpdir.join(subdir)), '--pdb']
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
try:
- lsession.main(args, reporter=allevents.append, runner=plain_runner)
+ lsession.main(reporter=allevents.append, runner=plain_runner)
except SystemExit:
pass
else:
@@ -116,12 +116,12 @@
pass
"""))
args = [str(tmpdir.join(subdir)), '-x']
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
assert config.option.exitfirst
lsession = LSession(config)
allevents = []
- lsession.main(args, reporter=allevents.append, runner=box_runner)
+ lsession.main(reporter=allevents.append, runner=box_runner)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents)
@@ -146,11 +146,11 @@
pass
"""))
args = [str(tmpdir.join("sub3")), '-k', 'test_one']
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
- lsession.main(args, reporter=allevents.append, runner=box_runner)
+ lsession.main(reporter=allevents.append, runner=box_runner)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents)
@@ -174,7 +174,7 @@
"""))
args = [str(tmpdir.join("sub4"))]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
allruns = []
@@ -182,7 +182,7 @@
allruns.append(item)
item.passed = True
return item
- lsession.main(args, reporter=allevents.append, runner=dummy_runner)
+ lsession.main(reporter=allevents.append, runner=dummy_runner)
assert len(allruns) == 4
testevents = [x for x in allevents
@@ -205,10 +205,10 @@
"""))
args = [str(tmpdir.join("sub5"))]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
- lsession.main(args, reporter=allevents.append, runner=box_runner)
+ lsession.main(reporter=allevents.append, runner=box_runner)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents) == 0
@@ -231,10 +231,10 @@
assert [0] == x
"""))
args = [str(tmpdir.join("sub6"))]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
- lsession.main(args, reporter=allevents.append, runner=box_runner)
+ lsession.main(reporter=allevents.append, runner=box_runner)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
failevents = [i for i in testevents if i.outcome.excinfo]
@@ -252,10 +252,10 @@
print 3
"""))
args = [str(tmpdir.join("sub7"))]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
lsession = LSession(config)
allevents = []
- lsession.main(args, reporter=allevents.append, runner=plain_runner)
+ lsession.main(reporter=allevents.append, runner=plain_runner)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents) == 1
Modified: py/dist/py/test/rsession/testing/test_master.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_master.py (original)
+++ py/dist/py/test/rsession/testing/test_master.py Thu Jan 18 08:00:43 2007
@@ -18,7 +18,7 @@
def setup_module(mod):
# bind an empty config
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
config.option.max_tasks_per_node = 10
session_options.bind_config(config)
#assert not remote_options.exitfirst
Modified: py/dist/py/test/rsession/testing/test_reporter.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_reporter.py (original)
+++ py/dist/py/test/rsession/testing/test_reporter.py Thu Jan 18 08:00:43 2007
@@ -61,7 +61,7 @@
return outcomes
def report_received_item_outcome(self):
- config, args = py.test.Config.parse(["some_sub"])
+ config = py.test.config._reparse(["some_sub"])
# we just go...
rootcol = py.test.collect.Directory(self.pkgdir.dirpath())
item = rootcol.getitembynames(funcpass_spec)
@@ -81,7 +81,7 @@
return out
def _test_module(self):
- config, args = py.test.Config.parse(["some_sub"])
+ config = py.test.config._reparse(["some_sub"])
# we just go...
rootcol = py.test.collect.Directory(self.pkgdir.dirpath())
funcitem = rootcol.getitembynames(funcpass_spec)
@@ -119,7 +119,7 @@
"""))
def boxfun():
- config, args = py.test.Config.parse([str(tmpdir)])
+ config = py.test.config._reparse([str(tmpdir)])
rootcol = py.test.collect.Directory(tmpdir)
hosts = [HostInfo('localhost')]
r = self.reporter(config, hosts)
@@ -138,7 +138,7 @@
sadsadsa
"""))
def boxfun():
- config, args = py.test.Config.parse([str(tmpdir)])
+ config = py.test.config._reparse([str(tmpdir)])
rootcol = py.test.collect.Directory(tmpdir)
host = HostInfo('localhost')
r = self.reporter(config, [host])
@@ -157,7 +157,7 @@
tmpdir = py.test.ensuretemp("stilltogo")
tmpdir.ensure("__init__.py")
cap = py.io.OutErrCapture()
- config, args = py.test.Config.parse([str(tmpdir)])
+ config = py.test.config._reparse([str(tmpdir)])
hosts = [HostInfo(i) for i in ["host1", "host2", "host3"]]
r = self.reporter(config, hosts)
r.report(report.TestStarted(hosts))
@@ -170,7 +170,7 @@
host1: READY (still 2 to go)
host2: READY (still 1 to go)
host3: READY"""
- assert out.startswith(expected)
+ assert out.find(expected) != -1
class TestLocalReporter(AbstractTestReporter):
reporter = LocalReporter
@@ -191,7 +191,7 @@
repmod/test_one.py[1]
repmod/test_three.py[0] - FAILED TO LOAD MODULE
repmod/test_two.py[0] - skipped (reason)"""
- assert received == expected
+ assert received.find(expected) != -1
class TestRemoteReporter(AbstractTestReporter):
reporter = RemoteReporter
@@ -207,7 +207,7 @@
localhost: FAILED py test rsession testing test_slave.py funcpass
localhost: PASSED py test rsession testing test_slave.py funcpass
"""
- assert val == expected
+ assert val.find(expected) != -1
def test_module(self):
val = self._test_module()
@@ -217,10 +217,10 @@
localhost: FAILED py test rsession testing test_slave.py funcpass
localhost: PASSED py test rsession testing test_slave.py funcpass
"""
- assert val == expected
+ assert val.find(expected) != -1
def test_full_module(self):
#py.test.skip("XXX rewrite test to not rely on exact formatting")
val = self._test_full_module()
- assert val == 'FAILED TO LOAD MODULE: repmod/test_three.py\n'\
- '\nSkipped (reason) repmod/test_two.py\n\n'
+ assert val.find('FAILED TO LOAD MODULE: repmod/test_three.py\n'\
+ '\nSkipped (reason) repmod/test_two.py') != -1
Modified: py/dist/py/test/rsession/testing/test_rest.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_rest.py (original)
+++ py/dist/py/test/rsession/testing/test_rest.py Thu Jan 18 08:00:43 2007
@@ -27,7 +27,7 @@
class TestRestUnits(object):
def setup_method(self, method):
- config, args = py.test.Config.parse(["some_sub"])
+ config = py.test.config._reparse(["some_sub"])
config.option.verbose = False
self.config = config
hosts = [HostInfo('localhost')]
Modified: py/dist/py/test/rsession/testing/test_rsession.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_rsession.py (original)
+++ py/dist/py/test/rsession/testing/test_rsession.py Thu Jan 18 08:00:43 2007
@@ -91,10 +91,10 @@
pass
"""))
args = [str(tmpdir.join("sub")), "-x"]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
rsession = RSession(config)
allevents = []
- rsession.main(args, reporter=allevents.append)
+ rsession.main(reporter=allevents.append)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents) == 3
@@ -121,10 +121,10 @@
assert __file__ != '%s'
""" % str(tmpdir.join(subdir))))
args = [str(tmpdir.join(subdir))]
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
rsession = RSession(config, optimise_localhost=False)
allevents = []
- rsession.main(args, reporter=allevents.append)
+ rsession.main(reporter=allevents.append)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
assert len(testevents)
@@ -154,7 +154,7 @@
setup_events = []
teardown_events = []
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
session_options.bind_config(config)
nodes = init_hosts(setup_events.append, hosts, pkgdir,
rsync_roots=["py"], optimise_localhost=False, remote_options=remote_options.d)
@@ -181,7 +181,7 @@
parse_directories(hosts)
allevents = []
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
session_options.bind_config(config)
nodes = init_hosts(allevents.append, hosts, pkgdir,
rsync_roots=["py"], optimise_localhost=False, remote_options=remote_options.d)
@@ -214,7 +214,7 @@
assert len(skipped) == len(nodes)
assert len(events) == 4 * len(nodes)
# one of passed for each node has non-empty stdout
- passed_stdout = [i for i in passed if i.outcome.stdout == 'samfing\n']
+ passed_stdout = [i for i in passed if i.outcome.stdout.find('samfing') != -1]
assert len(passed_stdout) == len(nodes), passed
def test_config_pass(self):
@@ -223,7 +223,7 @@
allevents = []
hosts = [HostInfo('localhost')]
parse_directories(hosts)
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
session_options.bind_config(config)
d = remote_options.d.copy()
d['custom'] = 'custom'
@@ -264,11 +264,11 @@
assert os.nice(0) == 10
""")
- config, args = py.test.Config.parse([str(tmpdir)])
+ config = py.test.config._reparse([tmpdir])
config.option.nice_level = 10
rsession = RSession(config)
allevents = []
- rsession.main(args, reporter=allevents.append)
+ rsession.main(reporter=allevents.append)
testevents = [x for x in allevents
if isinstance(x, report.ReceivedItemOutcome)]
passevents = [x for x in testevents if x.outcome.passed]
Modified: py/dist/py/test/rsession/testing/test_slave.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_slave.py (original)
+++ py/dist/py/test/rsession/testing/test_slave.py Thu Jan 18 08:00:43 2007
@@ -13,7 +13,7 @@
def setup_module(module):
from py.__.test.rsession.rsession import session_options
module.rootdir = py.path.local(py.__file__).dirpath().dirpath()
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
session_options.bind_config(config)
# ----------------------------------------------------------------------
Modified: py/dist/py/test/rsession/testing/test_web.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_web.py (original)
+++ py/dist/py/test/rsession/testing/test_web.py Thu Jan 18 08:00:43 2007
@@ -13,7 +13,7 @@
py.test.skip("PyPy not found")
def setup_module(mod):
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
from py.__.test.rsession.rsession import session_options
session_options.bind_config(config)
session_options.import_pypy = True
Modified: py/dist/py/test/rsession/testing/test_webjs.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_webjs.py (original)
+++ py/dist/py/test/rsession/testing/test_webjs.py Thu Jan 18 08:00:43 2007
@@ -15,7 +15,7 @@
mod.dom = dom
dom.window = dom.Window(html)
dom.document = dom.window.document
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
from py.__.test.rsession.rsession import session_options
session_options.bind_config(config)
session_options.import_pypy = True
Modified: py/dist/py/test/session.py
==============================================================================
--- py/dist/py/test/session.py (original)
+++ py/dist/py/test/session.py Thu Jan 18 08:00:43 2007
@@ -13,20 +13,21 @@
return False
def header(self, colitems):
- """ setup any neccessary resources. """
+ """ setup any neccessary resources ahead of the test run. """
if not self.config.option.nomagic:
py.magic.invoke(assertion=1)
def footer(self, colitems):
- """ teardown any resources we know about. """
+ """ teardown any resources after a test run. """
py.test.Function.state.teardown_all()
if not self.config.option.nomagic:
py.magic.revoke(assertion=1)
def start(self, colitem):
- pass
+ """ hook invoked before each colitem.run() invocation. """
def finish(self, colitem, outcome):
+ """ hook invoked after each colitem.run() invocation. """
self._memo.append((colitem, outcome))
def startiteration(self, colitem, subitems):
@@ -35,9 +36,9 @@
def getitemoutcomepairs(self, cls):
return [x for x in self._memo if isinstance(x[1], cls)]
- def main(self, args):
+ def main(self):
""" main loop for running tests. """
- colitems = self._map2colitems(args)
+ colitems = self._map2colitems(self.config.remaining)
try:
self.header(colitems)
try:
Modified: py/dist/py/test/terminal/remote.py
==============================================================================
--- py/dist/py/test/terminal/remote.py (original)
+++ py/dist/py/test/terminal/remote.py Thu Jan 18 08:00:43 2007
@@ -53,7 +53,7 @@
def failure_slave(channel):
""" we run this on the other side. """
args, failures = channel.receive()
- config, args = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
# making this session definitely non-remote
config.option.executable = py.std.sys.executable
config.option.looponfailing = False
@@ -66,7 +66,7 @@
#print "processing", cols
session = config.getsessionclass()(config)
session.shouldclose = channel.isclosed
- failures = session.main(cols)
+ failures = session.main()
channel.send(failures)
def getfailureitems(failures):
Modified: py/dist/py/test/terminal/terminal.py
==============================================================================
--- py/dist/py/test/terminal/terminal.py (original)
+++ py/dist/py/test/terminal/terminal.py Thu Jan 18 08:00:43 2007
@@ -28,12 +28,12 @@
self._started = {}
self._opencollectors = []
- def main(self, args):
+ def main(self):
if self.config.option._remote:
from py.__.test.terminal import remote
return remote.main(self.config, self._file, self.config._origargs)
else:
- return super(TerminalSession, self).main(args)
+ return super(TerminalSession, self).main()
# ---------------------
# PROGRESS information
@@ -145,7 +145,8 @@
for x in colitems:
self.out.line("test target: %s" %(x.fspath,))
- for i,x in py.builtin.enumerate(self.config._initialconfigmodules):
+ conftestmodules = self.config.conftest.getconftestmodules(None)
+ for i,x in py.builtin.enumerate(conftestmodules):
self.out.line("initial conf %d: %s" %(i, x.__file__))
#for i, x in py.builtin.enumerate(py.test.config.configpaths):
Modified: py/dist/py/test/testing/test_collect.py
==============================================================================
--- py/dist/py/test/testing/test_collect.py (original)
+++ py/dist/py/test/testing/test_collect.py Thu Jan 18 08:00:43 2007
@@ -1,13 +1,13 @@
from __future__ import generators
import py
-datadir = py.magic.autopath().dirpath('data')
+from setupdata import setupdatadir
-tmpdir = py.test.ensuretemp('test_collect')
+def setup_module(mod):
+ mod.datadir = setupdatadir()
+ mod.tmpdir = py.test.ensuretemp('test_collect')
def test_failing_import_execfile():
- fn = datadir / 'failingimport.py'
- dest = tmpdir.join('failing_import.py')
- fn.copy(dest)
+ dest = datadir / 'failingimport.py'
col = py.test.collect.Module(dest)
py.test.raises(ImportError, col.run)
py.test.raises(ImportError, col.run)
@@ -213,20 +213,20 @@
# test that running a session works from the directories
old = o.chdir()
try:
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
out = py.std.cStringIO.StringIO()
session = config.getsessionclass()(config, out)
- session.main(args)
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert len(l) == 2
finally:
old.chdir()
# test that running the file directly works
- config, args = py.test.Config.parse([str(checkfile)])
+ config = py.test.config._reparse([str(checkfile)])
out = py.std.cStringIO.StringIO()
session = config.getsessionclass()(config, out)
- session.main(args)
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert len(l) == 2
@@ -260,20 +260,20 @@
# test that running a session works from the directories
old = o.chdir()
try:
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
out = py.std.cStringIO.StringIO()
session = config.getsessionclass()(config, out)
- session.main(args)
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert len(l) == 1
finally:
old.chdir()
# test that running the file directly works
- config, args = py.test.Config.parse([str(checkfile)])
+ config = py.test.config._reparse([str(checkfile)])
out = py.std.cStringIO.StringIO()
session = config.getsessionclass()(config, out)
- session.main(args)
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert len(l) == 1
Modified: py/dist/py/test/testing/test_config.py
==============================================================================
--- py/dist/py/test/testing/test_config.py (original)
+++ py/dist/py/test/testing/test_config.py Thu Jan 18 08:00:43 2007
@@ -1,26 +1,5 @@
from __future__ import generators
import py
-from py.__.test import config
-
-class MyClass:
- def getoptions(self):
- yield config.Option('-v', action="count", dest="verbose", help="verbose")
-
-def xtest_verbose():
- obj = MyClass()
- args = config.parseargs(['-v', 'hello'], obj)
- assert args == ['hello']
- assert hasattr(obj, 'option')
- assert hasattr(obj.option, 'verbose')
- assert obj.option.verbose
-
-def xtest_verbose_default():
- obj = MyClass()
- args = config.parseargs(['hello'], obj)
- assert args, ['hello']
- assert hasattr(obj, 'option')
- assert hasattr(obj.option, 'verbose')
- assert not obj.option.verbose
def test_tmpdir():
d1 = py.test.ensuretemp('hello')
@@ -28,14 +7,14 @@
assert d1 == d2
assert d1.check(dir=1)
-def test_config_options():
+def test_config_cmdline_options():
o = py.test.ensuretemp('configoptions')
o.ensure("conftest.py").write(py.code.Source("""
import py
def _callback(option, opt_str, value, parser, *args, **kwargs):
option.tdest = True
- Option = py.test.Config.Option
- option = py.test.Config.addoptions("testing group",
+ Option = py.test.config.Option
+ option = py.test.config.addoptions("testing group",
Option('-g', '--glong', action="store", default=42,
type="int", dest="gdest", help="g value."),
# XXX note: special case, option without a destination
@@ -45,35 +24,30 @@
"""))
old = o.chdir()
try:
- config, args = py.test.Config.parse(['-g', '17'])
- assert config.option.gdest == 17
+ config = py.test.config._reparse(['-g', '17'])
finally:
old.chdir()
-
-#def test_config_order():
-# from py.__.test import config
-# o = py.test.ensuretemp('configorder')
-# o.ensure('conftest.py').write('x=1 ; import py ; py._x = [x]')
-# o.ensure('a/conftest.py').write('x=2 ; import py ; py._x.append(x)')
-# o.ensure('a/b/c/conftest.py').write('x=3 ; import py ; py._x.append(x)')
-# cfg = config.Config()
-# cfg.readconfiguration(o)
-# assert cfg.getfirst('x') == 1
-# assert py._x == [1]
-#
-# cfg = config.Config()
-# cfg.readconfiguration(o.join('a/b/c'))
-# assert cfg.getfirst('x') == 1
-# assert py._x == [1,2,3]
-#
-#def test_getconfigvalue():
-# from py.__.test import config
-# cfg = config.Config()
-# o = py.test.ensuretemp('configtest')
-# o.ensure('conftest.py').write('x=1')
-# assert cfg.getconfigvalue(o, 'x') == 1
-# py.test.raises(ValueError, "cfg.getconfigvalue(o, 'y')")
-#
+ assert config.option.gdest == 17
+
+def test_parsing_again_fails():
+ dir = py.test.ensuretemp("parsing_again_fails")
+ config = py.test.config._reparse([str(dir)])
+ py.test.raises(AssertionError, "config.parse([])")
+
+def test_config_getvalue_honours_conftest():
+ o = py.test.ensuretemp('testconfigget')
+ o.ensure("conftest.py").write("x=1")
+ o.ensure("sub", "conftest.py").write("x=2 ; y = 3")
+ config = py.test.config._reparse([str(o)])
+ assert config.getvalue("x") == 1
+ assert config.getvalue("x", o.join('sub')) == 2
+ py.test.raises(KeyError, "config.getvalue('y')")
+ config = py.test.config._reparse([str(o.join('sub'))])
+ assert config.getvalue("x") == 2
+ assert config.getvalue("y") == 3
+ assert config.getvalue("x", o) == 1
+ py.test.raises(KeyError, 'config.getvalue("y", o)')
+
def test_siblingconftest_fails_maybe():
from py.__.test import config
Modified: py/dist/py/test/testing/test_session.py
==============================================================================
--- py/dist/py/test/testing/test_session.py (original)
+++ py/dist/py/test/testing/test_session.py Thu Jan 18 08:00:43 2007
@@ -1,32 +1,35 @@
import py
-datadir = py.magic.autopath().dirpath('data')
-from cStringIO import StringIO
+from setupdata import setupdatadir
-tmpdir = py.test.ensuretemp('test_drive')
+def setup_module(mod):
+ mod.datadir = setupdatadir()
+ mod.tmpdir = py.test.ensuretemp(mod.__name__)
class TestDefaultSession:
def test_simple(self):
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([datadir/'filetest.py'])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([datadir / 'filetest.py'])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 2
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert not l
def test_simple_verbose(self):
- config, args = py.test.Config.parse(['--verbose'])
+ config = py.test.config._reparse([datadir/'filetest.py',
+ '--verbose'])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([datadir / 'filetest.py'])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 2
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert not l
def test_simple_verbose_verbose(self):
- config, args = py.test.Config.parse(['-v', '-v'])
+ config = py.test.config._reparse([datadir/'filetest.py',
+ '-v', '-v'])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([datadir / 'filetest.py'])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 2
l = session.getitemoutcomepairs(py.test.Item.Passed)
@@ -35,19 +38,20 @@
def test_session_parsing(self):
from py.__.test.terminal.terminal import TerminalSession
from py.__.test.tkinter.reportsession import ReportSession
- config, args = py.test.Config.parse(['--session=terminal'])
+ config = py.test.config._reparse(['--session=terminal'])
assert issubclass(config.getsessionclass(), TerminalSession)
- config, args = py.test.Config.parse(['--session=tkinter'])
+ config = py.test.config._reparse(['--session=tkinter'])
assert issubclass(config.getsessionclass(), ReportSession)
- config, args = py.test.Config.parse(['--tkinter'])
+ config = py.test.config._reparse(['--tkinter'])
assert issubclass(config.getsessionclass(), ReportSession)
class TestKeywordSelection:
def test_select_simple(self):
for keyword in ['test_one', 'est_on']:
- config, args = py.test.Config.parse(['-k', keyword])
+ config = py.test.config._reparse([datadir/'filetest.py',
+ '-k', keyword])
session = config.getsessionclass()(config, py.std.sys.stdout)
- session.main([datadir / 'filetest.py'])
+ session.main()
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 1
item = l[0][0]
@@ -73,10 +77,10 @@
"""))
for keyword in ('xxx', 'xxx test_2', 'TestClass', 'xxx -test_1',
'TestClass test_2', 'xxx TestClass test_2',):
- f = StringIO()
- config, args = py.test.Config.parse(['-k', keyword])
+ f = py.std.StringIO.StringIO()
+ config = py.test.config._reparse([o, '-k', keyword])
session = config.getsessionclass()(config, f)
- session.main([o])
+ session.main()
print "keyword", repr(keyword)
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert len(l) == 1
@@ -93,33 +97,23 @@
def teardown_class(cls):
(datadir / 'syntax_error.py').remove()
- def setup_method(self, method):
+ def mainsession(self, *args):
from py.__.test.terminal.terminal import TerminalSession
- self.file = StringIO()
- config, args = py.test.Config.parse([])
- self.session = TerminalSession(config, file=self.file)
- #print >>f, "session %r is setup for %r" %(self.session, method)
- #f.flush()
- #print "session is setup", self.session
-
- #def teardown_method(self, method):
- #print >>f, "session %r finished method %r" % (self.session, method)
- #f.flush()
+ self.file = py.std.StringIO.StringIO()
+ config = py.test.config._reparse(list(args))
+ session = TerminalSession(config, file=self.file)
+ session.main()
+ return session
def test_terminal(self):
- self.session.main([datadir / 'filetest.py'])
+ session = self.mainsession(datadir / 'filetest.py')
out = self.file.getvalue()
- #print "memo"
- #print self.session._memo
- #print "out"
- #print out
- l = self.session.getitemoutcomepairs(py.test.Item.Failed)
+ l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 2
assert out.find('2 failed') != -1
def test_syntax_error_module(self):
- session = self.session
- session.main([str(datadir / 'syntax_error.py')])
+ session = self.mainsession(datadir / 'syntax_error.py')
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 1
out = self.file.getvalue()
@@ -127,18 +121,18 @@
assert out.find(str('not python')) != -1
def test_exit_first_problem(self):
- session = self.session
- session.config.option.exitfirst = True
- session.main([str(datadir / 'filetest.py')])
+ session = self.mainsession("--exitfirst",
+ datadir / 'filetest.py')
+ assert session.config.option.exitfirst
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 1
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert not l
def test_collectonly(self):
- session = self.session
- session.config.option.collectonly = True
- session.main([str(datadir / 'filetest.py')])
+ session = self.mainsession("--collectonly",
+ datadir / 'filetest.py')
+ assert session.config.option.collectonly
out = self.file.getvalue()
#print out
l = session.getitemoutcomepairs(py.test.Item.Failed)
@@ -162,11 +156,7 @@
f()
f()
"""))
- #print "hello"
- session = self.session
- #session.config.option.nocapture = True
- print "calling main", o
- session.main([str(o)])
+ session = self.mainsession(o)
print "back from main", o
out = self.file.getvalue()
#print out
@@ -180,8 +170,7 @@
def test_1():
yield None
"""))
- session = self.session
- session.main([o])
+ session = self.mainsession(o)
out = self.file.getvalue()
#print out
i = out.find('TypeError')
@@ -209,8 +198,7 @@
def finishcapture(self):
self._testmycapture = self._mycapture.reset()
"""))
- session = self.session
- session.main([o])
+ session = self.mainsession(o)
l = session.getitemoutcomepairs(py.test.Item.Passed)
assert len(l) == 1
item = l[0][0]
@@ -236,8 +224,7 @@
def test_raises_doesnt():
py.test.raises(ValueError, int, "3")
"""))
- session = self.session
- session.main([o])
+ session = self.mainsession(o)
out = self.file.getvalue()
if not out.find("DID NOT RAISE") != -1:
print out
@@ -266,8 +253,7 @@
assert self.reslist == [1,2,1,2,3]
"""))
- session = self.session
- session.main([o])
+ session = self.mainsession(o)
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 0
l = session.getitemoutcomepairs(py.test.Item.Passed)
@@ -290,16 +276,14 @@
import does_not_work
a = 1
"""))
- session = self.session
- session.main([o])
+ session = self.mainsession(o)
l = session.getitemoutcomepairs(py.test.Item.Failed)
assert len(l) == 1
item, outcome = l[0]
assert str(outcome.excinfo).find('does_not_work') != -1
def test_safe_repr(self):
- session = self.session
- session.main([str(datadir / 'brokenrepr.py')])
+ session = self.mainsession(datadir/'brokenrepr.py')
out = self.file.getvalue()
print 'Output of simulated "py.test brokenrepr.py":'
print out
@@ -321,8 +305,7 @@
'c'])
""")
tfile.write(source)
- session = self.session
- session.main([o])
+ session = self.mainsession(o)
out = self.file.getvalue()
print 'Output of simulated "py.test test_correct_line.py":'
print out
@@ -362,14 +345,14 @@
assert 1 == 0
"""))
print py.std.sys.executable
- config, args = py.test.Config.parse(
+ config = py.test.config._reparse(
['--exec=' + py.std.sys.executable,
- str(o)])
+ o])
assert config.option._remote
cls = config.getsessionclass()
out = [] # out = py.std.Queue.Queue()
session = cls(config, out.append)
- session.main([o])
+ session.main()
for s in out:
if s.find('1 failed') != -1:
break
@@ -384,13 +367,13 @@
assert 1 == 0
"""))
print py.std.sys.executable
- config, args = py.test.Config.parse(['--looponfailing', str(o)])
+ config = py.test.config._reparse(['--looponfailing', str(o)])
assert config.option._remote
cls = config.getsessionclass()
out = py.std.Queue.Queue()
session = cls(config, out.put)
pool = py._thread.WorkerPool()
- reply = pool.dispatch(session.main, [str(o)])
+ reply = pool.dispatch(session.main)
while 1:
s = out.get()
if s.find('1 failed') != -1:
Modified: py/dist/py/test/tkinter/backend.py
==============================================================================
--- py/dist/py/test/tkinter/backend.py (original)
+++ py/dist/py/test/tkinter/backend.py Thu Jan 18 08:00:43 2007
@@ -229,12 +229,12 @@
from py.__.test.tkinter.reportsession import ReportSession
from py.__.test.terminal.remote import getfailureitems
- config, testfiles = py.test.Config.parse(args)
+ config = py.test.config._reparse(args)
if tests:
cols = getfailureitems(tests)
else:
- cols = testfiles
+ cols = config.remaining
session = ReportSession(config = config, channel=channel)
session.shouldclose = channel.isclosed
- session.main(cols)
+ session.main()
Modified: py/dist/py/test/tkinter/reportsession.py
==============================================================================
--- py/dist/py/test/tkinter/reportsession.py (original)
+++ py/dist/py/test/tkinter/reportsession.py Thu Jan 18 08:00:43 2007
@@ -44,4 +44,5 @@
def sendreport(self, report):
self.channel.send(report.to_channel())
+TkinterSession = ReportSession
Modified: py/dist/py/test/tkinter/testing/test_backend.py
==============================================================================
--- py/dist/py/test/tkinter/testing/test_backend.py (original)
+++ py/dist/py/test/tkinter/testing/test_backend.py Thu Jan 18 08:00:43 2007
@@ -178,7 +178,7 @@
assert l[0] is None
def test_start_tests(self):
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([])
self.backend.start_tests(config = config,
args = [str(datadir / 'filetest.py')],
tests = [])
Modified: py/dist/py/test/tkinter/testing/test_capture_out_err.py
==============================================================================
--- py/dist/py/test/tkinter/testing/test_capture_out_err.py (original)
+++ py/dist/py/test/tkinter/testing/test_capture_out_err.py Thu Jan 18 08:00:43 2007
@@ -5,10 +5,10 @@
datadir = py.magic.autopath().dirpath('data')
def test_capture_out_err():
- config, args = py.test.Config.parse([])
+ config = py.test.config._reparse([datadir/'filetest.py'])
backend = ReportBackend()
backend.start_tests(config = config,
- args = [str(datadir / 'filetest.py')],
+ args = config.remaining,
tests = [])
while backend.running:
backend.update()
_______________________________________________
py-svn mailing list
py-svn at codespeak.net
http://codespeak.net/mailman/listinfo/py-svn
----- End forwarded message -----
--
merlinux GmbH Steinbergstr. 42 31139 Hildesheim
http://merlinux.de tel +49 5121 20800 75 (fax 77)
More information about the py-dev
mailing list