Example #1
0
def test_render_debug_better_error_message_recursion_error():
    io = BufferedIO()
    io.set_verbosity(DEBUG)

    try:
        recursion_error()
    except RecursionError as e:
        trace = ExceptionTrace(e)

    trace.render(io)

    expected = r"""^
  Stack trace:

  \d+  {}:163 in test_render_debug_better_error_message_recursion_error
        161\│ 
        162\│     try:
      → 163\│         recursion_error\(\)
        164\│     except RecursionError as e:
        165\│         trace = ExceptionTrace\(e\)

  ...  Previous frame repeated \d+ times

  \s*\d+  {}:152 in recursion_error
        150\│ 
        151\│ def recursion_error\(\):
      → 152\│     recursion_error\(\)
        153\│ 
        154\│ 

  RecursionError

  maximum recursion depth exceeded

  at {}:152 in recursion_error
      148\│     assert re.match\(expected, io.fetch_output\(\)\) is not None
      149\│ 
      150\│ 
      151\│ def recursion_error\(\):
    → 152\│     recursion_error\(\)
      153\│ 
      154\│ 
      155\│ @pytest.mark.skipif\(
      156\│     not PY36, reason="Better error messages are only available for Python \^3\.6"
""".format(
        re.escape(trace._get_relative_file_path(__file__)),
        re.escape(trace._get_relative_file_path(__file__)),
        re.escape(trace._get_relative_file_path(__file__)),
    )

    assert re.match(expected, io.fetch_output()) is not None
Example #2
0
def test_render_can_ignore_given_files():
    import os

    from .helpers import outer

    io = BufferedIO()
    io.set_verbosity(VERBOSE)

    def call():
        def run():
            outer()

        run()

    with pytest.raises(Exception) as e:
        call()

    trace = ExceptionTrace(e.value)
    helpers_file = os.path.join(os.path.dirname(__file__), "helpers.py")
    trace.ignore_files_in("^{}$".format(re.escape(helpers_file)))

    trace.render(io)

    expected = """
  Stack trace:

  2  {}:297 in test_render_can_ignore_given_files
     call()

  1  {}:294 in call
     run()

  Exception

  Foo

  at {}:3 in inner
        1│ def outer():
        2│     def inner():
    →   3│         raise Exception("Foo")
        4│ 
        5│     inner()
        6│ 
""".format(
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(helpers_file),
    )

    assert expected == io.fetch_output()
Example #3
0
def test_render_better_error_message():
    io = BufferedIO()

    try:
        raise Exception("Failed")
    except Exception as e:
        trace = ExceptionTrace(e)

    trace.render(io)

    expected = """\

  Exception

  Failed

  at {}:45 in test_render_better_error_message
       41│ def test_render_better_error_message():
       42│     io = BufferedIO()
       43│ 
       44│     try:
    →  45│         raise Exception("Failed")
       46│     except Exception as e:
       47│         trace = ExceptionTrace(e)
       48│ 
       49│     trace.render(io)
""".format(trace._get_relative_file_path(__file__))
    assert expected == io.fetch_output()
Example #4
0
def test_render_supports_solutions():
    from crashtest.contracts.provides_solution import ProvidesSolution
    from crashtest.contracts.base_solution import BaseSolution
    from crashtest.solution_providers.solution_provider_repository import (
        SolutionProviderRepository,
    )

    class CustomError(ProvidesSolution, Exception):
        @property
        def solution(self):
            solution = BaseSolution("Solution Title.", "Solution Description")
            solution.documentation_links.append("https://example.com")
            solution.documentation_links.append("https://example2.com")

            return solution

    io = BufferedIO()

    def call():
        raise CustomError("Error with solution")

    with pytest.raises(CustomError) as e:
        call()

    trace = ExceptionTrace(
        e.value, solution_provider_repository=SolutionProviderRepository()
    )

    trace.render(io)

    expected = """
  CustomError

  Error with solution

  at {}:433 in call
      429│ 
      430│     io = BufferedIO()
      431│ 
      432│     def call():
    → 433│         raise CustomError("Error with solution")
      434│ 
      435│     with pytest.raises(CustomError) as e:
      436│         call()
      437│ 

  • Solution Title: Solution Description
    https://example.com,
    https://example2.com
""".format(
        trace._get_relative_file_path(__file__),
    )

    assert expected == io.fetch_output()
