From 707775dcfa9a0fff05bd465fb91ec759fdaa66af Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sat, 6 Nov 2010 22:17:33 +0100 Subject: [PATCH] introduce new --testpkg importpath option, add more meat to draft release announcement --- doc/announce/release-2.0.0.txt | 136 ++++++++++++++++++++++++++++----- doc/usage.txt | 72 ++++++++++------- pytest/__init__.py | 2 +- pytest/plugin/python.py | 4 +- pytest/plugin/session.py | 21 ++++- setup.py | 2 +- testing/acceptance_test.py | 21 +++++ 7 files changed, 204 insertions(+), 54 deletions(-) diff --git a/doc/announce/release-2.0.0.txt b/doc/announce/release-2.0.0.txt index 4cdd19c8f..16e250b44 100644 --- a/doc/announce/release-2.0.0.txt +++ b/doc/announce/release-2.0.0.txt @@ -3,14 +3,24 @@ py.test 2.0.0: standalone, features++, implementation++, docs++ XXX PENDING -Welcome to pytest-2.0.0! With this release py.test becomes its own standalone -PyPI distribution, named ``pytest``, installing the ``py.test`` command line -tool. Apart from a great internal cleanup this release comes with tons -of improvements and new features and a completely revamped extensive -documentation, including many continously tested examples. See +Welcome to pytest-2.0.0, rapid and easy testing for and with Python. +py.test now comes as its own PyPI distribution named ``pytest`` which +installs the ``py.test`` tool. It removes most long-deprecated code, +providing for a much smaller and easier to understand code base. There +are also many new features and much improved documentation. See http://pytest.org +for details or below for some more information. + +Thanks to all issue reporters and people asking questions or +complaining. Particular thanks to Floris Bruynooghe and Ronny Pfannschmidt +for their great coding contributions. + +best, +holger + + New Features ----------------------- @@ -20,31 +30,117 @@ New Features python -m pytest.main # on all pythons >= 2.5 import pytest ; pytest.main(args, plugins) - see http://pytest.org/2.0.0/invoke.html for details. + see http://pytest.org/2.0.0/usage.html for details. + +- new and better reporting information in assert expressions + which compare lists, sequences or strings. + + see http://pytest.org/2.0.0/assert.html for details. - new configuration through ini-files (setup.cfg or tox.ini recognized), for example:: [pytest] - norecursedirs = .hg _build - python_collect_funcprefix = test_ - python_collect_classprefix = Test + norecursedirs = .hg data* # don't ever recurse in such dirs + addopts = -x --pyargs # add these options by default see http://pytest.org/2.0.0/customize.html -- +- improved standard unittest support. For example you can now run + the tests of an installed 'unittest' package with py.test:: -Thanks to issue reporters, people asking questions, complaining and -generally to Ronny Pfannschmidt for his awesome help on many issues. + py.test --pyargs unittest -cheers, -holger krekel +- add a new "-q" option which decreases verbosity and prints a more + nose/unittest-style "dot" output. -Changes between 1.3.3 and 1.3.4 +Fixes +----------------------- + +- fix issue126 - introduce py.test.set_trace() to trace execution via + PDB during the running of tests even if capturing is ongoing. +- fix issue124 - make reporting more resilient against tests opening + files on filedescriptor 1 (stdout). +- fix issue109 - sibling conftest.py files will not be loaded. + (and Directory collectors cannot be customized anymore from a Directory's + conftest.py - this needs to happen at least one level up). +- fix issue88 (finding custom test nodes from command line arg) +- fix issue93 stdout/stderr is captured while importing conftest.py +- fix bug: unittest collected functions now also can have "pytestmark" + applied at class/module level + +Important Note on importing "pytest" versus "py.test" +------------------------------------------------------- + +The usual way in pre-2.0 times to use py.test in python code was +to import "py" and then e.g. use "py.test.raises" for the helper. +This remains valid and is not planned to be deprecated. However, +in most examples and internal code you'll find "import pytest" +and "pytest.raises" used as the recommended default way. + +(Incompatible) Removals +----------------------------- + +- py.test.config is now only available if you are in a test run. + +- the following (mostly already deprecated) functionality was removed: + - removed support for Module/Class/... collection node definitions + in conftest.py files. They will cause nothing special. + - removed support for calling the pre-1.0 collection API of "run()" and "join" + - removed reading option values from conftest.py files or env variables. + This can now be done much much better and easier through the ini-file + mechanism and the "addopts" entry in particular. + - removed the "disabled" attribute in test classes. Use the skipping + and pytestmark mechanism to skip or xfail a test class. + +- py.test.collect.Directory does not exist anymore and it + is not possible to provide an own "Directory" object. + If you have used this and don#t know what to do, get + in contact. We'll figure someting out. + + Note that pytest_collect_directory() is still called but + any return value will be ignored. This allows to keep + old code working that performed for example "py.test.skip()" + in collect() to prevent recursion into directory trees + if a certain dependency or command line option is missing. + + +More Detailed Changes between 1.3.4 and 2.0.0 ================================================== -- fix issue111: improve install documentation for windows -- fix issue119: fix custom collectability of __init__.py as a module -- fix issue116: --doctestmodules work with __init__.py files as well -- fix issue115: unify internal exception passthrough/catching/GeneratorExit -- fix issue118: new --tb=native for presenting cpython-standard exceptions +- pytest-2.0 is now its own package and depends on pylib-2.0 +- new ability: python -m pytest / python -m pytest.main ability +- new python invcation: pytest.main(args, plugins) to load + some custom plugins early. +- try harder to run unittest test suites in a more compatible manner + by deferring setup/teardown semantics to the unittest package. +- introduce a new way to set config options via ini-style files, + by default setup.cfg and tox.ini files are searched. The old + ways (certain environment variables, dynamic conftest.py reading + is removed). +- add a new "-q" option which decreases verbosity and prints a more + nose/unittest-style "dot" output. +- fix issue126 - introduce py.test.set_trace() to trace execution via + PDB during the running of tests even if capturing is ongoing. +- fix issue123 - new "python -m py.test" invocation for py.test + (requires Python 2.5 or above) +- fix issue124 - make reporting more resilient against tests opening + files on filedescriptor 1 (stdout). +- fix issue109 - sibling conftest.py files will not be loaded. + (and Directory collectors cannot be customized anymore from a Directory's + conftest.py - this needs to happen at least one level up). +- introduce (customizable) assertion failure representations and enhance + output on assertion failures for comparisons and other cases (Floris Bruynooghe) +- nose-plugin: pass through type-signature failures in setup/teardown + functions instead of not calling them (Ed Singleton) +- remove py.test.collect.Directory (follows from a major refactoring + and simplification of the collection process) +- majorly reduce py.test core code, shift function/python testing to own plugin +- fix issue88 (finding custom test nodes from command line arg) +- refine 'tmpdir' creation, will now create basenames better associated + with test names (thanks Ronny) +- "xpass" (unexpected pass) tests don't cause exitcode!=0 +- fix issue131 / issue60 - importing doctests in __init__ files used as namespace packages +- fix issue93 stdout/stderr is captured while importing conftest.py +- fix bug: unittest collected functions now also can have "pytestmark" + applied at class/module level diff --git a/doc/usage.txt b/doc/usage.txt index 38a0f3687..02607ee99 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -25,39 +25,18 @@ To stop the testing process after the first (N) failures:: py.test -x # stop after first failure py.test -maxfail=2 # stop after two failures -calling pytest from Python code ----------------------------------------------------- +specifying tests / selecting tests +--------------------------------------------------- -.. versionadded: 2.0 +Several test run options:: -You can invoke ``py.test`` from Python code directly:: + py.test test_mod.py # run tests in module + py.test somepath # run all tests below path + py.test -k string # only run tests whose names contain a string - pytest.main() +Import 'pkg' and use its filesystem location to find and run tests:: -this acts as if you would call "py.test" from the command line. -It will not raise ``SystemExit`` but return the exitcode instead. -You can pass in options and arguments:: - - pytest.main(['x', 'mytestdir']) - -or pass in a string:: - - pytest.main("-x mytestdir") - -You can specify additional plugins to ``pytest.main``:: - - # content of myinvoke.py - import pytest - class MyPlugin: - def pytest_addoption(self, parser): - raise pytest.UsageError("hi from our plugin") - - pytest.main(plugins=[MyPlugin()]) - -Running it will exit quickly:: - - $ python myinvoke.py - ERROR: hi from our plugin + py.test --testpkg=pypkg # run all tests found below directory of pypkg calling pytest through ``python -m pytest`` ----------------------------------------------------- @@ -162,4 +141,39 @@ for example ``-x`` if you only want to send one particular failure. Currently only pasting to the http://paste.pocoo.org service is implemented. +calling pytest from Python code +---------------------------------------------------- + +.. versionadded: 2.0 + +You can invoke ``py.test`` from Python code directly:: + + pytest.main() + +this acts as if you would call "py.test" from the command line. +It will not raise ``SystemExit`` but return the exitcode instead. +You can pass in options and arguments:: + + pytest.main(['x', 'mytestdir']) + +or pass in a string:: + + pytest.main("-x mytestdir") + +You can specify additional plugins to ``pytest.main``:: + + # content of myinvoke.py + import pytest + class MyPlugin: + def pytest_addoption(self, parser): + raise pytest.UsageError("hi from our plugin") + + pytest.main(plugins=[MyPlugin()]) + +Running it will exit quickly:: + + $ python myinvoke.py + ERROR: hi from our plugin + + .. include:: links.inc diff --git a/pytest/__init__.py b/pytest/__init__.py index 2ac1a43b8..98ad3b1bc 100644 --- a/pytest/__init__.py +++ b/pytest/__init__.py @@ -5,7 +5,7 @@ see http://pytest.org for documentation and details (c) Holger Krekel and others, 2004-2010 """ -__version__ = '2.0.0.dev19' +__version__ = '2.0.0.dev20' __all__ = ['config', 'cmdline'] diff --git a/pytest/plugin/python.py b/pytest/plugin/python.py index de9db73c7..17d94a9c9 100644 --- a/pytest/plugin/python.py +++ b/pytest/plugin/python.py @@ -9,8 +9,8 @@ cutdir = py.path.local(pytest.__file__).dirpath() def pytest_addoption(parser): - group = parser.getgroup("terminal reporting") - group._addoption('--funcargs', + group = parser.getgroup("general") + group.addoption('--funcargs', action="store_true", dest="showfuncargs", default=False, help="show available function arguments, sorted by plugin") diff --git a/pytest/plugin/session.py b/pytest/plugin/session.py index 8fa6442be..e54fbc1d8 100644 --- a/pytest/plugin/session.py +++ b/pytest/plugin/session.py @@ -31,6 +31,8 @@ def pytest_addoption(parser): group.addoption('--collectonly', action="store_true", dest="collectonly", help="only collect tests, don't execute them."), + group.addoption('--pyargs', action="store_true", + help="try to interpret all arguments as python packages.") group.addoption("--ignore", action="append", metavar="path", help="ignore path during collection (multi-allowed).") group.addoption('--confcutdir', dest="confcutdir", default=None, @@ -429,12 +431,29 @@ class Collection(FSCollector): ihook.pytest_collect_directory(path=path, parent=self) return True + def _tryconvertpyarg(self, x): + try: + mod = __import__(x, None, None, ['__doc__']) + except ImportError: + return x + p = py.path.local(mod.__file__) + if p.purebasename == "__init__": + p = p.dirpath() + return p + def _parsearg(self, arg): """ return (fspath, names) tuple after checking the file exists. """ + arg = str(arg) + if self.config.option.pyargs: + arg = self._tryconvertpyarg(arg) parts = str(arg).split("::") path = self.fspath.join(parts[0], abs=True) if not path.check(): - raise pytest.UsageError("file not found: %s" %(path,)) + if self.config.option.pyargs: + msg = "file or package not found: " + else: + msg = "file not found: " + raise pytest.UsageError(msg + arg) parts[0] = path return parts diff --git a/setup.py b/setup.py index 5a69ffce7..d559e9818 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def main(): name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.0.0.dev19', + version='2.0.0.dev20', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 20474ed6a..4d00517a3 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -309,3 +309,24 @@ class TestInvocationVariants: out, err = capsys.readouterr() assert "--myopt" in out + def test_cmdline_python_package(self, testdir): + path = testdir.mkpydir("tpkg") + path.join("test_hello.py").write("def test_hello(): pass") + path.join("test_world.py").write("def test_world(): pass") + result = testdir.runpytest("--pyargs", "tpkg") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + "*2 passed*" + ]) + result = testdir.runpytest("--pyargs", "tpkg.test_hello") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + "*1 passed*" + ]) + + def test_cmdline_python_package_not_exists(self, testdir): + result = testdir.runpytest("--pyargs", "tpkgwhatv") + assert result.ret + result.stderr.fnmatch_lines([ + "ERROR*file*or*package*not*found*", + ])