229 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
| from __future__ import absolute_import, division, print_function
 | |
| import os
 | |
| 
 | |
| import _pytest._code
 | |
| import py
 | |
| import pytest
 | |
| from _pytest.nodes import Node, Item, FSCollector
 | |
| from _pytest.resultlog import generic_path, ResultLog, \
 | |
|     pytest_configure, pytest_unconfigure
 | |
| 
 | |
| 
 | |
| def test_generic_path(testdir):
 | |
|     from _pytest.main import Session
 | |
|     config = testdir.parseconfig()
 | |
|     session = Session(config)
 | |
|     p1 = Node('a', config=config, session=session, nodeid='a')
 | |
|     # assert p1.fspath is None
 | |
|     p2 = Node('B', parent=p1)
 | |
|     p3 = Node('()', parent=p2)
 | |
|     item = Item('c', parent=p3)
 | |
| 
 | |
|     res = generic_path(item)
 | |
|     assert res == 'a.B().c'
 | |
| 
 | |
|     p0 = FSCollector('proj/test', config=config, session=session)
 | |
|     p1 = FSCollector('proj/test/a', parent=p0)
 | |
|     p2 = Node('B', parent=p1)
 | |
|     p3 = Node('()', parent=p2)
 | |
|     p4 = Node('c', parent=p3)
 | |
|     item = Item('[1]', parent=p4)
 | |
| 
 | |
|     res = generic_path(item)
 | |
|     assert res == 'test/a:B().c[1]'
 | |
| 
 | |
| 
 | |
| def test_write_log_entry():
 | |
|     reslog = ResultLog(None, None)
 | |
|     reslog.logfile = py.io.TextIO()
 | |
|     reslog.write_log_entry('name', '.', '')
 | |
|     entry = reslog.logfile.getvalue()
 | |
|     assert entry[-1] == '\n'
 | |
|     entry_lines = entry.splitlines()
 | |
|     assert len(entry_lines) == 1
 | |
|     assert entry_lines[0] == '. name'
 | |
| 
 | |
|     reslog.logfile = py.io.TextIO()
 | |
|     reslog.write_log_entry('name', 's', 'Skipped')
 | |
|     entry = reslog.logfile.getvalue()
 | |
|     assert entry[-1] == '\n'
 | |
|     entry_lines = entry.splitlines()
 | |
|     assert len(entry_lines) == 2
 | |
|     assert entry_lines[0] == 's name'
 | |
|     assert entry_lines[1] == ' Skipped'
 | |
| 
 | |
|     reslog.logfile = py.io.TextIO()
 | |
|     reslog.write_log_entry('name', 's', 'Skipped\n')
 | |
|     entry = reslog.logfile.getvalue()
 | |
|     assert entry[-1] == '\n'
 | |
|     entry_lines = entry.splitlines()
 | |
|     assert len(entry_lines) == 2
 | |
|     assert entry_lines[0] == 's name'
 | |
|     assert entry_lines[1] == ' Skipped'
 | |
| 
 | |
|     reslog.logfile = py.io.TextIO()
 | |
|     longrepr = ' tb1\n tb 2\nE tb3\nSome Error'
 | |
|     reslog.write_log_entry('name', 'F', longrepr)
 | |
|     entry = reslog.logfile.getvalue()
 | |
|     assert entry[-1] == '\n'
 | |
|     entry_lines = entry.splitlines()
 | |
|     assert len(entry_lines) == 5
 | |
|     assert entry_lines[0] == 'F name'
 | |
|     assert entry_lines[1:] == [' ' + line for line in longrepr.splitlines()]
 | |
| 
 | |
| 
 | |
| class TestWithFunctionIntegration(object):
 | |
|     # XXX (hpk) i think that the resultlog plugin should
 | |
|     # provide a Parser object so that one can remain
 | |
|     # ignorant regarding formatting details.
 | |
|     def getresultlog(self, testdir, arg):
 | |
|         resultlog = testdir.tmpdir.join("resultlog")
 | |
|         testdir.plugins.append("resultlog")
 | |
|         args = ["--resultlog=%s" % resultlog] + [arg]
 | |
|         testdir.runpytest(*args)
 | |
|         return [x for x in resultlog.readlines(cr=0) if x]
 | |
| 
 | |
|     def test_collection_report(self, testdir):
 | |
|         ok = testdir.makepyfile(test_collection_ok="")
 | |
|         fail = testdir.makepyfile(test_collection_fail="XXX")
 | |
|         lines = self.getresultlog(testdir, ok)
 | |
|         assert not lines
 | |
| 
 | |
|         lines = self.getresultlog(testdir, fail)
 | |
|         assert lines
 | |
|         assert lines[0].startswith("F ")
 | |
|         assert lines[0].endswith("test_collection_fail.py"), lines[0]
 | |
|         for x in lines[1:]:
 | |
|             assert x.startswith(" ")
 | |
|         assert "XXX" in "".join(lines[1:])
 | |
| 
 | |
|     def test_log_test_outcomes(self, testdir):
 | |
|         mod = testdir.makepyfile(test_mod="""
 | |
|             import pytest
 | |
|             def test_pass(): pass
 | |
|             def test_skip(): pytest.skip("hello")
 | |
|             def test_fail(): raise ValueError("FAIL")
 | |
| 
 | |
|             @pytest.mark.xfail
 | |
|             def test_xfail(): raise ValueError("XFAIL")
 | |
|             @pytest.mark.xfail
 | |
|             def test_xpass(): pass
 | |
| 
 | |
|         """)
 | |
