0
# Test Discovery and Loading
1
2
Green's enhanced test discovery system provides comprehensive test loading capabilities with pattern matching, module loading, and Green-specific test suite creation with filtering and customization.
3
4
## Capabilities
5
6
### Green Test Loader
7
8
Enhanced test loader that extends unittest.TestLoader with Green-specific functionality for parallel execution and advanced test discovery.
9
10
```python { .api }
11
class GreenTestLoader(unittest.TestLoader):
12
"""
13
Enhanced test loader with Green-specific features.
14
15
Extends unittest.TestLoader to provide:
16
- Parallel-friendly test loading
17
- Custom test suite creation
18
- Enhanced discovery patterns
19
- Integration with Green's configuration system
20
"""
21
22
def loadTargets(self, targets, file_pattern='test*.py'):
23
"""
24
Load tests from multiple target specifications.
25
26
Args:
27
targets (list): List of test targets. Can be:
28
- Directory paths: 'tests/', 'src/tests'
29
- Module names: 'tests.test_module'
30
- Class names: 'tests.test_module.TestClass'
31
- Method names: 'tests.test_module.TestClass.test_method'
32
- File paths: 'tests/test_file.py'
33
file_pattern (str): Pattern for test files (default: 'test*.py')
34
35
Returns:
36
GreenTestSuite or None: Test suite containing all loaded tests,
37
or None if no tests found
38
39
Example:
40
loader = GreenTestLoader()
41
suite = loader.loadTargets(['tests/', 'integration/'])
42
if suite:
43
print(f"Loaded {suite.countTestCases()} tests")
44
"""
45
46
def loadTarget(self, target, file_pattern='test*.py'):
47
"""
48
Load tests from a single target specification.
49
50
Args:
51
target (str): Single test target (directory, module, class, or method)
52
file_pattern (str): Pattern for test files
53
54
Returns:
55
GreenTestSuite or None: Test suite for the target
56
57
Example:
58
loader = GreenTestLoader()
59
suite = loader.loadTarget('tests.test_auth.TestLogin.test_valid_credentials')
60
"""
61
62
def discover(self, current_path, file_pattern='test*.py', top_level_dir=None):
63
"""
64
Discover tests in a directory structure.
65
66
Args:
67
current_path (str): Directory to search for tests
68
file_pattern (str): Pattern to match test files (default: 'test*.py')
69
top_level_dir (str, optional): Top-level directory for imports
70
71
Returns:
72
GreenTestSuite or None: Discovered tests
73
74
Example:
75
loader = GreenTestLoader()
76
suite = loader.discover('tests', file_pattern='*_test.py')
77
"""
78
79
def loadTestsFromTestCase(self, testCaseClass):
80
"""
81
Load tests from a test case class.
82
83
Args:
84
testCaseClass: unittest.TestCase subclass
85
86
Returns:
87
GreenTestSuite: Test suite containing tests from the class
88
"""
89
90
def loadFromModuleFilename(self, filename):
91
"""
92
Load tests from a module filename.
93
94
Args:
95
filename (str): Path to Python module file
96
97
Returns:
98
TestSuite: Loaded tests from the module
99
"""
100
101
def loadTestsFromModule(self, module, pattern=None):
102
"""
103
Load tests from a Python module.
104
105
Args:
106
module: Python module object
107
pattern (str, optional): Pattern to filter test methods
108
109
Returns:
110
GreenTestSuite: Tests loaded from the module
111
"""
112
113
def loadTestsFromName(self, name, module=None):
114
"""
115
Load tests from a dotted name specification.
116
117
Args:
118
name (str): Dotted name (e.g., 'tests.test_module.TestClass.test_method')
119
module (optional): Module to use as context for relative names
120
121
Returns:
122
GreenTestSuite: Loaded tests
123
"""
124
```
125
126
## Helper Functions
127
128
### Test Suite Manipulation
129
130
```python { .api }
131
def toProtoTestList(suite, test_list=None, doing_completions=False):
132
"""
133
Convert test suite to list of ProtoTest objects for multiprocessing.
134
135
Args:
136
suite: Test suite to convert
137
test_list (list, optional): Existing list to append to
138
doing_completions (bool): Whether this is for shell completions
139
140
Returns:
141
list: List of ProtoTest objects
142
"""
143
144
def toParallelTargets(suite, targets):
145
"""
146
Convert test suite to parallel-execution-friendly target list.
147
148
Args:
149
suite: Test suite to convert
150
targets: Original target specifications
151
152
Returns:
153
list: List of target strings suitable for parallel execution
154
"""
155
156
def flattenTestSuite(test_suite, module=None):
157
"""
158
Flatten nested test suites into a single GreenTestSuite.
159
160
Args:
161
test_suite: Test suite to flatten
162
module (optional): Module context
163
164
Returns:
165
GreenTestSuite: Flattened test suite
166
"""
167
```
168
169
### Shell Completion Support
170
171
```python { .api }
172
def getCompletions(target):
173
"""
174
Get shell completion suggestions for a test target.
175
176
Args:
177
target (str): Partial test target for completion
178
179
Returns:
180
str: Newline-separated completion suggestions
181
182
Example:
183
completions = getCompletions('tests.test_')
184
# Returns possible completions like:
185
# tests.test_auth
186
# tests.test_models
187
# tests.test_views
188
"""
189
```
190
191
### Module and Package Detection
192
193
```python { .api }
194
def findDottedModuleAndParentDir(file_path):
195
"""
196
Find the dotted module name and parent directory for a file path.
197
198
Args:
199
file_path (str): Path to Python file
200
201
Returns:
202
tuple: (dotted_module_name, parent_directory)
203
204
Example:
205
module, parent = findDottedModuleAndParentDir('/project/tests/test_auth.py')
206
# Returns: ('tests.test_auth', '/project')
207
"""
208
209
def isPackage(file_path):
210
"""
211
Check if a file path represents a Python package.
212
213
Args:
214
file_path (str): Path to check
215
216
Returns:
217
bool: True if path is a package (directory with __init__.py)
218
"""
219
220
def isTestCaseDisabled(test_case_class, method_name):
221
"""
222
Check if a test case method is disabled.
223
224
Args:
225
test_case_class: TestCase class
226
method_name (str): Name of test method
227
228
Returns:
229
bool: True if test method is disabled
230
"""
231
```
232
233
## Usage Examples
234
235
### Basic Test Loading
236
237
```python
238
from green.loader import GreenTestLoader
239
240
# Create loader
241
loader = GreenTestLoader()
242
243
# Load from directory
244
suite = loader.loadTargets(['tests/'])
245
print(f"Found {suite.countTestCases()} tests")
246
247
# Load specific module
248
suite = loader.loadTarget('tests.test_authentication')
249
250
# Load specific test class
251
suite = loader.loadTarget('tests.test_models.UserModelTest')
252
253
# Load specific test method
254
suite = loader.loadTarget('tests.test_views.LoginViewTest.test_valid_login')
255
```
256
257
### Advanced Discovery Patterns
258
259
```python
260
from green.loader import GreenTestLoader
261
262
loader = GreenTestLoader()
263
264
# Custom file patterns
265
suite = loader.discover('tests', file_pattern='*_test.py')
266
suite = loader.discover('tests', file_pattern='test_*.py')
267
268
# Multiple targets with different patterns
269
targets = ['unit_tests/', 'integration_tests/', 'tests/test_specific.py']
270
suite = loader.loadTargets(targets, file_pattern='*.py')
271
```
272
273
### Integration with Configuration
274
275
```python
276
from green.config import parseArguments, mergeConfig
277
from green.loader import GreenTestLoader
278
279
# Use configuration-driven loading
280
args = parseArguments(['tests/', '--file-pattern', '*_test.py'])
281
config = mergeConfig(args)
282
283
loader = GreenTestLoader()
284
suite = loader.loadTargets(config.targets, config.file_pattern)
285
```
286
287
### Working with Test Suite Results
288
289
```python
290
from green.loader import GreenTestLoader, toProtoTestList, flattenTestSuite
291
292
loader = GreenTestLoader()
293
suite = loader.loadTargets(['tests/'])
294
295
# Convert to proto tests for multiprocessing
296
proto_tests = toProtoTestList(suite)
297
print(f"Proto tests: {len(proto_tests)}")
298
299
# Flatten nested suites
300
flat_suite = flattenTestSuite(suite)
301
print(f"Flattened: {flat_suite.countTestCases()} tests")
302
```
303
304
### Shell Completion Integration
305
306
```python
307
from green.loader import getCompletions
308
309
# Get completions for partial target
310
completions = getCompletions('tests.test_')
311
print("Available completions:")
312
for completion in completions.split('\n'):
313
if completion.strip():
314
print(f" {completion}")
315
```
316
317
### Custom Test Loading Scenarios
318
319
```python
320
from green.loader import GreenTestLoader, findDottedModuleAndParentDir, isPackage
321
322
loader = GreenTestLoader()
323
324
# Load tests from specific file paths
325
test_files = ['/project/tests/test_auth.py', '/project/tests/test_models.py']
326
suites = []
327
for file_path in test_files:
328
if file_path.endswith('.py'):
329
# Convert file path to module name
330
module_name, parent_dir = findDottedModuleAndParentDir(file_path)
331
suite = loader.loadTarget(module_name)
332
if suite:
333
suites.append(suite)
334
335
# Combine all suites
336
if suites:
337
main_suite = suites[0]
338
for suite in suites[1:]:
339
main_suite.addTest(suite)
340
```
341
342
### Error Handling
343
344
```python
345
from green.loader import GreenTestLoader
346
347
loader = GreenTestLoader()
348
349
try:
350
suite = loader.loadTargets(['nonexistent_tests/'])
351
if suite is None:
352
print("No tests found in specified targets")
353
elif suite.countTestCases() == 0:
354
print("Test suite is empty")
355
else:
356
print(f"Successfully loaded {suite.countTestCases()} tests")
357
except ImportError as e:
358
print(f"Failed to import test module: {e}")
359
except Exception as e:
360
print(f"Error loading tests: {e}")
361
```
362
363
## Test Discovery Patterns
364
365
Green supports various test discovery patterns:
366
367
### Standard Patterns
368
- `test*.py` - Files starting with "test"
369
- `*test.py` - Files ending with "test"
370
- `*_test.py` - Files ending with "_test"
371
- `test_*.py` - Files starting with "test_"
372
373
### Target Types
374
- **Directories**: `tests/`, `src/tests/`
375
- **Modules**: `tests.test_auth`, `mypackage.tests.test_models`
376
- **Classes**: `tests.test_auth.AuthenticationTest`
377
- **Methods**: `tests.test_auth.AuthenticationTest.test_login`
378
- **Files**: `tests/test_auth.py`, `/absolute/path/to/test.py`
379
380
### DocTest Integration
381
382
```python
383
# In test modules, specify doctests to run
384
doctest_modules = ['mypackage.utils', 'mypackage.helpers']
385
386
# Green will automatically discover and run doctests from these modules
387
```