~ubuntu-branches/ubuntu/precise/landscape-client/precise-proposed

« back to all changes in this revision

Viewing changes to landscape/tests/mocker.py

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2010-06-28 18:07:18 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20100628180718-jkuv4n8rbpkddxjk
Tags: 1.5.2.1-0ubuntu0.10.10.0
* Include maverick in debian/rules substvars (LP: #596062)
* Filter duplicate network interfaces in get_active_interfaces (LP: #597000)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
"""
2
 
Copyright (c) 2007  Gustavo Niemeyer <gustavo@niemeyer.net>
3
 
 
4
 
Graceful platform for test doubles in Python (mocks, stubs, fakes, and dummies).
 
2
Mocker
 
3
 
 
4
Graceful platform for test doubles in Python: mocks, stubs, fakes, and dummies.
 
5
 
 
6
Copyright (c) 2007-2010, Gustavo Niemeyer <gustavo@niemeyer.net>
 
7
 
 
8
All rights reserved.
 
9
 
 
10
Redistribution and use in source and binary forms, with or without
 
11
modification, are permitted provided that the following conditions are met:
 
12
 
 
13
    * Redistributions of source code must retain the above copyright notice,
 
14
      this list of conditions and the following disclaimer.
 
15
    * Redistributions in binary form must reproduce the above copyright notice,
 
16
      this list of conditions and the following disclaimer in the documentation
 
17
      and/or other materials provided with the distribution.
 
18
    * Neither the name of the copyright holder nor the names of its
 
19
      contributors may be used to endorse or promote products derived from
 
20
      this software without specific prior written permission.
 
21
 
 
22
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
23
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
24
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
25
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
26
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
27
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
28
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
29
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 
30
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
31
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
32
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5
33
"""
6
34
import __builtin__
7
35
import tempfile
18
46
    from sets import Set as set # pragma: nocover
19
47
 
20
48
 
21
 
__all__ = ["Mocker", "expect", "IS", "CONTAINS", "IN", "MATCH",
22
 
           "ANY", "ARGS", "KWARGS"]
 
49
__all__ = ["Mocker", "Expect", "expect", "IS", "CONTAINS", "IN", "MATCH",
 
50
           "ANY", "ARGS", "KWARGS", "MockerTestCase"]
23
51
 
24
52
 
25
53
__author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
26
 
__license__ = "PSF License"
27
 
__version__ = "0.10.1"
 
54
__license__ = "BSD"
 
55
__version__ = "1.0"
28
56
 
29
57
 
30
58
ERROR_PREFIX = "[Mocker] "
56
84
 
57
85
    """
58
86
 
 
87
    __mocker__ = None
 
88
 
59
89
    def __init__(self, mock, attr=None):
60
90
        self._mock = mock
61
91
        self._attr = attr
64
94
        return self.__class__(self._mock, attr)
65
95
 
66
96
    def __call__(self, *args, **kwargs):
67
 
        getattr(self._mock.__mocker__, self._attr)(*args, **kwargs)
 
97
        mocker = self.__mocker__
 
98
        if not mocker:
 
99
            mocker = self._mock.__mocker__
 
100
        getattr(mocker, self._attr)(*args, **kwargs)
68
101
        return self
69
102
 
70
103
 
 
104
def Expect(mocker):
 
105
    """Create an expect() "function" using the given Mocker instance.
 
106
 
 
107
    This helper allows defining an expect() "function" which works even
 
108
    in trickier cases such as:
 
109
 
 
110
        expect = Expect(mymocker)
 
111
        expect(iter(mock)).generate([1, 2, 3])
 
112
 
 
113
    """
 
114
    return type("Expect", (expect,), {"__mocker__": mocker})
 
115
 
 
116
 
71
117
# --------------------------------------------------------------------
72
118
# Extensions to Python's unittest.
73
119
 
88
134
    a few additional helper methods.
89
135
    """
90
136
 
91
 
    expect = expect
92
 
 
93
137
    def __init__(self, methodName="runTest"):
94
138
        # So here is the trick: we take the real test method, wrap it on
95
139
        # a function that do the job we have to do, and insert it in the
115
159
                        result.addCallback(verify)
116
160
                    else:
117
161
                        self.mocker.verify()
 
162
                        self.mocker.restore()
118
163
                    return result
119
164
            # Copy all attributes from the original method..
120
165
            for attr in dir(test_method):
137
182
        self.run = run_wrapper
138
183
 
139
184
        self.mocker = Mocker()
 
185
        self.expect = Expect(self.mocker)
140
186
 
141
187
        self.__cleanup_funcs = []
142
188
        self.__cleanup_paths = []
143
189
 
144
190
        super(MockerTestCase, self).__init__(methodName)
145
191
 
 
192
    def __call__(self, *args, **kwargs):
 
193
        # This is necessary for Python 2.3 only, because it didn't use run(),
 
194
        # which is supported above.
 
195
        try:
 
196
            super(MockerTestCase, self).__call__(*args, **kwargs)
 
197
        finally:
 
198
            if sys.version_info < (2, 4):
 
199
                self.__cleanup()
 
200
 
146
201
    def __cleanup(self):
147
202
        for path in self.__cleanup_paths:
148
203
            if os.path.isfile(path):
274
329
        """
275
330
        first_methods = dict(inspect.getmembers(first, inspect.ismethod))
276
331
        second_methods = dict(inspect.getmembers(second, inspect.ismethod))
277
 
        for name, first_method in first_methods.items():
 
332
        for name, first_method in first_methods.iteritems():
278
333
            first_argspec = inspect.getargspec(first_method)
279
334
            first_formatted = inspect.formatargspec(*first_argspec)
280
335
 
292
347
                    (first.__name__, name, first_formatted,
293
348
                     second.__name__, name, second_formatted))
294
349
 
 
350
    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
 
351
        """
 
352
        Fail unless an exception of class excClass is thrown by callableObj
 
353
        when invoked with arguments args and keyword arguments kwargs. If a
 
354
        different type of exception is thrown, it will not be caught, and the
 
355
        test case will be deemed to have suffered an error, exactly as for an
 
356
        unexpected exception. It returns the exception instance if it matches
 
357
        the given exception class.
 
358
        """
 
359
        try:
 
360
            result = callableObj(*args, **kwargs)
 
361
        except excClass, e:
 
362
            return e
 
363
        else:
 
364
            excName = excClass
 
365
            if hasattr(excClass, "__name__"):
 
366
                excName = excClass.__name__
 
367
            raise self.failureException(
 
368
                "%s not raised (%r returned)" % (excName, result))
 
369
 
295
370
 
296
371
    assertIs = failUnlessIs
297
372
    assertIsNot = failIfIs
304
379
    assertApproximates = failUnlessApproximates
305
380
    assertNotApproximates = failIfApproximates
306
381
    assertMethodsMatch = failUnlessMethodsMatch
 
382
    assertRaises = failUnlessRaises
307
383
 
308
384
    # The following are missing in Python < 2.4.
309
385
    assertTrue = unittest.TestCase.failUnless
570
646
            while import_stack:
571
647
                module_path = ".".join(import_stack)
572
648
                try:
573
 
                    object = __import__(module_path, {}, {}, [""])
 
649
                    __import__(module_path)
574
650
                except ImportError:
575
651
                    attr_stack.insert(0, import_stack.pop())
576
652
                    if not import_stack:
577
653
                        raise
578
654
                    continue
579
655
                else:
 
656
                    object = sys.modules[module_path]
580
657
                    for attr in attr_stack:
581
658
                        object = getattr(object, attr)
582
659
                    break
 
660
        if isinstance(object, types.UnboundMethodType):
 
661
            object = object.im_func
583
662
        if spec is True:
584
663
            spec = object
585
664
        if type is True:
669
748
        event.add_task(patcher)
670
749
        mock = Mock(self, object=object, patcher=patcher,
671
750
                    passthrough=True, spec=spec)
672
 
        object.__mocker_mock__ = mock
 
751
        patcher.patch_attr(object, '__mocker_mock__', mock)
673
752
        return mock
674
753
 
675
754
    def act(self, path):
1052
1131
            if self.__mocker__.is_recording() or self.__mocker_type__ is None:
1053
1132
                return type(self)
1054
1133
            return self.__mocker_type__
 
1134
        if name == "__length_hint__":
 
1135
            # This is used by Python 2.6+ to optimize the allocation
 
1136
            # of arrays in certain cases.  Pretend it doesn't exist.
 
1137
            raise AttributeError("No __length_hint__ here!")
1055
1138
        return self.__mocker_act__("getattr", (name,))
1056
1139
 
1057
1140
    def __setattr__(self, name, value):
1091
1174
 
1092
1175
    def __nonzero__(self):
1093
1176
        try:
1094
 
            return self.__mocker_act__("nonzero")
 
1177
            result = self.__mocker_act__("nonzero")
1095
1178
        except MatchError, e:
1096
1179
            return True
 
1180
        if type(result) is Mock:
 
1181
            return True
 
1182
        return result
1097
1183
 
1098
1184
    def __iter__(self):
1099
1185
        # XXX On py3k, when next() becomes __next__(), we'll be able
1920
2006
    for referrer in gc.get_referrers(remove):
1921
2007
        if (type(referrer) is dict and
1922
2008
            referrer.get("__mocker_replace__", True)):
1923
 
            for key, value in referrer.items():
 
2009
            for key, value in list(referrer.iteritems()):
1924
2010
                if value is remove:
1925
2011
                    referrer[key] = install
1926
2012
 
2019
2105
        try:
2020
2106
            return unpatched(*action.args, **action.kwargs)
2021
2107
        except AttributeError:
 
2108
            type, value, traceback = sys.exc_info()
2022
2109
            if action.kind == "getattr":
2023
2110
                # The normal behavior of Python is to try __getattribute__,
2024
2111
                # and if it raises AttributeError, try __getattr__.   We've
2030
2117
                    pass
2031
2118
                else:
2032
2119
                    return __getattr__(*action.args, **action.kwargs)
2033
 
            raise
 
2120
            raise type, value, traceback
2034
2121
 
2035
2122
 
2036
2123
class PatchedMethod(object):