Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

""" discovery and running of std-library "unittest" style tests. """ 

from __future__ import absolute_import 

 

import sys 

import traceback 

 

import pytest 

# for transfering markers 

import _pytest._code 

from _pytest.python import transfer_markers 

from _pytest.skipping import MarkEvaluator 

 

 

def pytest_pycollect_makeitem(collector, name, obj): 

    # has unittest been imported and is obj a subclass of its TestCase? 

    try: 

        if not issubclass(obj, sys.modules["unittest"].TestCase): 

            return 

    except Exception: 

        return 

    # yes, so let's collect it 

    return UnitTestCase(name, parent=collector) 

 

 

class UnitTestCase(pytest.Class): 

    # marker for fixturemanger.getfixtureinfo() 

    # to declare that our children do not support funcargs 

    nofuncargs = True 

 

    def setup(self): 

        cls = self.obj 

33        if getattr(cls, '__unittest_skip__', False): 

            return  # skipped 

        setup = getattr(cls, 'setUpClass', None) 

37        if setup is not None: 

            setup() 

        teardown = getattr(cls, 'tearDownClass', None) 

40        if teardown is not None: 

            self.addfinalizer(teardown) 

        super(UnitTestCase, self).setup() 

 

    def collect(self): 

        from unittest import TestLoader 

        cls = self.obj 

46        if not getattr(cls, "__test__", True): 

            return 

        self.session._fixturemanager.parsefactories(self, unittest=True) 

        loader = TestLoader() 

        module = self.getparent(pytest.Module).obj 

        foundsomething = False 

        for name in loader.getTestCaseNames(self.obj): 

            x = getattr(self.obj, name) 

            funcobj = getattr(x, 'im_func', x) 

            transfer_markers(funcobj, cls, module) 

            yield TestCaseFunction(name, parent=self) 

            foundsomething = True 

 

59        if not foundsomething: 

            runtest = getattr(self.obj, 'runTest', None) 

            if runtest is not None: 

                ut = sys.modules.get("twisted.trial.unittest", None) 

                if ut is None or runtest != ut.TestCase.runTest: 

                    yield TestCaseFunction('runTest', parent=self) 

 

 

 

class TestCaseFunction(pytest.Function): 

    _excinfo = None 

 

    def setup(self): 

        self._testcase = self.parent.obj(self.name) 

        self._fix_unittest_skip_decorator() 

        self._obj = getattr(self._testcase, self.name) 

75        if hasattr(self._testcase, 'setup_method'): 

            self._testcase.setup_method(self._obj) 

exit        if hasattr(self, "_request"): 

            self._request._fillfixtures() 

 

    def _fix_unittest_skip_decorator(self): 

        """ 

        The @unittest.skip decorator calls functools.wraps(self._testcase) 

        The call to functools.wraps() fails unless self._testcase 

        has a __name__ attribute. This is usually automatically supplied 

        if the test is a function or method, but we need to add manually 

        here. 

 

        See issue #1169 

        """ 

exit        if sys.version_info[0] == 2: 

            setattr(self._testcase, "__name__", self.name) 

 

    def teardown(self): 

94        if hasattr(self._testcase, 'teardown_method'): 

            self._testcase.teardown_method(self._obj) 

 

    def startTest(self, testcase): 

        pass 

 

    def _addexcinfo(self, rawexcinfo): 

        # unwrap potential exception info (see twisted trial support below) 

        rawexcinfo = getattr(rawexcinfo, '_rawexcinfo', rawexcinfo) 

        try: 

            excinfo = _pytest._code.ExceptionInfo(rawexcinfo) 

        except TypeError: 

            try: 

                try: 

                    l = traceback.format_exception(*rawexcinfo) 

                    l.insert(0, "NOTE: Incompatible Exception Representation, " 

                        "displaying natively:\n\n") 

                    pytest.fail("".join(l), pytrace=False) 

                except (pytest.fail.Exception, KeyboardInterrupt): 

                    raise 

                except: 

                    pytest.fail("ERROR: Unknown Incompatible Exception " 

                        "representation:\n%r" %(rawexcinfo,), pytrace=False) 

            except KeyboardInterrupt: 

                raise 

            except pytest.fail.Exception: 

                excinfo = _pytest._code.ExceptionInfo() 

        self.__dict__.setdefault('_excinfo', []).append(excinfo) 

 

    def addError(self, testcase, rawexcinfo): 

        self._addexcinfo(rawexcinfo) 

    def addFailure(self, testcase, rawexcinfo): 

        self._addexcinfo(rawexcinfo) 

 

    def addSkip(self, testcase, reason): 

        try: 

            pytest.skip(reason) 

        except pytest.skip.Exception: 

            self._evalskip = MarkEvaluator(self, 'SkipTest') 

            self._evalskip.result = True 

            self._addexcinfo(sys.exc_info()) 

 

    def addExpectedFailure(self, testcase, rawexcinfo, reason=""): 

        try: 

            pytest.xfail(str(reason)) 

        except pytest.xfail.Exception: 

            self._addexcinfo(sys.exc_info()) 

 

    def addUnexpectedSuccess(self, testcase, reason=""): 

        self._unexpectedsuccess = reason 

 

    def addSuccess(self, testcase): 

        pass 

 

    def stopTest(self, testcase): 

        pass 

 

    def runtest(self): 

        self._testcase(result=self) 

 

    def _prunetraceback(self, excinfo): 

        pytest.Function._prunetraceback(self, excinfo) 

        traceback = excinfo.traceback.filter( 

            lambda x:not x.frame.f_globals.get('__unittest')) 

        if traceback: 

            excinfo.traceback = traceback 

 

@pytest.hookimpl(tryfirst=True) 

def pytest_runtest_makereport(item, call): 

exit    if isinstance(item, TestCaseFunction): 

164        if item._excinfo: 

            call.excinfo = item._excinfo.pop(0) 

            try: 

                del call.result 

            except AttributeError: 

                pass 

 

# twisted trial support 

 

@pytest.hookimpl(hookwrapper=True) 

def pytest_runtest_protocol(item): 

176    if isinstance(item, TestCaseFunction) and \ 

       'twisted.trial.unittest' in sys.modules: 

        ut = sys.modules['twisted.python.failure'] 

        Failure__init__ = ut.Failure.__init__ 

        check_testcase_implements_trial_reporter() 

        def excstore(self, exc_value=None, exc_type=None, exc_tb=None, 

            captureVars=None): 

            if exc_value is None: 

                self._rawexcinfo = sys.exc_info() 

            else: 

                if exc_type is None: 

                    exc_type = type(exc_value) 

                self._rawexcinfo = (exc_type, exc_value, exc_tb) 

            try: 

                Failure__init__(self, exc_value, exc_type, exc_tb, 

                    captureVars=captureVars) 

            except TypeError: 

                Failure__init__(self, exc_value, exc_type, exc_tb) 

        ut.Failure.__init__ = excstore 

        yield 

        ut.Failure.__init__ = Failure__init__ 

    else: 

        yield 

 

 

def check_testcase_implements_trial_reporter(done=[]): 

    if done: 

        return 

    from zope.interface import classImplements 

    from twisted.trial.itrial import IReporter 

    classImplements(TestCaseFunction, IReporter) 

    done.append(1)