Esempio n. 1
0
class ApplicationTester(object):
    """
    Eases the testing of console applications.
    """
    def __init__(self, application: Application) -> None:
        self._application = application
        self._application.auto_exits(False)
        self._io = BufferedIO()
        self._status_code = 0

    @property
    def application(self) -> Application:
        return self._application

    @property
    def io(self):  # type: () -> BufferedIO
        return self._io

    @property
    def status_code(self):  # type: () -> int
        return self._status_code

    def execute(
        self,
        args: Optional[str] = "",
        inputs: Optional[str] = None,
        interactive: Optional[bool] = None,
        verbosity: Optional[Verbosity] = None,
        decorated: bool = False,
        supports_utf8: bool = True,
    ) -> int:
        """
        Executes the command
        """
        self._io.clear()

        input = StringInput(args)
        self._io.set_input(input)
        self._io.decorated(decorated)
        self._io.output.set_supports_utf8(supports_utf8)
        self._io.error_output.set_supports_utf8(supports_utf8)

        if inputs is not None:
            self._io.input.set_stream(StringIO(inputs))

        if interactive is not None:
            self._io.interactive(interactive)

        if verbosity is not None:
            self._io.set_verbosity(verbosity)

        self._status_code = self._application.run(
            self._io.input,
            self._io.output,
            self._io.error_output,
        )

        return self._status_code
Esempio n. 2
0
def test_render_debug_better_error_message_recursion_error():
    io = BufferedIO()
    io.set_verbosity(Verbosity.DEBUG)

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

    trace.render(io)

    expected = r"""^
  Stack trace:

  \d+  {}:99 in test_render_debug_better_error_message_recursion_error
         97\│ 
         98\│     try:
      →  99\│         recursion_error\(\)
        100\│     except RecursionError as e:
        101\│         trace = ExceptionTrace\(e\)

  ...  Previous frame repeated \d+ times

  \s*\d+  {}:91 in recursion_error
         89\│ 
         90\│ def recursion_error\(\):
      →  91\│     recursion_error\(\)
         92\│ 
         93\│ 

  RecursionError

  maximum recursion depth exceeded

  at {}:91 in recursion_error
       87\│     assert re.match\(expected, io.fetch_output\(\)\) is not None
       88\│ 
       89\│ 
       90\│ def recursion_error\(\):
    →  91\│     recursion_error\(\)
       92\│ 
       93\│ 
       94\│ def test_render_debug_better_error_message_recursion_error\(\):
       95\│     io = BufferedIO\(\)
""".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
Esempio n. 3
0
def test_render_can_ignore_given_files():
    import os

    from .helpers import outer

    io = BufferedIO()
    io.set_verbosity(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  {}:224 in test_render_can_ignore_given_files
       call()

  1  {}:221 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()
Esempio n. 4
0
def test_render_debug_better_error_message_recursion_error_with_multiple_duplicated_frames(
):
    io = BufferedIO()
    io.set_verbosity(Verbosity.VERBOSE)

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

    trace = ExceptionTrace(e.value)

    trace.render(io)

    expected = r"...  Previous 2 frames repeated \d+ times"

    assert re.search(expected, io.fetch_output()) is not None
Esempio n. 5
0
def test_render_debug_better_error_message():
    io = BufferedIO()
    io.set_verbosity(Verbosity.DEBUG)

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

    trace.render(io)

    expected = r"""^
  Stack trace:

  1  {}:52 in test_render_debug_better_error_message
       50\│ 
       51\│     try:
    →  52\│         fail\(\)
       53\│     except Exception as e:  # Exception
       54\│         trace = ExceptionTrace\(e\)

  Exception

  Failed

  at {}:12 in fail
        8\│ from cleo.ui.exception_trace import ExceptionTrace
        9\│ 
       10\│ 
       11\│ def fail\(\):
    →  12\│     raise Exception\("Failed"\)
       13\│ 
       14\│ 
       15\│ def test_render_better_error_message\(\):
       16\│     io = BufferedIO\(\)
""".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
Esempio n. 6
0
class CommandTester(object):
    """
    Eases the testing of console commands.
    """

    def __init__(self, command: Command) -> None:
        self._command = command
        self._io = BufferedIO()
        self._inputs = []
        self._status_code = None

    @property
    def command(self) -> Command:
        return self._command

    @property
    def io(self) -> BufferedIO:
        return self._io

    @property
    def status_code(self):  # type: () -> int
        return self._status_code

    def execute(
        self,
        args: Optional[str] = "",
        inputs: Optional[str] = None,
        interactive: Optional[bool] = None,
        verbosity: Optional[Verbosity] = None,
        decorated: Optional[bool] = None,
        supports_utf8: bool = True,
    ) -> int:
        """
        Executes the command
        """
        application = self._command.application

        input = StringInput(args)
        if application is not None and application.definition.has_argument("command"):
            name = self._command.name
            if " " in name:
                # If the command is namespaced we rearrange
                # the input to parse it as a single argument
                argv = [application.name, self._command.name] + input._tokens

                input = ArgvInput(argv)
            else:
                input = StringInput(name + " " + args)

        self._io.set_input(input)
        self._io.output.set_supports_utf8(supports_utf8)
        self._io.error_output.set_supports_utf8(supports_utf8)

        if inputs is not None:
            self._io.input.set_stream(StringIO(inputs))

        if interactive is not None:
            self._io.interactive(interactive)

        if verbosity is not None:
            self._io.set_verbosity(verbosity)

        if decorated is not None:
            self._io.decorated(decorated)

        self._status_code = self._command.run(self._io)

        return self._status_code
Esempio n. 7
0
def test_render_shows_ignored_files_if_in_debug_mode():
    import os

    from .helpers import outer

    io = BufferedIO()
    io.set_verbosity(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  {}:276 in test_render_shows_ignored_files_if_in_debug_mode
      274│ 
      275│     with pytest.raises(Exception) as e:
    → 276│         call()
      277│ 
      278│     trace = ExceptionTrace(e.value)

  3  {}:273 in call
      271│             outer()
      272│ 
    → 273│         run()
      274│ 
      275│     with pytest.raises(Exception) as e:

  2  {}:271 in run
      269│     def call():
      270│         def run():
    → 271│             outer()
      272│ 
      273│         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()