ISSUE:
exception serialization should include chained exceptions
given some simple tests:
```
def test_chained_exception_with_from():
    try:
        try:
            raise ValueError(11)
        except Exception as e1:
            raise ValueError(12) from e1
    except Exception as e2:
        raise ValueError(13) from e2


def test_chained_exception_without_from():
    try:
        try:
            raise ValueError(21)
        except Exception:
            raise ValueError(22)
    except Exception:
        raise ValueError(23)
```
when run without xdist it displays whole exception trace nicely :
```
================ FAILURES ==========================
__________________________ test_chained_exception_with_from _______________________

    def test_chained_exception_with_from():
        try:
            try:
>               raise ValueError(11)
E               ValueError: 11

basic/test_basic.py:80: ValueError

The above exception was the direct cause of the following exception:

    def test_chained_exception_with_from():
        try:
            try:
                raise ValueError(11)
            except Exception as e1:
>               raise ValueError(12) from e1
E               ValueError: 12

basic/test_basic.py:82: ValueError

The above exception was the direct cause of the following exception:

    def test_chained_exception_with_from():
        try:
            try:
                raise ValueError(11)
            except Exception as e1:
                raise ValueError(12) from e1
        except Exception as e2:
>           raise ValueError(13) from e2
E           ValueError: 13

basic/test_basic.py:84: ValueError


_____________________ test_chained_exception_without_from ____________________________

    def test_chained_exception_without_from():
        try:
            try:
>               raise ValueError(21)
E               ValueError: 21

basic/test_basic.py:90: ValueError

During handling of the above exception, another exception occurred:

    def test_chained_exception_without_from():
        try:
            try:
                raise ValueError(21)
            except Exception:
>               raise ValueError(22)
E               ValueError: 22

basic/test_basic.py:92: ValueError

During handling of the above exception, another exception occurred:

    def test_chained_exception_without_from():
        try:
            try:
                raise ValueError(21)
            except Exception:
                raise ValueError(22)
        except Exception:
>           raise ValueError(23)
E           ValueError: 23

basic/test_basic.py:94: ValueError

```

but when run with xdist (`-n auto`), it just displays the last one:
```
============ FAILURES ================
_____________ test_chained_exception_with_from _______________________________
[gw0] linux -- Python 3.6.7 /home/mulawa/developement/omcp/has/test/py/.tox/sct/bin/python3.6

    def test_chained_exception_with_from():
        try:
            try:
                raise ValueError(11)
            except Exception as e1:
                raise ValueError(12) from e1
        except Exception as e2:
>           raise ValueError(13) from e2
E           ValueError: 13

basic/test_basic.py:84: ValueError

____________ test_chained_exception_without_from ____________
[gw1] linux -- Python 3.6.7 /home/mulawa/developement/omcp/has/test/py/.tox/sct/bin/python3.6

    def test_chained_exception_without_from():
        try:
            try:
                raise ValueError(21)
            except Exception:
                raise ValueError(22)
        except Exception:
>           raise ValueError(23)
E           ValueError: 23

basic/test_basic.py:94: ValueError

```

my setup:
```
pytest           4.0.2       
pytest-xdist     1.25.0
```


currently exception serialization is best described as limited and simplicistic,
thats the main issue there

CODE CONTEXT:
TOP-1 FULL FILE src/_pytest/outcomes.py:
"""
exception classes and constants handling test outcomes
as well as functions creating them
"""
import sys
from typing import Any
from typing import Optional

from packaging.version import Version

if False:  # TYPE_CHECKING
    from typing import NoReturn


class OutcomeException(BaseException):
    """ OutcomeException and its subclass instances indicate and
        contain info about test and collection outcomes.
    """

    def __init__(self, msg: Optional[str] = None, pytrace: bool = True) -> None:
        if msg is not None and not isinstance(msg, str):
            error_msg = (
                "{} expected string as 'msg' parameter, got '{}' instead.\n"
                "Perhaps you meant to use a mark?"
            )
            raise TypeError(error_msg.format(type(self).__name__, type(msg).__name__))
        BaseException.__init__(self, msg)
        self.msg = msg
        self.pytrace = pytrace

    def __repr__(self) -> str:
        if self.msg:
            return self.msg
        return "<{} instance>".format(self.__class__.__name__)

    __str__ = __repr__


TEST_OUTCOME = (OutcomeException, Exception)


class Skipped(OutcomeException):
    # XXX hackish: on 3k we fake to live in the builtins
    # in order to have Skipped exception printing shorter/nicer
    __module__ = "builtins"

    def __init__(
        self,
        msg: Optional[str] = None,
        pytrace: bool = True,
        allow_module_level: bool = False,
    ) -> None:
        OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
        self.allow_module_level = allow_module_level