|         lines = self.getresultlog(testdir, mod)
 | |
|         assert len(lines) >= 3
 | |
|         assert lines[0].startswith(". ")
 | |
|         assert lines[0].endswith("test_pass")
 | |
|         assert lines[1].startswith("s "), lines[1]
 | |
|         assert lines[1].endswith("test_skip")
 | |
|         assert lines[2].find("hello") != -1
 | |
| 
 | |
|         assert lines[3].startswith("F ")
 | |
|         assert lines[3].endswith("test_fail")
 | |
|         tb = "".join(lines[4:8])
 | |
|         assert tb.find('raise ValueError("FAIL")') != -1
 | |
| 
 | |
|         assert lines[8].startswith('x ')
 | |
|         tb = "".join(lines[8:14])
 | |
|         assert tb.find('raise ValueError("XFAIL")') != -1
 | |
| 
 | |
|         assert lines[14].startswith('X ')
 | |
|         assert len(lines) == 15
 | |
| 
 | |
|     @pytest.mark.parametrize("style", ("native", "long", "short"))
 | |
|     def test_internal_exception(self, style):
 | |
|         # they are produced for example by a teardown failing
 | |
|         # at the end of the run or a failing hook invocation
 | |
|         try:
 | |
|             raise ValueError
 | |
|         except ValueError:
 | |
|             excinfo = _pytest._code.ExceptionInfo()
 | |
|         reslog = ResultLog(None, py.io.TextIO())
 | |
|         reslog.pytest_internalerror(excinfo.getrepr(style=style))
 | |
|         entry = reslog.logfile.getvalue()
 | |
|         entry_lines = entry.splitlines()
 | |
| 
 | |
|         assert entry_lines[0].startswith('! ')
 | |
|         if style != "native":
 | |
|             assert os.path.basename(__file__)[:-9] in entry_lines[0]  # .pyc/class
 | |
|         assert entry_lines[-1][0] == ' '
 | |
|         assert 'ValueError' in entry
 | |
| 
 | |
| 
 | |
| def test_generic(testdir, LineMatcher):
 | |
|     testdir.plugins.append("resultlog")
 | |
|     testdir.makepyfile("""
 | |
|         import pytest
 | |
|         def test_pass():
 | |
|             pass
 | |
|         def test_fail():
 | |
|             assert 0
 | |
|         def test_skip():
 | |
|             pytest.skip("")
 | |
|         @pytest.mark.xfail
 | |
|         def test_xfail():
 | |
|             assert 0
 | |
|         @pytest.mark.xfail(run=False)
 | |
|         def test_xfail_norun():
 | |
|             assert 0
 | |
|     """)
 | |
|     testdir.runpytest("--resultlog=result.log")
 | |
|     lines = testdir.tmpdir.join("result.log").readlines(cr=0)
 | |
|     LineMatcher(lines).fnmatch_lines([
 | |
|         ". *:test_pass",
 | |
|         "F *:test_fail",
 | |
|         "s *:test_skip",
 | |
|         "x *:test_xfail",
 | |
|         "x *:test_xfail_norun",
 | |
|     ])
 | |
| 
 | |
| 
 | |
| def test_makedir_for_resultlog(testdir, LineMatcher):
 | |
|     """--resultlog should automatically create directories for the log file"""
 | |
|     testdir.plugins.append("resultlog")
 | |
|     testdir.makepyfile("""
 | |
|         import pytest
 | |
|         def test_pass():
 | |
|             pass
 | |
|     """)
 | |
|     testdir.runpytest("--resultlog=path/to/result.log")
 | |
|     lines = testdir.tmpdir.join("path/to/result.log").readlines(cr=0)
 | |
|     LineMatcher(lines).fnmatch_lines([
 | |
|         ". *:test_pass",
 | |
|     ])
 | |
| 
 | |
| 
 | |
| def test_no_resultlog_on_slaves(testdir):
 | |
|     config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
 | |
| 
 | |
|     assert not hasattr(config, '_resultlog')
 | |
|     pytest_configure(config)
 | |
|     assert hasattr(config, '_resultlog')
 | |
|     pytest_unconfigure(config)
 | |
|     assert not hasattr(config, '_resultlog')
 | |
| 
 | |
|     config.slaveinput = {}
 | |
|     pytest_configure(config)
 | |
|     assert not hasattr(config, '_resultlog')
 | |
|     pytest_unconfigure(config)
 | |
|     assert not hasattr(config, '_resultlog')
 | |
| 
 | |
| 
 | |
| def test_failure_issue380(testdir):
 | |
|     testdir.makeconftest("""
 | |
|         import pytest
 | |
|         class MyCollector(pytest.File):
 | |
|             def collect(self):
 | |
|                 raise ValueError()
 | |
|             def repr_failure(self, excinfo):
 | |
|                 return "somestring"
 | |
|         def pytest_collect_file(path, parent):
 | |
|             return MyCollector(parent=parent, fspath=path)
 | |
|     """)
 | |
|     testdir.makepyfile("""
 | |
|         def test_func():
 | |
|             pass
 | |
|     """)
 | |
|     result = testdir.runpytest("--resultlog=log")
 | |
|     assert result.ret == 2
 |