[Pytest-commit] commit/pytest: hpk42: fix issue436: improved finding of initial conftest files from command

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Wed Apr 2 11:52:54 CEST 2014


1 new commit in pytest:

https://bitbucket.org/hpk42/pytest/commits/083d8d0b065f/
Changeset:   083d8d0b065f
User:        hpk42
Date:        2014-04-02 11:29:23
Summary:     fix issue436: improved finding of initial conftest files from command
line arguments by using the result of parse_known_args rather than
the previous flaky heuristics.  Thanks Marc Abramowitz for tests
and initial fixing approaches in this area.
Affected #:  5 files

diff -r 8d04808c1e928179c11974741428a418a9378d37 -r 083d8d0b065f11860fc1ec4edb50480b6ee50b35 CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,11 @@
 - change skips into warnings for test classes with an __init__ and
   callables in test modules which look like a test but are not functions.
 
+- fix issue436: improved finding of initial conftest files from command
+  line arguments by using the result of parse_known_args rather than
+  the previous flaky heuristics.  Thanks Marc Abramowitz for tests
+  and initial fixing approaches in this area.
+
 - fix issue #479: properly handle nose/unittest(2) SkipTest exceptions
   during collection/loading of test modules.  Thanks to Marc Schlaich
   for the complete PR.

diff -r 8d04808c1e928179c11974741428a418a9378d37 -r 083d8d0b065f11860fc1ec4edb50480b6ee50b35 _pytest/capture.py
--- a/_pytest/capture.py
+++ b/_pytest/capture.py
@@ -31,7 +31,7 @@
 
 @pytest.mark.tryfirst
 def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
-    ns = parser.parse_known_args(args)
+    ns = early_config.known_args_namespace
     pluginmanager = early_config.pluginmanager
     if ns.capture == "no":
         return

diff -r 8d04808c1e928179c11974741428a418a9378d37 -r 083d8d0b065f11860fc1ec4edb50480b6ee50b35 _pytest/config.py
--- a/_pytest/config.py
+++ b/_pytest/config.py
@@ -449,38 +449,27 @@
     """ the single place for accessing values and interacting
         towards conftest modules from pytest objects.
     """
-    def __init__(self, onimport=None, confcutdir=None):
+    def __init__(self, onimport=None):
         self._path2confmods = {}
         self._onimport = onimport
         self._conftestpath2mod = {}
-        self._confcutdir = confcutdir
+        self._confcutdir = None
 