class Failed(OutcomeException):
    """ raised from an explicit call to pytest.fail() """

    __module__ = "builtins"


class Exit(Exception):
    """ raised for immediate program exits (no tracebacks/summaries)"""

    def __init__(
        self, msg: str = "unknown reason", returncode: Optional[int] = None
    ) -> None:
        self.msg = msg
        self.returncode = returncode
        super().__init__(msg)


# exposed helper methods


def exit(msg: str, returncode: Optional[int] = None) -> "NoReturn":
    """
    Exit testing process.

    :param str msg: message to display upon exit.
    :param int returncode: return code to be used when exiting pytest.
    """
    __tracebackhide__ = True
    raise Exit(msg, returncode)


# Ignore type because of https://github.com/python/mypy/issues/2087.
exit.Exception = Exit  # type: ignore


def skip(msg: str = "", *, allow_module_level: bool = False) -> "NoReturn":
    """
    Skip an executing test with the given message.

    This function should be called only during testing (setup, call or teardown) or
    during collection by using the ``allow_module_level`` flag.  This function can
    be called in doctests as well.

    :kwarg bool allow_module_level: allows this function to be called at
        module level, skipping the rest of the module. Default to False.

    .. note::
        It is better to use the :ref:`pytest.mark.skipif ref` marker when possible to declare a test to be
        skipped under certain conditions like mismatching platforms or
        dependencies.
        Similarly, use the ``# doctest: +SKIP`` directive (see `doctest.SKIP
        <https://docs.python.org/3/library/doctest.html#doctest.SKIP>`_)
        to skip a doctest statically.
    """
    __tracebackhide__ = True
    raise Skipped(msg=msg, allow_module_level=allow_module_level)


# Ignore type because of https://github.com/python/mypy/issues/2087.
skip.Exception = Skipped  # type: ignore


def fail(msg: str = "", pytrace: bool = True) -> "NoReturn":
    """
    Explicitly fail an executing test with the given message.

    :param str msg: the message to show the user as reason for the failure.
    :param bool pytrace: if false the msg represents the full failure information and no
        python traceback will be reported.
    """
    __tracebackhide__ = True
    raise Failed(msg=msg, pytrace=pytrace)


# Ignore type because of https://github.com/python/mypy/issues/2087.
fail.Exception = Failed  # type: ignore


class XFailed(Failed):
    """ raised from an explicit call to pytest.xfail() """


def xfail(reason: str = "") -> "NoReturn":
    """
    Imperatively xfail an executing test or setup functions with the given reason.

    This function should be called only during testing (setup, call or teardown).

    .. note::
        It is better to use the :ref:`pytest.mark.xfail ref` marker when possible to declare a test to be
        xfailed under certain conditions like known bugs or missing features.
    """
    __tracebackhide__ = True
    raise XFailed(reason)


# Ignore type because of https://github.com/python/mypy/issues/2087.
xfail.Exception = XFailed  # type: ignore


def importorskip(
    modname: str, minversion: Optional[str] = None, reason: Optional[str] = None
) -> Any:
    """Imports and returns the requested module ``modname``, or skip the
    current test if the module cannot be imported.

    :param str modname: the name of the module to import
    :param str minversion: if given, the imported module's ``__version__``
        attribute must be at least this minimal version, otherwise the test is
        still skipped.
    :param str reason: if given, this reason is shown as the message when the
        module cannot be imported.
    :returns: The imported module. This should be assigned to its canonical
        name.

    Example::

        docutils = pytest.importorskip("docutils")
    """
    import warnings

    __tracebackhide__ = True
    compile(modname, "", "eval")  # to catch syntaxerrors

    with warnings.catch_warnings():
        # make sure to ignore ImportWarnings that might happen because
        # of existing directories with the same name we're trying to
        # import but without a __init__.py file
        warnings.simplefilter("ignore")
        try:
            __import__(modname)
        except ImportError as exc:
            if reason is None:
                reason = "could not import {!r}: {}".format(modname, exc)
            raise Skipped(reason, allow_module_level=True) from None
    mod = sys.modules[modname]
    if minversion is None:
        return mod
    verattr = getattr(mod, "__version__", None)
    if minversion is not None:
        if verattr is None or Version(verattr) < Version(minversion):
            raise Skipped(
                "module %r has __version__ %r, required is: %r"
                % (modname, verattr, minversion),
                allow_module_level=True,
            )
    return mod


src/_pytest/outcomes.py:
"""
exception classes and constants handling test outcomes
as well as functions creating them
"""
import sys
from typing import Any
from typing import Optional

from packaging.version import Version

