@@ -53,20 +53,21 @@ MTAnalysis >> coverageAnalysisResult: anObject [
53
53
54
54
{ #category : ' accessing - defaults' }
55
55
MTAnalysis >> defaultBudget [
56
+ " Since tests often take little time to run, we multiply it by 30"
56
57
57
- ^ MTFreeBudget new
58
+ ^ MTTimeBudget for: self totalTestsTime * 30
58
59
]
59
60
60
61
{ #category : ' accessing - defaults' }
61
62
MTAnalysis >> defaultLogger [
62
63
63
- ^ MTNullLogger new
64
+ ^ MTTranscriptLogger new
64
65
]
65
66
66
67
{ #category : ' accessing - defaults' }
67
68
MTAnalysis >> defaultMutantGenerationStrategy [
68
69
69
- ^ MTAllMutantGenerationStrategy new
70
+ ^ MTAllMutantGenerationStrategy withRandomOperatorMutantSelection
70
71
]
71
72
72
73
{ #category : ' accessing - defaults' }
@@ -78,13 +79,20 @@ MTAnalysis >> defaultOperators [
78
79
{ #category : ' accessing - defaults' }
79
80
MTAnalysis >> defaultTestFilter [
80
81
81
- ^ MTFreeTestFilter new
82
+ | times |
83
+ times := testCases collect: #lastTimeToRun .
84
+ (times anySatisfy: #isNil ) ifTrue: [
85
+ ^ Error signal :
86
+ ' Either there is no test cases, or the initial test run has not been executed yet' ].
87
+ ^ MTCompositeTestFilter for: {
88
+ MTRedTestFilter new .
89
+ (MTTimeTestFilter for: (self percentile: 90 for: times sorted)) }
82
90
]
83
91
84
92
{ #category : ' accessing - defaults' }
85
93
MTAnalysis >> defaultTestSelectionStrategy [
86
94
87
- ^ MTAllTestsMethodsRunningTestSelectionStrategy new
95
+ ^ MTSelectingFromCoverageTestSelectionStrategy new
88
96
]
89
97
90
98
{ #category : ' accessing' }
@@ -151,7 +159,9 @@ MTAnalysis >> initialTestRun [
151
159
152
160
| results |
153
161
results := testCases collect: [ :aTestCase | aTestCase run ].
154
- testFilter validateFailuresIn: results.
162
+
163
+ " The test filter is initialized lazily here because the default one needs the run time of tests, so the initial test run must be executed first"
164
+ self testFilter validateFailuresIn: results.
155
165
testCases := testFilter filterTests: testCases
156
166
]
157
167
@@ -165,8 +175,6 @@ MTAnalysis >> initialize [
165
175
mutantResults := OrderedCollection new .
166
176
elapsedTime := 0 .
167
177
logger := self defaultLogger.
168
- budget := self defaultBudget.
169
- testFilter := self defaultTestFilter.
170
178
stopOnErrorOrFail := true
171
179
]
172
180
@@ -223,6 +231,13 @@ MTAnalysis >> mutations: anObject [
223
231
mutations := anObject
224
232
]
225
233
234
+ { #category : ' initialization' }
235
+ MTAnalysis >> noLimitations [
236
+
237
+ budget := MTFreeBudget new .
238
+ testFilter := MTFreeTestFilter new
239
+ ]
240
+
226
241
{ #category : ' accessing' }
227
242
MTAnalysis >> operators [
228
243
@@ -242,6 +257,17 @@ MTAnalysis >> packagesToMutate: aCollectionOfPackages [
242
257
packageName asPackage definedClasses ]
243
258
]
244
259
260
+ { #category : ' computing' }
261
+ MTAnalysis >> percentile: aPercentage for: aCollection [
262
+
263
+ | size index |
264
+ aCollection isEmpty ifTrue: [
265
+ ^ CollectionIsEmpty signalWith: aCollection ].
266
+ size := aCollection size.
267
+ index := (aPercentage percent * size) rounded.
268
+ ^ aCollection at: index
269
+ ]
270
+
245
271
{ #category : ' running' }
246
272
MTAnalysis >> run [
247
273
" Obtain mutants applying the operators in the classes (or
@@ -250,8 +276,9 @@ MTAnalysis >> run [
250
276
We obtain a result for each mutant generated"
251
277
252
278
^ [
253
- budget start.
254
279
self initialTestRun.
280
+ " The budget is started after the initial test run because the default one needs the run time of tests"
281
+ self startBudget.
255
282
logger logAnalysisStartFor: self .
256
283
elapsedTime := [
257
284
self generateCoverageAnalysis.
@@ -265,6 +292,14 @@ MTAnalysis >> run [
265
292
false ]
266
293
]
267
294
295
+ { #category : ' starting' }
296
+ MTAnalysis >> startBudget [
297
+ " The budget is initialized here because the default one needs the run time of tests, so the initial test run must be executed first"
298
+
299
+ budget ifNil: [ budget := self defaultBudget ].
300
+ budget start
301
+ ]
302
+
268
303
{ #category : ' accessing' }
269
304
MTAnalysis >> stopOnErrorOrFail: aBoolean [
270
305
@@ -292,12 +327,17 @@ MTAnalysis >> testCases: anObject [
292
327
{ #category : ' accessing' }
293
328
MTAnalysis >> testCasesFrom: aClassCollection [
294
329
295
- ^ aClassCollection
296
- inject: OrderedCollection new
297
- into: [ :testCase :testClass |
298
- testClass isAbstract ifFalse: [
299
- testCase addAll: (self testCasesReferencesFrom: testClass) ].
300
- testCase ]
330
+ | tests |
331
+ tests := aClassCollection
332
+ inject: OrderedCollection new
333
+ into: [ :testCase :testClass |
334
+ testClass isAbstract ifFalse: [
335
+ testCase addAll:
336
+ (self testCasesReferencesFrom: testClass) ].
337
+ testCase ].
338
+ tests isEmpty ifTrue: [
339
+ Warning signal : ' There is currently no tests' ].
340
+ ^ tests
301
341
]
302
342
303
343
{ #category : ' tests' }
@@ -316,7 +356,7 @@ MTAnalysis >> testClasses: aClassCollection [
316
356
{ #category : ' accessing' }
317
357
MTAnalysis >> testFilter [
318
358
319
- ^ testFilter
359
+ ^ testFilter ifNil: [ testFilter := self defaultTestFilter ]
320
360
]
321
361
322
362
{ #category : ' accessing' }
@@ -346,3 +386,13 @@ MTAnalysis >> testSelectionStrategy: anObject [
346
386
347
387
testSelectionStrategy := anObject
348
388
]
389
+
390
+ { #category : ' accessing' }
391
+ MTAnalysis >> totalTestsTime [
392
+
393
+ | times |
394
+ times := testCases collect: #lastTimeToRun .
395
+ (times anySatisfy: #isNil ) ifTrue: [
396
+ ^ Error signal : ' The initial test run has not been executed yet' ].
397
+ ^ times reduce: [ :t1 :t2 | t1 + t2 ]
398
+ ]
0 commit comments