Changeset 1747:ffa05876b460


Ignore:
Timestamp:
Jan 1, 2019, 1:59:26 PM (3 years ago)
Author:
Stefan Schwarzer <sschwarzer@…>
Branch:
default
histedit_source:
3cbe98b4af130e7f517217817c9a3422104feb02,d4c83738e0a871b833afc42924881350c4163999
Message:
Improve `Call` and `ScriptedSession`

Some of the changes:

- Allow passing expected args and kwargs to `Call` constructor and
  have them checked against the actual args and kwargs.

- Move the call logic (raise or return) into the new method
  `Call.__call__`.

- Print more output to help with debugging. (Pytest will print this
  output only if a test fails.)

- Use an integer index instead of an iterator to get the next scripted
  call. This change makes it easier to "see" in the debugger "where"
  we are in the execution.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • test/scripted_session.py

    r1746 r1747  
    99class Call:
    1010
    11     def __init__(self, method_name, result=None, args=None, kwargs=None):
     11    def __init__(self, method_name, result=None,
     12                 expected_args=None, expected_kwargs=None):
    1213        self.method_name = method_name
    1314        self.result = result
    14         self.args = args if args is not None else ()
    15         self.kwargs = kwargs if kwargs is not None else {}
     15        self.expected_args = expected_args
     16        self.expected_kwargs = expected_kwargs
     17
     18    def __repr__(self):
     19        return ("{0.__class__.__name__}("
     20                "method_name={0.method_name!r}, "
     21                "result={0.result!r}, "
     22                "expected_args={0.expected_args!r}, "
     23                "expected_kwargs={0.expected_kwargs!r})".format(self))
     24
     25    def check_args(self, args, kwargs):
     26        if self.expected_args is not None:
     27            assert args == self.expected_args
     28        if self.expected_kwargs is not None:
     29            assert kwargs == self.expected_kwargs
     30
     31    @staticmethod
     32    def _is_exception_class(obj):
     33        """
     34        Return `True` if `obj` is an exception class, else `False`.
     35        """
     36        try:
     37            return issubclass(obj, Exception)
     38        except TypeError:
     39            # TypeError: issubclass() arg 1 must be a class
     40            return False
     41
     42    def __call__(self):
     43        """
     44        Simulate call, returning the result or raising the exception.
     45        """
     46        if isinstance(self.result, Exception) or self._is_exception_class(self.result):
     47            raise self.result
     48        else:
     49            return self.result
    1650
    1751
     
    4175
    4276    def __init__(self, script):
     77        self.script = script
     78        self._index = 0
    4379        # Always expect an entry for the constructor.
    44         init = script[0]
     80        init = self._next_call()
    4581        assert init.method_name == "__init__"
    46         if isinstance(init.result, Exception) or self._is_exception_class(init.result):
    47             # Simulate an exception raised in the factory's constructor.
    48             raise init.result
    49         self.script = script[1:]
    50         self._script_iter = iter(self.script)
     82        init()
    5183
    52     @staticmethod
    53     def _is_exception_class(obj):
     84    def _next_call(self, expected_method_name=None):
    5485        """
    55         Return `True` if `obj` is an exception class, else `False`.
     86        Return next `Call` object.
     87
     88        Print the `Call` object before returning it. This is useful for
     89        testing and debugging.
    5690        """
    57         try:
    58             return issubclass(obj, Exception)
    59         except TypeError:
    60             # TypeError: issubclass() arg 1 must be a class
    61             return False
     91        print("Expected method name: {!r}".format(expected_method_name))
     92        call = self.script[self._index]
     93        self._index += 1
     94        print("Next call: {!r}".format(call))
     95        if expected_method_name is not None:
     96            assert call.method_name == expected_method_name, (
     97                     "called method {!r} instead of {!r}".format(expected_method_name,
     98                                                                 call.method_name))
     99        return call
    62100
    63101    def __getattr__(self, attribute_name):
    64         print("attribute name:", attribute_name)
    65         call = next(self._script_iter)
    66         print("calling {0.method_name!r} with result {0.result!r}".format(call))
    67         assert call.method_name == attribute_name, (
    68                  "called method {!r} instead of {!r}".format(attribute_name,
    69                                                              call.method_name))
     102        call = self._next_call(expected_method_name=attribute_name)
    70103        def dummy_method(*args, **kwargs):
    71             if isinstance(call.result, Exception) or self._is_exception_class(call.result):
    72                 raise call.result
    73             else:
    74                 return call.result
     104            print("args: {!r}".format(args))
     105            print("kwargs: {!r}".format(kwargs))
     106            call.check_args(args, kwargs)
     107            return call()
    75108        return dummy_method
    76109
Note: See TracChangeset for help on using the changeset viewer.