if False:  # TYPE_CHECKING
    from typing import NoReturn


class OutcomeException(BaseException):
    """ OutcomeException and its subclass instances indicate and
        contain info about test and collection outcomes.
    """

    def __init__(self, msg: Optional[str] = None, pytrace: bool = True) -> None:
        if msg is not None and not isinstance(msg, str):
            error_msg = (
                "{} expected string as 'msg' parameter, got '{}' instead.\n"
                "Perhaps you meant to use a mark?"
            )
            raise TypeError(error_msg.format(type(self).__name__, type(msg).__name__))
        BaseException.__init__(self, msg)
        self.msg = msg
        self.pytrace = pytrace

    def __repr__(self) -> str:
        if self.msg:
            return self.msg
        return "<{} instance>".format(self.__class__.__name__)

    __str__ = __repr__


TEST_OUTCOME = (OutcomeException, Exception)


class Skipped(OutcomeException):
    # XXX hackish: on 3k we fake to live in the builtins
    # in order to have Skipped exception printing shorter/nicer
    __module__ = "builtins"

    def __init__(
        self,
        msg: Optional[str] = None,
        pytrace: bool = True,
        allow_module_level: bool = False,
    ) -> None:
        OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
        self.allow_module_level = allow_module_level


class Failed(OutcomeException):
    """ raised from an explicit call to pytest.fail() """

    __module__ = "builtins"


class Exit(Exception):
    """ raised for immediate program exits (no tracebacks/summaries)"""

    def __init__(
        self, msg: str = "unknown reason", returncode: Optional[int] = None
    ) -> None:
        self.msg = msg
        self.returncode = returncode
        super().__init__(msg)


# exposed helper methods


def exit(msg: str, returncode: Optional[int] = None) -> "NoReturn":
    """
    Exit testing process.

    :param str msg: message to display upon exit.
    :param int returncode: return code to be used when exiting pytest.
    """
    __tracebackhide__ = True
    raise Exit(msg, returncode)


# Ignore type because of https://github.com/python/mypy/issues/2087.
exit.Exception = Exit  # type: ignore


def skip(msg: str = "", *, allow_module_level: bool = False) -> "NoReturn":
    """
    Skip an executing test with the given message.

    This function should be called only during testing (setup, call or teardown) or
    during collection by using the ``allow_module_level`` flag.  This function can
    be called in doctests as well.

    :kwarg bool allow_module_level: allows this function to be called at
        module level, skipping the rest of the module. Default to False.

    .. note::
        It is better to use the :ref:`pytest.mark.skipif ref` marker when possible to declare a test to be
        skipped under certain conditions like mismatching platforms or
        dependencies.
        Similarly, use the ``# doctest: +SKIP`` directive (see `doctest.SKIP
        <https://docs.python.org/3/library/doctest.html#doctest.SKIP>`_)
        to skip a doctest statically.
    """
    __tracebackhide__ = True
    raise Skipped(msg=msg, allow_module_level=allow_module_level)


# Ignore type because of https://github.com/python/mypy/issues/2087.
skip.Exception = Skipped  # type: ignore


def fail(msg: str = "", pytrace: bool = True) -> "NoReturn":
    """
    Explicitly fail an executing test with the given message.

    :param str msg: the message to show the user as reason for the failure.
    :param bool pytrace: if false the msg represents the full failure information and no
        python traceback will be reported.
    """
    __tracebackhide__ = True
    raise Failed(msg=msg, pytrace=pytrace)


# Ignore type because of https://github.com/python/mypy/issues/2087.
fail.Exception = Failed  # type: ignore


class XFailed(Failed):
    """ raised from an explicit call to pytest.xfail() """


def xfail(reason: str = "") -> "NoReturn":
    """
    Imperatively xfail an executing test or setup functions with the given reason.

    This function should be called only during testing (setup, call or teardown).

    .. note::
        It is better to use the :ref:`pytest.mark.xfail ref` marker when possible to declare a test to be
        xfailed under certain conditions like known bugs or missing features.
    """
    __tracebackhide__ = True
    raise XFailed(reason)


# Ignore type because of https://github.com/python/mypy/issues/2087.
xfail.Exception = XFailed  # type: ignore


