2 new commits in pytest:

https://bitbucket.org/hpk42/pytest/changeset/4d9f48622c63/
changeset:   4d9f48622c63
user:        hpk42
date:        2012-08-13 12:58:08
summary:     fix/update some docs to work with @pytest.factory instead of 
pytest_funcarg__ naming.
affected #:  4 files

diff -r 90a3b3d49cebb9b6484251b7c7f6df1c317305d9 -r 
4d9f48622c63733d4d67b436d40bdb14fb1ca037 doc/en/example/costlysetup/conftest.py
--- a/doc/en/example/costlysetup/conftest.py
+++ b/doc/en/example/costlysetup/conftest.py
@@ -1,10 +1,11 @@
 
-def pytest_funcarg__setup(request):
-    return request.cached_setup(
-        setup=lambda: CostlySetup(),
-        teardown=lambda costlysetup: costlysetup.finalize(),
-        scope="session",
-    )
+import pytest
+
+@pytest.factory("session")
+def setup(testcontext):
+    setup = CostlySetup()
+    testcontext.addfinalizer(setup.finalize)
+    return setup
 
 class CostlySetup:
     def __init__(self):


diff -r 90a3b3d49cebb9b6484251b7c7f6df1c317305d9 -r 
4d9f48622c63733d4d67b436d40bdb14fb1ca037 doc/en/example/multipython.py
--- a/doc/en/example/multipython.py
+++ b/doc/en/example/multipython.py
@@ -5,29 +5,14 @@
 import py, pytest
 
 pythonlist = ['python2.4', 'python2.5', 'python2.6', 'python2.7', 'python2.8']
+@pytest.factory(params=pythonlist)
+def python1(testcontext, tmpdir):
+    picklefile = tmpdir.join("data.pickle")
+    return Python(testcontext.param, picklefile)
 
-def pytest_generate_tests(metafunc):
-    # we parametrize all "python1" and "python2" arguments to iterate
-    # over the python interpreters of our list above - the actual
-    # setup and lookup of interpreters in the python1/python2 factories
-    # respectively.
-    for arg in metafunc.funcargnames:
-        if arg in ("python1", "python2"):
-            metafunc.parametrize(arg, pythonlist, indirect=True)
-
-@pytest.mark.parametrize("obj", [42, {}, {1:3},])
-def test_basic_objects(python1, python2, obj):
-    python1.dumps(obj)
-    python2.load_and_is_true("obj == %s" % obj)
-
-def pytest_funcarg__python1(request):
-    tmpdir = request.getfuncargvalue("tmpdir")
-    picklefile = tmpdir.join("data.pickle")
-    return Python(request.param, picklefile)
-
-def pytest_funcarg__python2(request):
-    python1 = request.getfuncargvalue("python1")
-    return Python(request.param, python1.picklefile)
+@pytest.factory(params=pythonlist)
+def python2(testcontext, python1):
+    return Python(testcontext.param, python1.picklefile)
 
 class Python:
     def __init__(self, version, picklefile):