Example #5
0
def test_render_falls_back_on_ascii_symbols():
    from crashtest.contracts.base_solution import BaseSolution
    from crashtest.contracts.provides_solution import ProvidesSolution
    from crashtest.solution_providers.solution_provider_repository import (
        SolutionProviderRepository, )

    class CustomError(ProvidesSolution, Exception):
        @property
        def solution(self):
            solution = BaseSolution("Solution Title.", "Solution Description")
            solution.documentation_links.append("https://example.com")
            solution.documentation_links.append("https://example2.com")

            return solution

    io = BufferedIO(supports_utf8=False)

    def call():
        raise CustomError("Error with solution")

    with pytest.raises(CustomError) as e:
        call()

    trace = ExceptionTrace(
        e.value, solution_provider_repository=SolutionProviderRepository())

    trace.render(io)

    expected = """
  CustomError

  Error with solution

  at {}:493 in call
      489| 
      490|     io = BufferedIO(supports_utf8=False)
      491| 
      492|     def call():
    > 493|         raise CustomError("Error with solution")
      494| 
      495|     with pytest.raises(CustomError) as e:
      496|         call()
      497| 

  * Solution Title: Solution Description
    https://example.com,
    https://example2.com
""".format(trace._get_relative_file_path(__file__), )

    assert expected == io.fetch_output()
Example #6
0
def test_render_debug_better_error_message_recursion_error_with_multiple_duplicated_frames():
    io = BufferedIO()
    io.set_verbosity(VERBOSE)

    with pytest.raises(RecursionError) as e:
        first()

    trace = ExceptionTrace(e.value)

    trace.render(io)

    expected = r"...  Previous 2 frames repeated \d+ times".format(
        filename=re.escape(trace._get_relative_file_path(__file__)),
    )

    assert re.search(expected, io.fetch_output()) is not None
Example #7
0
def test_render_debug_better_error_message():
    io = BufferedIO()
    io.set_verbosity(DEBUG)

    try:
        fail()
    except Exception as e:  # Exception
        trace = ExceptionTrace(e)

    trace.render(io)

    expected = r"""^
  Stack trace:

  1  {}:113 in test_render_debug_better_error_message
      111\│ 
      112\│     try:
    → 113\│         fail\(\)
      114\│     except Exception as e:  # Exception
      115\│         trace = ExceptionTrace\(e\)

  Exception

  Failed

  at {}:15 in fail
       11\│ from clikit.utils._compat import PY38
       12\│ 
       13\│ 
       14\│ def fail\(\):
    →  15\│     raise Exception\("Failed"\)
       16\│ 
       17\│ 
       18\│ @pytest.mark.skipif\(PY36, reason="Legacy error messages are Python <3.6 only"\)
       19\│ def test_render_legacy_error_message\(\):
""".format(
        re.escape(trace._get_relative_file_path(__file__)),
        re.escape(trace._get_relative_file_path(__file__)),
    )

    assert re.match(expected, io.fetch_output()) is not None
Example #8
0
def test_render_shows_ignored_files_if_in_debug_mode():
    import os

    from .helpers import outer

    io = BufferedIO()
    io.set_verbosity(DEBUG)

    def call():
        def run():
            outer()

        run()

    with pytest.raises(Exception) as e:
        call()

    trace = ExceptionTrace(e.value)
    helpers_file = os.path.join(os.path.dirname(__file__), "helpers.py")
    trace.ignore_files_in("^{}$".format(re.escape(helpers_file)))

    trace.render(io)

    expected = """
  Stack trace:

  4  {}:352 in test_render_shows_ignored_files_if_in_debug_mode
      350│ 
      351│     with pytest.raises(Exception) as e:
    → 352│         call()
      353│ 
      354│     trace = ExceptionTrace(e.value)

  3  {}:349 in call
      347│             outer()
      348│ 
    → 349│         run()
      350│ 
      351│     with pytest.raises(Exception) as e:

  2  {}:347 in run
      345│     def call():
      346│         def run():
    → 347│             outer()
      348│ 
      349│         run()

  1  {}:5 in outer
        3│         raise Exception("Foo")
        4│ 
    →   5│     inner()
        6│ 

  Exception

  Foo

  at {}:3 in inner
        1│ def outer():
        2│     def inner():
    →   3│         raise Exception("Foo")
        4│ 
        5│     inner()
        6│ 
""".format(
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(helpers_file),
        trace._get_relative_file_path(helpers_file),
    )

    assert expected == io.fetch_output()