def importorskip(
    modname: str, minversion: Optional[str] = None, reason: Optional[str] = None
) -> Any:
    """Imports and returns the requested module ``modname``, or skip the
    current test if the module cannot be imported.

    :param str modname: the name of the module to import
    :param str minversion: if given, the imported module's ``__version__``
        attribute must be at least this minimal version, otherwise the test is
        still skipped.
    :param str reason: if given, this reason is shown as the message when the
        module cannot be imported.
    :returns: The imported module. This should be assigned to its canonical
        name.

    Example::

        docutils = pytest.importorskip("docutils")
    """
    import warnings

    __tracebackhide__ = True
    compile(modname, "", "eval")  # to catch syntaxerrors

    with warnings.catch_warnings():
        # make sure to ignore ImportWarnings that might happen because
        # of existing directories with the same name we're trying to
        # import but without a __init__.py file
        warnings.simplefilter("ignore")
        try:
            __import__(modname)
        except ImportError as exc:
            if reason is None:
                reason = "could not import {!r}: {}".format(modname, exc)
            raise Skipped(reason, allow_module_level=True) from None
    mod = sys.modules[modname]
    if minversion is None:
        return mod
    verattr = getattr(mod, "__version__", None)
    if minversion is not None:
        if verattr is None or Version(verattr) < Version(minversion):
            raise Skipped(
                "module %r has __version__ %r, required is: %r"
                % (modname, verattr, minversion),
                allow_module_level=True,
            )
    return mod


src/_pytest/_io/saferepr.py:
import pprint
import reprlib


def _format_repr_exception(exc, obj):
    exc_name = type(exc).__name__
    try:
        exc_info = str(exc)
    except Exception:
        exc_info = "unknown"
    return '<[{}("{}") raised in repr()] {} object at 0x{:x}>'.format(
        exc_name, exc_info, obj.__class__.__name__, id(obj)
    )