@@ -58,3 +43,8 @@
         """ % (str(self.picklefile), expression)))
         print (loadfile)
         py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
+
+@pytest.mark.parametrize("obj", [42, {}, {1:3},])
+def test_basic_objects(python1, python2, obj):
+    python1.dumps(obj)
+    python2.load_and_is_true("obj == %s" % obj)


diff -r 90a3b3d49cebb9b6484251b7c7f6df1c317305d9 -r 
4d9f48622c63733d4d67b436d40bdb14fb1ca037 doc/en/faq.txt
--- a/doc/en/faq.txt
+++ b/doc/en/faq.txt
@@ -123,6 +123,11 @@
 source code and safely find all factory functions for
 the ``MYARG`` function argument.
 
+.. note::
+
+    With pytest-2.3 you can use the :ref:`@pytest.factory` decorator
+    to mark a function as a funcarg factory.  
+
 .. _`Convention over Configuration`: 
http://en.wikipedia.org/wiki/Convention_over_Configuration
 
 Can I yield multiple values from a funcarg factory function?
@@ -141,8 +146,12 @@
   policy - in real-world examples some combinations
   often should not run.
 
-Use the `pytest_generate_tests`_ hook to solve both issues
-and implement the `parametrization scheme of your choice`_.
+However, with pytest-2.3 you can use the :ref:`@pytest.factory` decorator
+and specify ``params`` so that all tests depending on the factory-created
+resource will run multiple times with different parameters.
+
+You can also use the `pytest_generate_tests`_ hook to 
+implement the `parametrization scheme of your choice`_.
 
 .. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests
 .. _`parametrization scheme of your choice`: 
http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/


diff -r 90a3b3d49cebb9b6484251b7c7f6df1c317305d9 -r 
4d9f48622c63733d4d67b436d40bdb14fb1ca037 doc/en/funcarg_compare.txt
--- a/doc/en/funcarg_compare.txt
+++ b/doc/en/funcarg_compare.txt
@@ -88,7 +88,7 @@
 sets.  pytest-2.3 introduces a decorator for use on the factory itself::
 
     @pytest.factory(params=["mysql", "pg"])
-    def pytest_funcarg__db(testcontext):
+    def db(testcontext):
         ... # use testcontext.param
 
 Here the factory will be invoked twice (with the respective "mysql" 
@@ -105,7 +105,7 @@
 Of course it's perfectly fine to combine parametrization and scoping::
 
     @pytest.factory(scope="session", params=["mysql", "pg"])
-    def pytest_funcarg__db(testcontext):
+    def db(testcontext):
         if testcontext.param == "mysql":
             db = MySQL()
         elif testcontext.param == "pg":
@@ -137,7 +137,9 @@
     def pytest_funcarg__db(request):
         ...
 
-It is recommended to use the resource decorator, however.
+
+But it is then not possible to define scoping and parametrization.
+It is thus recommended to use the factory decorator.
 
 
 solving per-session setup / the new @setup marker



https://bitbucket.org/hpk42/pytest/changeset/57b9e4d9bdb2/
changeset:   57b9e4d9bdb2
user:        hpk42
date:        2012-08-13 13:37:14
summary:     fix issue172 so that @pytest.setup marked setup_module/function... 
functions
are not called twice.  Also fix ordering to that broader scoped setup
functions are executed first.
affected #:  3 files

diff -r 4d9f48622c63733d4d67b436d40bdb14fb1ca037 -r 
57b9e4d9bdb29039856691c16a2d7b5696d0eb89 CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
 Changes between 2.2.4 and 2.3.0.dev
 -----------------------------------
 
+- fix issue172 duplicate call of pytest.setup-decoratored setup_module
+  functions
 - fix junitxml=path construction so that if tests change the
   current working directory and the path is a relative path
   it is constructed correctly from the original current working dir.


diff -r 4d9f48622c63733d4d67b436d40bdb14fb1ca037 -r 
57b9e4d9bdb29039856691c16a2d7b5696d0eb89 _pytest/python.py
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -363,24 +363,26 @@
         return mod
 
     def setup(self):
-        if hasattr(self.obj, 'setup_module'):
+        setup_module = xunitsetup(self.obj, "setup_module")
+        if setup_module is not None:
             #XXX: nose compat hack, move to nose plugin
             # if it takes a positional arg, its probably a pytest style one
             # so we pass the current module object
-            if inspect.getargspec(self.obj.setup_module)[0]:
-                self.obj.setup_module(self.obj)
+            if inspect.getargspec(setup_module)[0]:
+                setup_module(self.obj)
             else:
-                self.obj.setup_module()
+                setup_module()
 
     def teardown(self):
-        if hasattr(self.obj, 'teardown_module'):
+        teardown_module = xunitsetup(self.obj, 'teardown_module')
+        if teardown_module is not None:
             #XXX: nose compat hack, move to nose plugin
             # if it takes a positional arg, its probably a py.test style one
             # so we pass the current module object
-            if inspect.getargspec(self.obj.teardown_module)[0]:
-                self.obj.teardown_module(self.obj)
+            if inspect.getargspec(teardown_module)[0]:
+                teardown_module(self.obj)
             else:
-                self.obj.teardown_module()
+                teardown_module()
 
 class Class(PyCollector):
     """ Collector for test methods. """
@@ -388,14 +390,14 @@
         return [self._getcustomclass("Instance")(name="()", parent=self)]
 
     def setup(self):
-        setup_class = getattr(self.obj, 'setup_class', None)
+        setup_class = xunitsetup(self.obj, 'setup_class')
         if setup_class is not None:
             setup_class = getattr(setup_class, 'im_func', setup_class)
             setup_class = getattr(setup_class, '__func__', setup_class)
             setup_class(self.obj)
 
     def teardown(self):
-        teardown_class = getattr(self.obj, 'teardown_class', None)
+        teardown_class = xunitsetup(self.obj, 'teardown_class')
         if teardown_class is not None:
             teardown_class = getattr(teardown_class, 'im_func', teardown_class)
             teardown_class = getattr(teardown_class, '__func__', 
teardown_class)
@@ -431,7 +433,7 @@
             name = 'setup_method'
         else:
             name = 'setup_function'
-        setup_func_or_method = getattr(obj, name, None)
+        setup_func_or_method = xunitsetup(obj, name)
         if setup_func_or_method is not None:
             setup_func_or_method(self.obj)
 
@@ -442,7 +444,7 @@
         else:
             name = 'teardown_function'
         obj = self.parent.obj
-        teardown_func_or_meth = getattr(obj, name, None)
+        teardown_func_or_meth = xunitsetup(obj, name)
         if teardown_func_or_meth is not None:
             teardown_func_or_meth(self.obj)
 
@@ -1338,6 +1340,7 @@
             if nodeid.startswith(setupcall.baseid):
                 l.append(setupcall)
                 allargnames.update(setupcall.funcargnames)
+        l.sort(key=lambda x: x.scopenum)
         return l, allargnames
 
 
@@ -1479,6 +1482,7 @@
         self.func = func
         self.funcargnames = getfuncargnames(func)
         self.scope = scope
+        self.scopenum = scopes.index(scope)
         self.active = False
         self._finalizer = []
 
@@ -1595,3 +1599,9 @@
     #            argparams.append(key)
     return argparams
 
+
+def xunitsetup(obj, name):
+    meth = getattr(obj, name, None)
+    if meth is not None:
+        if not hasattr(meth, "_pytestsetup"):
+            return meth


diff -r 4d9f48622c63733d4d67b436d40bdb14fb1ca037 -r 
57b9e4d9bdb29039856691c16a2d7b5696d0eb89 testing/test_python.py
--- a/testing/test_python.py
+++ b/testing/test_python.py
@@ -1874,6 +1874,28 @@
         l = config._conftest.getconftestmodules(p)[0].l
         assert l == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2
 
+    def test_setup_scope_ordering(self, testdir):
+        testdir.makepyfile("""
+            import pytest
+            l = []
+            @pytest.setup(scope="function")
+            def fappend2():
+                l.append(2)
+            @pytest.setup(scope="class")
+            def classappend3():
+                l.append(3)
+            @pytest.setup(scope="module")
+            def mappend():
+                l.append(1)
+
+            class TestHallo:
+                def test_method(self):
+                    assert l == [1,3,2]
+        """)
+        reprec = testdir.inline_run()
+        reprec.assertoutcome(passed=1)
+
+
 class TestFuncargMarker:
     def test_parametrize(self, testdir):
         testdir.makepyfile("""
@@ -2404,3 +2426,33 @@
         """)
         reprec = testdir.inline_run()
         reprec.assertoutcome(passed=2)
+
+def test_setupdecorator_and_xunit(testdir):
+    testdir.makepyfile("""
+        import pytest
+        l = []
+        @pytest.setup(scope='module')
+        def setup_module():
+            l.append("module")
+        @pytest.setup()
+        def setup_function():
+            l.append("function")
+
+        def test_func():
+            pass
+
+        class TestClass:
+            @pytest.setup(scope="class")
+            def setup_class(self):
+                l.append("class")
+            @pytest.setup()
+            def setup_method(self):
+                l.append("method")
+            def test_method(self):
+                pass
+        def test_all():
+            assert l == ["module", "function", "class",
+                         "function", "method", "function"]
+    """)
+    reprec = testdir.inline_run()
+    reprec.assertoutcome(passed=3)

Repository URL: https://bitbucket.org/hpk42/pytest/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
py-svn mailing list
py-svn@codespeak.net
http://codespeak.net/mailman/listinfo/py-svn

Reply via email to