-    def setinitial(self, args):
-        """ try to find a first anchor path for looking up global values
-            from conftests. This function is usually called _before_
-            argument parsing.  conftest files may add command line options
-            and we thus have no completely safe way of determining
-            which parts of the arguments are actually related to options
-            and which are file system paths.  We just try here to get
-            bootstrapped ...
+    def setinitial(self, namespace):
+        """ load initial conftest files given a preparsed "namespace".
+            As conftest files may add their own command line options
+            which have arguments ('--my-opt somepath') we might get some
+            false positives.  All builtin and 3rd party plugins will have
+            been loaded, however, so common options will not confuse our logic
+            here.
         """
         current = py.path.local()
-        opt = '--confcutdir'
-        for i in range(len(args)):
-            opt1 = str(args[i])
-            if opt1.startswith(opt):
-                if opt1 == opt:
-                    if len(args) > i:
-                        p = current.join(args[i+1], abs=True)
-                elif opt1.startswith(opt + "="):
-                    p = current.join(opt1[len(opt)+1:], abs=1)
-                self._confcutdir = p
-                break
+        self._confcutdir = current.join(namespace.confcutdir, abs=True) \
+                                if namespace.confcutdir else None
+        testpaths = namespace.file_or_dir
         foundanchor = False
-        for arg in args:
-            if hasattr(arg, 'startswith') and arg.startswith("--"):
-                continue
-            anchor = current.join(arg, abs=1)
+        for path in testpaths:
+            anchor = current.join(path, abs=1)
             if exists(anchor): # we found some file object
                 self._try_load_conftest(anchor)
                 foundanchor = True
@@ -676,8 +665,8 @@
         plugins += self._conftest.getconftestmodules(fspath)
         return plugins
 
-    def pytest_load_initial_conftests(self, parser, args):
-        self._conftest.setinitial(args)
+    def pytest_load_initial_conftests(self, early_config):
+        self._conftest.setinitial(early_config.known_args_namespace)
     pytest_load_initial_conftests.trylast = True
 
     def _initini(self, args):
@@ -693,6 +682,7 @@
         self.pluginmanager.consider_preparse(args)
         self.pluginmanager.consider_setuptools_entrypoints()
         self.pluginmanager.consider_env()
+        self.known_args_namespace = self._parser.parse_known_args(args)
         self.hook.pytest_load_initial_conftests(early_config=self,
             args=args, parser=self._parser)
 
@@ -710,7 +700,6 @@
 
     def parse(self, args):
         # parse given cmdline arguments into this config object.
-        # Note that this can only be called once per testing process.
         assert not hasattr(self, 'args'), (
                 "can only parse cmdline args at most once per Config object")
         self._origargs = args

diff -r 8d04808c1e928179c11974741428a418a9378d37 -r 083d8d0b065f11860fc1ec4edb50480b6ee50b35 testing/test_config.py
--- a/testing/test_config.py
+++ b/testing/test_config.py
@@ -148,7 +148,7 @@
         assert config.getvalue('x') == 1
         config.option.x = 2
         assert config.getvalue('x') == 2
-        config = testdir.parseconfig([str(o)])
+        config = testdir.parseconfig(str(o))
         assert config.getvalue('x') == 1
 
     def test_getconftest_pathlist(self, testdir, tmpdir):

diff -r 8d04808c1e928179c11974741428a418a9378d37 -r 083d8d0b065f11860fc1ec4edb50480b6ee50b35 testing/test_conftest.py
--- a/testing/test_conftest.py
+++ b/testing/test_conftest.py
@@ -20,19 +20,26 @@
 
 def ConftestWithSetinitial(path):
     conftest = Conftest()
-    conftest.setinitial([path])
+    conftest_setinitial(conftest, [path])
     return conftest
 
+def conftest_setinitial(conftest, args, confcutdir=None):
+    class Namespace:
+        def __init__(self):
+            self.file_or_dir = args
+            self.confcutdir = str(confcutdir)
+    conftest.setinitial(Namespace())
+
 class TestConftestValueAccessGlobal:
     def test_basic_init(self, basedir):
         conftest = Conftest()
-        conftest.setinitial([basedir.join("adir")])
+        conftest_setinitial(conftest, [basedir.join("adir")])
         assert conftest.rget("a") == 1
 
     def test_onimport(self, basedir):
         l = []
         conftest = Conftest(onimport=l.append)
-        conftest.setinitial([basedir.join("adir"),
+        conftest_setinitial(conftest, [basedir.join("adir"),
             '--confcutdir=%s' % basedir])
         assert len(l) == 1
         assert conftest.rget("a") == 1
@@ -99,13 +106,13 @@
     tmpdir.ensure("adir-1.0/__init__.py")
     ConftestWithSetinitial(tmpdir.join("adir-1.0", "b"))
 
-def test_doubledash_not_considered(testdir):
+def test_doubledash_considered(testdir):
     conf = testdir.mkdir("--option")
     conf.join("conftest.py").ensure()
     conftest = Conftest()
-    conftest.setinitial([conf.basename, conf.basename])
+    conftest_setinitial(conftest, [conf.basename, conf.basename])
     l = conftest.getconftestmodules(None)
-    assert len(l) == 0
+    assert len(l) == 1
 
 def test_issue151_load_all_conftests(testdir):
     names = "code proj src".split()
@@ -114,7 +121,7 @@
         p.ensure("conftest.py")
 
     conftest = Conftest()
-    conftest.setinitial(names)
+    conftest_setinitial(conftest, names)
     d = list(conftest._conftestpath2mod.values())
     assert len(d) == len(names)
 
@@ -142,8 +149,8 @@
 def test_conftestcutdir(testdir):
     conf = testdir.makeconftest("")
     p = testdir.mkdir("x")
-    conftest = Conftest(confcutdir=p)
-    conftest.setinitial([testdir.tmpdir])
+    conftest = Conftest()
+    conftest_setinitial(conftest, [testdir.tmpdir], confcutdir=p)
     l = conftest.getconftestmodules(p)
     assert len(l) == 0
     l = conftest.getconftestmodules(conf.dirpath())
@@ -160,34 +167,18 @@
 
 def test_conftestcutdir_inplace_considered(testdir):
     conf = testdir.makeconftest("")
-    conftest = Conftest(confcutdir=conf.dirpath())
-    conftest.setinitial([conf.dirpath()])
+    conftest = Conftest()
+    conftest_setinitial(conftest, [conf.dirpath()], confcutdir=conf.dirpath())
     l = conftest.getconftestmodules(conf.dirpath())
     assert len(l) == 1
     assert l[0].__file__.startswith(str(conf))
 
-def test_setinitial_confcut(testdir):
-    conf = testdir.makeconftest("")
-    sub = testdir.mkdir("sub")
-    sub.chdir()
-    for opts in (["--confcutdir=%s" % sub, sub],
-                [sub, "--confcutdir=%s" % sub],
-                ["--confcutdir=.", sub],
-                [sub, "--confcutdir", sub],
-                [str(sub), "--confcutdir", "."],
-    ):
-        conftest = Conftest()
-        conftest.setinitial(opts)
-        assert conftest._confcutdir == sub
-        assert conftest.getconftestmodules(sub) == []
-        assert conftest.getconftestmodules(conf.dirpath()) == []
-
 @pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
 def test_setinitial_conftest_subdirs(testdir, name):
     sub = testdir.mkdir(name)
     subconftest = sub.ensure("conftest.py")
     conftest = Conftest()
-    conftest.setinitial([sub.dirpath(), '--confcutdir=%s' % testdir.tmpdir])
+    conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
     if name not in ('whatever', '.dotdir'):
         assert  subconftest in conftest._conftestpath2mod
         assert len(conftest._conftestpath2mod) == 1
@@ -205,6 +196,26 @@
     result = testdir.runpytest("-h", "--confcutdir=%s" % x, x)
     result.stdout.fnmatch_lines(["*--xyz*"])
 
+def test_conftest_existing_resultlog(testdir):
+    x = testdir.mkdir("tests")
+    x.join("conftest.py").write(py.code.Source("""
+        def pytest_addoption(parser):
+            parser.addoption("--xyz", action="store_true")
+    """))
+    testdir.makefile(ext=".log", result="")  # Writes result.log
+    result = testdir.runpytest("-h", "--resultlog", "result.log")
+    result.stdout.fnmatch_lines(["*--xyz*"])
+
+def test_conftest_existing_junitxml(testdir):
+    x = testdir.mkdir("tests")
+    x.join("conftest.py").write(py.code.Source("""
+        def pytest_addoption(parser):
+            parser.addoption("--xyz", action="store_true")
+    """))
+    testdir.makefile(ext=".xml", junit="")  # Writes junit.xml
+    result = testdir.runpytest("-h", "--junitxml", "junit.xml")
+    result.stdout.fnmatch_lines(["*--xyz*"])
+
 def test_conftest_import_order(testdir, monkeypatch):
     ct1 = testdir.makeconftest("")
     sub = testdir.mkdir("sub")

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.


More information about the pytest-commit mailing list