def _ellipsize(s, maxsize):
    if len(s) > maxsize:
        i = max(0, (maxsize - 3) // 2)
        j = max(0, maxsize - 3 - i)
        return s[:i] + "..." + s[len(s) - j :]
    return s


class SafeRepr(reprlib.Repr):
    """subclass of repr.Repr that limits the resulting size of repr()
    and includes information on exceptions raised during the call.
    """

    def __init__(self, maxsize):
        super().__init__()
        self.maxstring = maxsize
        self.maxsize = maxsize

    def repr(self, x):
        try:
            s = super().repr(x)
        except Exception as exc:
            s = _format_repr_exception(exc, x)
        return _ellipsize(s, self.maxsize)

    def repr_instance(self, x, level):
        try:
            s = repr(x)
        except Exception as exc:
            s = _format_repr_exception(exc, x)
        return _ellipsize(s, self.maxsize)


def safeformat(obj):
    """return a pretty printed string for the given object.
    Failing __repr__ functions of user instances will be represented
    with a short exception info.
    """
    try:
        return pprint.pformat(obj)
    except Exception as exc:
        return _format_repr_exception(exc, obj)


def saferepr(obj, maxsize=240):
    """return a size-limited safe repr-string for the given object.
    Failing __repr__ functions of user instances will be represented
    with a short exception info and 'saferepr' generally takes
    care to never raise exceptions itself.  This function is a wrapper
    around the Repr/reprlib functionality of the standard 2.6 lib.
    """
    return SafeRepr(maxsize).repr(obj)


testing/code/test_source.py:
# flake8: noqa
# disable flake check on this file because some constructs are strange
# or redundant on purpose and can't be disable on a line-by-line basis
import ast
import inspect
import sys

import _pytest._code
import pytest
from _pytest._code import Source


def test_source_str_function():
    x = Source("3")
    assert str(x) == "3"

    x = Source("   3")
    assert str(x) == "3"

    x = Source(
        """
        3
        """
    )
    assert str(x) == "\n3"


def test_unicode():
    x = Source("4")
    assert str(x) == "4"
    co = _pytest._code.compile('"å"', mode="eval")
    val = eval(co)
    assert isinstance(val, str)


def test_source_from_function():
    source = _pytest._code.Source(test_source_str_function)
    assert str(source).startswith("def test_source_str_function():")


def test_source_from_method():
    class TestClass:
        def test_method(self):
            pass

    source = _pytest._code.Source(TestClass().test_method)
    assert source.lines == ["def test_method(self):", "    pass"]


def test_source_from_lines():
    lines = ["a \n", "b\n", "c"]
    source = _pytest._code.Source(lines)
    assert source.lines == ["a ", "b", "c"]


def test_source_from_inner_function():
    def f():
        pass

    source = _pytest._code.Source(f, deindent=False)
    assert str(source).startswith("    def f():")
    source = _pytest._code.Source(f)
    assert str(source).startswith("def f():")


def test_source_putaround_simple():
    source = Source("raise ValueError")
    source = source.putaround(
        "try:",
        """\
        except ValueError:
            x = 42
        else:
            x = 23""",
    )
    assert (
        str(source)
        == """\
try:
    raise ValueError
except ValueError:
    x = 42
else:
    x = 23"""
    )


def test_source_putaround():
    source = Source()
    source = source.putaround(
        """
        if 1:
            x=1
    """
    )
    assert str(source).strip() == "if 1:\n    x=1"


def test_source_strips():
    source = Source("")
    assert source == Source()
    assert str(source) == ""
    assert source.strip() == source


def test_source_strip_multiline():
    source = Source()
    source.lines = ["", " hello", "  "]
    source2 = source.strip()
    assert source2.lines == [" hello"]


def test_syntaxerror_rerepresentation():
    ex = pytest.raises(SyntaxError, _pytest._code.compile, "xyz xyz")
    assert ex.value.lineno == 1
    assert ex.value.offset in {5, 7}  # cpython: 7, pypy3.6 7.1.1: 5
    assert ex.value.text.strip(), "x x"


def test_isparseable():
    assert Source("hello").isparseable()
    assert Source("if 1:\n  pass").isparseable()
    assert Source(" \nif 1:\n  pass").isparseable()
    assert not Source("if 1:\n").isparseable()
    assert not Source(" \nif 1:\npass").isparseable()
    assert not Source(chr(0)).isparseable()


class TestAccesses:
    source = Source(
        """\
        def f(x):
            pass
        def g(x):
            pass
    """
    )

    def test_getrange(self):
        x = self.source[0:2]
        assert x.isparseable()
        assert len(x.lines) == 2
        assert str(x) == "def f(x):\n    pass"

    def test_getline(self):
        x = self.source[0]
        assert x == "def f(x):"

    def test_len(self):
        assert len(self.source) == 4

    def test_iter(self):
        values = [x for x in self.source]
        assert len(values) == 4


class TestSourceParsingAndCompiling:
    source = Source(
        """\
        def f(x):
            assert (x ==
                    3 +
                    4)
    """
    ).strip()

    def test_compile(self):
        co = _pytest._code.compile("x=3")
        d = {}
        exec(co, d)
        assert d["x"] == 3

    def test_compile_and_getsource_simple(self):
        co = _pytest._code.compile("x=3")
        exec(co)
        source = _pytest._code.Source(co)
        assert str(source) == "x=3"

    def test_compile_and_getsource_through_same_function(self):
        def gensource(source):
            return _pytest._code.compile(source)

        co1 = gensource(
            """
            def f():
                raise KeyError()
        """
        )
        co2 = gensource(
            """
            def f():
                raise ValueError()
        """
        )
        source1 = inspect.getsource(co1)
        assert "KeyError" in source1
        source2 = inspect.getsource(co2)
        assert "ValueError" in source2

    def test_getstatement(self):
        # print str(self.source)
        ass = str(self.source[1:])
        for i in range(1, 4):
            # print "trying start in line %r" % self.source[i]
            s = self.source.getstatement(i)
            # x = s.deindent()
            assert str(s) == ass

    def test_getstatementrange_triple_quoted(self):
        # print str(self.source)
        source = Source(
            """hello('''
        ''')"""
        )
        s = source.getstatement(0)
        assert s == str(source)
        s = source.getstatement(1)
        assert s == str(source)

    def test_getstatementrange_within_constructs(self):
        source = Source(
            """\
            try:
                try:
                    raise ValueError
                except SomeThing:
                    pass
            finally:
                42
        """
        )
        assert len(source) == 7
        # check all lineno's that could occur in a traceback
        # assert source.getstatementrange(0) == (0, 7)
        # assert source.getstatementrange(1) == (1, 5)
        assert source.getstatementrange(2) == (2, 3)
        assert source.getstatementrange(3) == (3, 4)
        assert source.getstatementrange(4) == (4, 5)
        # assert source.getstatementrange(5) == (0, 7)
        assert source.getstatementrange(6) == (6, 7)

    def test_getstatementrange_bug(self):
        source = Source(
            """\
            try:
                x = (
                   y +
                   z)
            except:
                pass
        """
        )
        assert len(source) == 6
        assert source.getstatementrange(2) == (1, 4)

    def test_getstatementrange_bug2(self):
        source = Source(
            """\
            assert (
                33
                ==
                [
                  X(3,
                      b=1, c=2
                   ),
                ]
              )
        """
        )
        assert len(source) == 9
        assert source.getstatementrange(5) == (0, 9)

    def test_getstatementrange_ast_issue58(self):
        source = Source(
            """\

            def test_some():
                for a in [a for a in
                    CAUSE_ERROR]: pass

            x = 3
        """
        )
        assert getstatement(2, source).lines == source.lines[2:3]
        assert getstatement(3, source).lines == source.lines[3:4]

    def test_getstatementrange_out_of_bounds_py3(self):
        source = Source("if xxx:\n   from .collections import something")
        r = source.getstatementrange(1)
        assert r == (1, 2)

    def test_getstatementrange_with_syntaxerror_issue7(self):
        source = Source(":")
        pytest.raises(SyntaxError, lambda: source.getstatementrange(0))

    def test_compile_to_ast(self):
        source = Source("x = 4")
        mod = source.compile(flag=ast.PyCF_ONLY_AST)
        assert isinstance(mod, ast.Module)
        compile(mod, "<filename>", "exec")

    def test_compile_and_getsource(self):
        co = self.source.compile()
        exec(co, globals())
        f(7)
        excinfo = pytest.raises(AssertionError, f, 6)
        frame = excinfo.traceback[-1].frame
        stmt = frame.code.fullsource.getstatement(frame.lineno)
        assert str(stmt).strip().startswith("assert")

    @pytest.mark.parametrize("name", ["", None, "my"])
    def test_compilefuncs_and_path_sanity(self, name):
        def check(comp, name):
            co = comp(self.source, name)
    

testing/python/raises.py:
import sys

import pytest
from _pytest.outcomes import Failed


class TestRaises:
    def test_check_callable(self):
        with pytest.raises(TypeError, match=r".* must be callable"):
            pytest.raises(RuntimeError, "int('qwe')")

    def test_raises(self):
        excinfo = pytest.raises(ValueError, int, "qwe")
        assert "invalid literal" in str(excinfo.value)

    def test_raises_function(self):
        excinfo = pytest.raises(ValueError, int, "hello")
        assert "invalid literal" in str(excinfo.value)

    def test_raises_callable_no_exception(self):
        class A:
            def __call__(self):
                pass

        try:
            pytest.raises(ValueError, A())
        except pytest.raises.Exception:
            pass

    def test_raises_falsey_type_error(self):
        with pytest.raises(TypeError):
            with pytest.raises(AssertionError, match=0):
                raise AssertionError("ohai")

    def test_raises_repr_inflight(self):
        """Ensure repr() on an exception info inside a pytest.raises with block works (#4386)"""

        class E(Exception):
            pass

        with pytest.raises(E) as excinfo:
            # this test prints the inflight uninitialized object
            # using repr and str as well as pprint to demonstrate
            # it works
            print(str(excinfo))
            print(repr(excinfo))
            import pprint

            pprint.pprint(excinfo)
            raise E()

    def test_raises_as_contextmanager(self, testdir):
        testdir.makepyfile(
            """
            import pytest
            import _pytest._code

            def test_simple():
                with pytest.raises(ZeroDivisionError) as excinfo:
                    assert isinstance(excinfo, _pytest._code.ExceptionInfo)
                    1/0
                print(excinfo)
                assert excinfo.type == ZeroDivisionError
                assert isinstance(excinfo.value, ZeroDivisionError)

            def test_noraise():
                with pytest.raises(pytest.raises.Exception):
                    with pytest.raises(ValueError):
                           int()

            def test_raise_wrong_exception_passes_by():
                with pytest.raises(ZeroDivisionError):
                    with pytest.raises(ValueError):
                           1/0
        """
        )
        result = testdir.runpytest()
        result.stdout.fnmatch_lines(["*3 passed*"])

    def test_does_not_raise(self, testdir):
        testdir.makepyfile(
            """
            from contextlib import contextmanager
            import pytest

            @contextmanager
            def does_not_raise():
                yield

            @pytest.mark.parametrize('example_input,expectation', [
                (3, does_not_raise()),
                (2, does_not_raise()),
                (1, does_not_raise()),
                (0, pytest.raises(ZeroDivisionError)),
            ])
            def test_division(example_input, expectation):
                '''Test how much I know division.'''
                with expectation:
                    assert (6 / example_input) is not None
        """
        )
        result = testdir.runpytest()
        result.stdout.fnmatch_lines(["*4 passed*"])

    def test_does_not_raise_does_raise(self, testdir):
        testdir.makepyfile(
            """
            from contextlib import contextmanager
            import pytest

            @contextmanager
            def does_not_raise():
                yield

            @pytest.mark.parametrize('example_input,expectation', [
                (0, does_not_raise()),
                (1, pytest.raises(ZeroDivisionError)),
            ])
            def test_division(example_input, expectation):
                '''Test how much I know division.'''
                with expectation:
                    assert (6 / example_input) is not None
        """
        )
        result = testdir.runpytest()
        result.stdout.fnmatch_lines(["*2 failed*"])

    def test_noclass(self):
        with pytest.raises(TypeError):
            pytest.raises("wrong", lambda: None)

    def test_invalid_arguments_to_raises(self):
        with pytest.raises(TypeError, match="unknown"):
            with pytest.raises(TypeError, unknown="bogus"):
                raise ValueError()

    def test_tuple(self):
        with pytest.raises((KeyError, ValueError)):
            raise KeyError("oops")

    def test_no_raise_message(self):
        try:
            pytest.raises(ValueError, int, "0")
        except pytest.raises.Exception as e:
            assert e.msg == "DID NOT RAISE {}".format(repr(ValueError))
        else:
            assert False, "Expected pytest.raises.Exception"

        try:
            with pytest.raises(ValueError):
                pass
        except pytest.raises.Exception as e:
            assert e.msg == "DID NOT RAISE {}".format(repr(ValueError))
        else:
            assert False, "Expected pytest.raises.Exception"

    @pytest.mark.parametrize("method", ["function", "with"])
    def test_raises_cyclic_reference(self, method):
        """
        Ensure pytest.raises does not leave a reference cycle (#1965).
        """
        import gc

        class T:
            def __call__(self):
                # Early versions of Python 3.5 have some bug causing the
                # __call__ frame to still refer to t even after everything
                # is done. This makes the test pass for them.
                if sys.version_info < (3, 5, 2):  # pragma: no cover
                    del self
                raise ValueError

        t = T()
        refcount = len(gc.get_referrers(t))

        if method == "function":
            pytest.raises(ValueError, t)
        else:
            with pytest.raises(ValueError):
                t()

        # ensure both forms of pytest.raises don't leave exceptions in sys.exc_info()
        assert sys.exc_info() == (None, None, None)

        assert refcount == len(gc.get_referrers(t))

    def test_raises_match(self):
        msg = r"with base \d+"
        with pytest.raises(ValueError, match=msg):
            int("asdf")

        msg = "with base 10"
        with pytest.raises(ValueError, match=msg):
            int("asdf")

        msg = "with base 16"
        expr = r"Pattern '{}' not found in \"invalid literal for int\(\) with base 10: 'asdf'\"".format(
            msg
        )
        with pytest.raises(AssertionError, match=expr):
            with pytest.raises(ValueError, match=msg):
                int("asdf", base=10)

    def test_match_failure_string_quoting(self):
        with pytest.raises(AssertionError) as excinfo:
            with pytest.raises(AssertionError, match="'foo"):
                raise AssertionError("'bar")
        msg, = excinfo.value.args
        assert msg == 'Pattern "\'foo" not found in "\'bar"'

    def test_raises_match_wrong_type(self):
        """Raising an exception with the wrong type and match= given.

        pytest should throw the unexpected exception - the pattern match is not
        really relevant if we got a different exception.
        """
        with pytest.raises(ValueError):
            with pytest.raises(IndexError, match="nomatch"):
                int("asdf")

    def test_raises_exception_looks_iterable(self):
        class Meta(type):
            def __getitem__(self, item):
                return 1 / 0

            def __len__(self):
                return 1

        class ClassLooksIterableException(Exception, metaclass=Meta):
            pass

        with pytest.raises(
            Failed,
            match=r"DID NOT RAISE <class 'raises(\..*)*ClassLooksIterableException'>",
        ):
            pytest.raises(ClassLooksIterableException, lambda: None)

    def test_raises_with_raising_dunder_class(self):
        """Test current behavior with regard to exceptions via __class__ (#4284)."""

        class CrappyCla

doc/en/example/assertion/failure_demo.py:
import _pytest._code
import pytest
from pytest import raises


def otherfunc(a, b):
    assert a == b


def somefunc(x, y):
    otherfunc(x, y)


def otherfunc_multi(a, b):
    assert a == b


@pytest.mark.parametrize("param1, param2", [(3, 6)])
def test_generative(param1, param2):
    assert param1 * 2 < param2


class TestFailing:
    def test_simple(self):
        def f():
            return 42

        def g():
            return 43

        assert f() == g()

    def test_simple_multiline(self):
        otherfunc_multi(42, 6 * 9)

    def test_not(self):
        def f():
            return 42

        assert not f()


class TestSpecialisedExplanations:
    def test_eq_text(self):
        assert "spam" == "eggs"

    def test_eq_similar_text(self):
        assert "foo 1 bar" == "foo 2 bar"

    def test_eq_multiline_text(self):
        assert "foo\nspam\nbar" == "foo\neggs\nbar"

    def test_eq_long_text(self):
        a = "1" * 100 + "a" + "2" * 100
        b = "1" * 100 + "b" + "2" * 100
        assert a == b

    def test_eq_long_text_multiline(self):
        a = "1\n" * 100 + "a" + "2\n" * 100
        b = "1\n" * 100 + "b" + "2\n" * 100
        assert a == b

    def test_eq_list(self):
        assert [0, 1, 2] == [0, 1, 3]

    def test_eq_list_long(self):
        a = [0] * 100 + [1] + [3] * 100
        b = [0] * 100 + [2] + [3] * 100
        assert a == b

    def test_eq_dict(self):
        assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0}

    def test_eq_set(self):
        assert {0, 10, 11, 12} == {0, 20, 21}

    def test_eq_longer_list(self):
        assert [1, 2] == [1, 2, 3]

    def test_in_list(self):
        assert 1 in [0, 2, 3, 4, 5]

    def test_not_in_text_multiline(self):
        text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail"
        assert "foo" not in text

    def test_not_in_text_single(self):
        text = "single foo line"
        assert "foo" not in text

    def test_not_in_text_single_long(self):
        text = "head " * 50 + "foo " + "tail " * 20
        assert "foo" not in text

    def test_not_in_text_single_long_term(self):
        text = "head " * 50 + "f" * 70 + "tail " * 20
        assert "f" * 70 not in text

    def test_eq_dataclass(self):
        from dataclasses import dataclass

        @dataclass
        class Foo:
            a: int
            b: str

        left = Foo(1, "b")
        right = Foo(1, "c")
        assert left == right

    def test_eq_attrs(self):
        import attr

        @attr.s
        class Foo:
            a = attr.ib()
            b = attr.ib()

        left = Foo(1, "b")
        right = Foo(1, "c")
        assert left == right


