fix capturing to be more careful during teardown when a setup never happened (due to e.g. an error in user-provided runtest_setup code)
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									77b640d1b7
								
							
						
					
					
						commit
						9d01975c78
					
				| 
						 | 
					@ -9,6 +9,9 @@ Changes between 1.X and 1.1.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- new "pytestconfig" funcarg allows access to test config object
 | 
					- new "pytestconfig" funcarg allows access to test config object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- robustify capturing to survive if custom pytest_runtest_setup 
 | 
				
			||||||
 | 
					  code failed and prevented the capturing setup code from running. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- make py.test.* helpers provided by default plugins visible early -
 | 
					- make py.test.* helpers provided by default plugins visible early -
 | 
				
			||||||
  works transparently both for pydoc and for interactive sessions
 | 
					  works transparently both for pydoc and for interactive sessions
 | 
				
			||||||
  which will regularly see e.g. py.test.mark and py.test.importorskip. 
 | 
					  which will regularly see e.g. py.test.mark and py.test.importorskip. 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,16 +161,20 @@ class CaptureManager:
 | 
				
			||||||
                cap.resume()
 | 
					                cap.resume()
 | 
				
			||||||
        self._capturing = method 
 | 
					        self._capturing = method 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def suspendcapture(self):
 | 
					    def suspendcapture(self, item=None):
 | 
				
			||||||
        self.deactivate_funcargs()
 | 
					        self.deactivate_funcargs()
 | 
				
			||||||
        method = self._capturing
 | 
					        if hasattr(self, '_capturing'):
 | 
				
			||||||
        if method != "no":
 | 
					            method = self._capturing
 | 
				
			||||||
            cap = self._method2capture[method]
 | 
					            if method != "no":
 | 
				
			||||||
            outerr = cap.suspend()
 | 
					                cap = self._method2capture[method]
 | 
				
			||||||
        else:
 | 
					                outerr = cap.suspend()
 | 
				
			||||||
            outerr = "", ""
 | 
					            else:
 | 
				
			||||||
        del self._capturing
 | 
					                outerr = "", ""
 | 
				
			||||||
        return outerr 
 | 
					            del self._capturing
 | 
				
			||||||
 | 
					            if item:
 | 
				
			||||||
 | 
					                outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
 | 
				
			||||||
 | 
					            return outerr 
 | 
				
			||||||
 | 
					        return "", ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def activate_funcargs(self, pyfuncitem):
 | 
					    def activate_funcargs(self, pyfuncitem):
 | 
				
			||||||
        if not hasattr(pyfuncitem, 'funcargs'):
 | 
					        if not hasattr(pyfuncitem, 'funcargs'):
 | 
				
			||||||
| 
						 | 
					@ -210,9 +214,6 @@ class CaptureManager:
 | 
				
			||||||
    def pytest_runtest_teardown(self, item):
 | 
					    def pytest_runtest_teardown(self, item):
 | 
				
			||||||
        self.resumecapture_item(item)
 | 
					        self.resumecapture_item(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_runtest_teardown(self, item):
 | 
					 | 
				
			||||||
        self.resumecapture_item(item)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def pytest__teardown_final(self, __multicall__, session):
 | 
					    def pytest__teardown_final(self, __multicall__, session):
 | 
				
			||||||
        method = self._getmethod(session.config, None)
 | 
					        method = self._getmethod(session.config, None)
 | 
				
			||||||
        self.resumecapture(method)
 | 
					        self.resumecapture(method)
 | 
				
			||||||
| 
						 | 
					@ -231,8 +232,7 @@ class CaptureManager:
 | 
				
			||||||
    def pytest_runtest_makereport(self, __multicall__, item, call):
 | 
					    def pytest_runtest_makereport(self, __multicall__, item, call):
 | 
				
			||||||
        self.deactivate_funcargs()
 | 
					        self.deactivate_funcargs()
 | 
				
			||||||
        rep = __multicall__.execute()
 | 
					        rep = __multicall__.execute()
 | 
				
			||||||
        outerr = self.suspendcapture()
 | 
					        outerr = self.suspendcapture(item)
 | 
				
			||||||
        outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
 | 
					 | 
				
			||||||
        if not rep.passed:
 | 
					        if not rep.passed:
 | 
				
			||||||
            addouterr(rep, outerr)
 | 
					            addouterr(rep, outerr)
 | 
				
			||||||
        if not rep.passed or rep.when == "teardown":
 | 
					        if not rep.passed or rep.when == "teardown":
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,3 +379,15 @@ class TestCaptureFuncarg:
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
        assert result.ret == 2
 | 
					        assert result.ret == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_setup_failure_does_not_kill_capturing(testdir):
 | 
				
			||||||
 | 
					    sub1 = testdir.mkpydir("sub1")
 | 
				
			||||||
 | 
					    sub1.join("conftest.py").write(py.code.Source("""
 | 
				
			||||||
 | 
					        def pytest_runtest_setup(item):
 | 
				
			||||||
 | 
					            raise ValueError(42)
 | 
				
			||||||
 | 
					    """))
 | 
				
			||||||
 | 
					    sub1.join("test_mod.py").write("def test_func1(): pass")
 | 
				
			||||||
 | 
					    result = testdir.runpytest(testdir.tmpdir, '--traceconfig')
 | 
				
			||||||
 | 
					    result.stdout.fnmatch_lines([
 | 
				
			||||||
 | 
					        "*ValueError(42)*",
 | 
				
			||||||
 | 
					        "*1 error*"
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue