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

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

""" 

Test Selection 

-------------- 

 

Test selection is handled by a Selector. The test loader calls the 

appropriate selector method for each object it encounters that it 

thinks may be a test. 

""" 

import logging 

import os 

import unittest 

from nose.config import Config 

from nose.util import split_test_name, src, getfilename, getpackage, ispackage, is_executable 

 

log = logging.getLogger(__name__) 

 

__all__ = ['Selector', 'defaultSelector', 'TestAddress'] 

 

 

# for efficiency and easier mocking 

op_join = os.path.join 

op_basename = os.path.basename 

op_exists = os.path.exists 

op_splitext = os.path.splitext 

op_isabs = os.path.isabs 

op_abspath = os.path.abspath 

 

 

class Selector(object): 

"""Core test selector. Examines test candidates and determines whether, 

given the specified configuration, the test candidate should be selected 

as a test. 

""" 

def __init__(self, config): 

if config is None: 

config = Config() 

self.configure(config) 

 

def configure(self, config): 

self.config = config 

self.exclude = config.exclude 

self.ignoreFiles = config.ignoreFiles 

self.include = config.include 

self.plugins = config.plugins 

self.match = config.testMatch 

 

def matches(self, name): 

"""Does the name match my requirements? 

 

To match, a name must match config.testMatch OR config.include 

and it must not match config.exclude 

""" 

return ((self.match.search(name) 

or (self.include and 

[_f for _f in [inc.search(name) for inc in self.include] if _f])) 

and ((not self.exclude) 

or not [_f for _f in [exc.search(name) for exc in self.exclude] if _f] 

)) 

 

def wantClass(self, cls): 

"""Is the class a wanted test class? 

 

A class must be a unittest.TestCase subclass, or match test name 

requirements. Classes that start with _ are always excluded. 

""" 

declared = getattr(cls, '__test__', None) 

if declared is not None: 

wanted = declared 

else: 

wanted = (not cls.__name__.startswith('_') 

and (issubclass(cls, unittest.TestCase) 

or self.matches(cls.__name__))) 

 

plug_wants = self.plugins.wantClass(cls) 

if plug_wants is not None: 

log.debug("Plugin setting selection of %s to %s", cls, plug_wants) 

wanted = plug_wants 

log.debug("wantClass %s? %s", cls, wanted) 

return wanted 

 

def wantDirectory(self, dirname): 

"""Is the directory a wanted test directory? 

 

All package directories match, so long as they do not match exclude.  

All other directories must match test requirements. 

""" 

tail = op_basename(dirname) 

if ispackage(dirname): 

wanted = (not self.exclude 

or not [_f for _f in [exc.search(tail) for exc in self.exclude] if _f]) 

else: 

wanted = (self.matches(tail) 

or (self.config.srcDirs 

and tail in self.config.srcDirs)) 

plug_wants = self.plugins.wantDirectory(dirname) 

if plug_wants is not None: 

log.debug("Plugin setting selection of %s to %s", 

dirname, plug_wants) 

wanted = plug_wants 

log.debug("wantDirectory %s? %s", dirname, wanted) 

return wanted 

 

def wantFile(self, file): 

"""Is the file a wanted test file? 

 

The file must be a python source file and match testMatch or 

include, and not match exclude. Files that match ignore are *never* 

wanted, regardless of plugin, testMatch, include or exclude settings. 

""" 

# never, ever load files that match anything in ignore 

# (.* _* and *setup*.py by default) 

base = op_basename(file) 

ignore_matches = [ ignore_this for ignore_this in self.ignoreFiles 

if ignore_this.search(base) ] 

if ignore_matches: 

log.debug('%s matches ignoreFiles pattern; skipped', 

base) 

return False 

if not self.config.includeExe and is_executable(file): 

log.info('%s is executable; skipped', file) 

return False 

dummy, ext = op_splitext(base) 

pysrc = ext == '.py' 

 

wanted = pysrc and self.matches(base) 

plug_wants = self.plugins.wantFile(file) 

if plug_wants is not None: 

log.debug("plugin setting want %s to %s", file, plug_wants) 

wanted = plug_wants 

log.debug("wantFile %s? %s", file, wanted) 

return wanted 

 

def wantFunction(self, function): 

"""Is the function a test function? 

""" 

try: 

if hasattr(function, 'compat_func_name'): 

funcname = function.compat_func_name 

else: 

funcname = function.__name__ 

except AttributeError: 

# not a function 

return False 

declared = getattr(function, '__test__', None) 

if declared is not None: 

wanted = declared 

else: 

wanted = not funcname.startswith('_') and self.matches(funcname) 

plug_wants = self.plugins.wantFunction(function) 

if plug_wants is not None: 

wanted = plug_wants 

log.debug("wantFunction %s? %s", function, wanted) 

return wanted 

 

def wantMethod(self, method): 

"""Is the method a test method? 

""" 

try: 

method_name = method.__name__ 

except AttributeError: 

# not a method 

return False 

if method_name.startswith('_'): 

# never collect 'private' methods 

return False 

declared = getattr(method, '__test__', None) 

if declared is not None: 

wanted = declared 

else: 

wanted = self.matches(method_name) 

plug_wants = self.plugins.wantMethod(method) 

if plug_wants is not None: 

wanted = plug_wants 

log.debug("wantMethod %s? %s", method, wanted) 

return wanted 

 

def wantModule(self, module): 

"""Is the module a test module? 

 

The tail of the module name must match test requirements. One exception: 

we always want __main__. 

""" 

declared = getattr(module, '__test__', None) 

if declared is not None: 

wanted = declared 

else: 

wanted = self.matches(module.__name__.split('.')[-1]) \ 

or module.__name__ == '__main__' 

plug_wants = self.plugins.wantModule(module) 

if plug_wants is not None: 

wanted = plug_wants 

log.debug("wantModule %s? %s", module, wanted) 

return wanted 

 

defaultSelector = Selector 

 

 

class TestAddress(object): 

"""A test address represents a user's request to run a particular 

test. The user may specify a filename or module (or neither), 

and/or a callable (a class, function, or method). The naming 

format for test addresses is: 

 

filename_or_module:callable 

 

Filenames that are not absolute will be made absolute relative to 

the working dir. 

 

The filename or module part will be considered a module name if it 

doesn't look like a file, that is, if it doesn't exist on the file 

system and it doesn't contain any directory separators and it 

doesn't end in .py. 

 

Callables may be a class name, function name, method name, or 

class.method specification. 

""" 

def __init__(self, name, workingDir=None): 

if workingDir is None: 

workingDir = os.getcwd() 

self.name = name 

self.workingDir = workingDir 

self.filename, self.module, self.call = split_test_name(name) 

log.debug('Test name %s resolved to file %s, module %s, call %s', 

name, self.filename, self.module, self.call) 

if self.filename is None: 

if self.module is not None: 

self.filename = getfilename(self.module, self.workingDir) 

if self.filename: 

self.filename = src(self.filename) 

if not op_isabs(self.filename): 

self.filename = op_abspath(op_join(workingDir, 

self.filename)) 

if self.module is None: 

self.module = getpackage(self.filename) 

log.debug( 

'Final resolution of test name %s: file %s module %s call %s', 

name, self.filename, self.module, self.call) 

 

def totuple(self): 

return (self.filename, self.module, self.call) 

 

def __str__(self): 

return self.name 

 

def __repr__(self): 

return "%s: (%s, %s, %s)" % (self.name, self.filename, 

self.module, self.call)