def test_attribute():
    class Foo:
        b = 1

    i = Foo()
    assert i.b == 2


def test_attribute_instance():
    class Foo:
        b = 1

    assert Foo().b == 2


def test_attribute_failure():
    class Foo:
        def _get_b(self):
            raise Exception("Failed to get attrib")

        b = property(_get_b)

    i = Foo()
    assert i.b == 2


def test_attribute_multiple():
    class Foo:
        b = 1

    class Bar:
        b = 2

    assert Foo().b == Bar().b


def globf(x):
    return x + 1


class TestRaises:
    def test_raises(self):
        s = "qwe"
        raises(TypeError, int, s)

    def test_raises_doesnt(self):
        raises(IOError, int, "3")

    def test_raise(self):
        raise ValueError("demo error")

    def test_tupleerror(self):
        a, b = [1]  # NOQA

    def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
        items = [1, 2, 3]
        print("items is {!r}".format(items))
        a, b = items.pop()

    def test_some_error(self):
        if namenotexi:  # NOQA
            pass

    def func1(self):
        assert 41 == 42


# thanks to Matthew Scott for this test
def test_dynamic_compile_shows_nicely():
    import importlib.util
    import sys

    src = "def foo():\n assert 1 == 0\n"
    name = "abc-123"
    spec = importlib.util.spec_from_loader(name, loader=None)
    module = importlib.util.module_from_spec(spec)
    code = _pytest._code.compile(src, name, "exec")
    exec(code, module.__dict__)
    sys.modules[name] = module
    module.foo()


class TestMoreErrors:
    def test_complex_error(self):
        def f():
            return 44

        def g():
            return 43

        somefunc(f(), g())

    def test_z1_unpack_error(self):
        items = []
        a, b = items

    def test_z2_type_error(self):
        items = 3
        a, b = items

    def test_startswith(self):
        s = "123"
        g = "456"
        assert s.startswith(g)

    def test_startswith_nested(self):
        def f():
            return "123"

        def g():
            return "456"

        assert f().startswith(g())

    def test_global_func(self):
        assert isinstance(globf(42), float)

    def test_instance(self):
        self.x = 6 * 7
        assert self.x != 42

    def test_compare(self):
        assert globf(10) < 5

    def test_try_finally(self):
        x = 1
        try:
            assert x == 0
        finally:
            x = 0


class TestCustomAssertMsg:
    def test_single_line(self):
        class A:
            a = 1

        b = 2
        assert A.a == b, "A.a appears not to be b"

    def test_multiline(self):
        class A:
            a = 1

        b = 2
        assert (
            A.a == b
        ), "A.a appears not to be b\nor does not appear to be b\none of those"

    def test_custom_repr(self):
        class JSON:
            a = 1

            def __repr__(self):
                return "This is JSON\n{\n  'foo': 'bar'\n}"

        a = JSON()
        b = 2
        assert a.a == b, a


FORMAT VIOLATION IN YOUR PREVIOUS SYNTHESIS (ground truth, fix it): 0 complete SEARCH/REPLACE blocks (chars=0, SEARCHx0, separatorx0, REPLACEx0, finish_reason=length). Output ONLY complete blocks, blocks FIRST, one repo-relative file path header per block, non-empty SEARCH and REPLACE.