11
11
12
12
import type { AggregatedResult } from 'types/TestResult' ;
13
13
import type { Context } from 'types/Context' ;
14
- import type { Tests } from 'types/TestRunner' ;
14
+ import type { Test , Tests } from 'types/TestRunner' ;
15
15
16
16
const fs = require ( 'fs' ) ;
17
17
const getCacheFilePath = require ( 'jest-haste-map' ) . getCacheFilePath ;
@@ -24,19 +24,31 @@ type Cache = {
24
24
} ;
25
25
26
26
class TestSequencer {
27
- _context : Context ;
28
- _cache : Cache ;
27
+ _cache : Map < Context , Cache > ;
29
28
30
- constructor ( context : Context ) {
31
- this . _context = context ;
32
- this . _cache = { } ;
29
+ constructor ( ) {
30
+ this . _cache = new Map ( ) ;
33
31
}
34
32
35
- _getTestPerformanceCachePath ( ) {
36
- const { config} = this . _context ;
33
+ _getCachePath ( context : Context ) {
34
+ const { config} = context ;
37
35
return getCacheFilePath ( config . cacheDirectory , 'perf-cache-' + config . name ) ;
38
36
}
39
37
38
+ _getCache ( test : Test ) {
39
+ const { context} = test ;
40
+ if ( ! this . _cache . has ( context ) && context . config . cache ) {
41
+ try {
42
+ this . _cache . set (
43
+ context ,
44
+ JSON . parse ( fs . readFileSync ( this . _getCachePath ( context ) , 'utf8' ) ) ,
45
+ ) ;
46
+ } catch ( e ) { }
47
+ }
48
+
49
+ return this . _cache . get ( context ) || { } ;
50
+ }
51
+
40
52
// When running more tests than we have workers available, sort the tests
41
53
// by size - big test files usually take longer to complete, so we run
42
54
// them first in an effort to minimize worker idle time at the end of a
@@ -47,62 +59,48 @@ class TestSequencer {
47
59
// fastest results.
48
60
sort ( tests : Tests ) : Tests {
49
61
const stats = { } ;
50
- const fileSize = filePath =>
51
- stats [ filePath ] || ( stats [ filePath ] = fs . statSync ( filePath ) . size ) ;
52
- const failed = filePath =>
53
- this . _cache [ filePath ] && this . _cache [ filePath ] [ 0 ] === FAIL ;
54
- const time = filePath => this . _cache [ filePath ] && this . _cache [ filePath ] [ 1 ] ;
62
+ const fileSize = test =>
63
+ stats [ test . path ] || ( stats [ test . path ] = fs . statSync ( test . path ) . size ) ;
64
+ const hasFailed = ( cache , test ) =>
65
+ cache [ test . path ] && cache [ test . path ] [ 0 ] === FAIL ;
66
+ const time = ( cache , test ) => cache [ test . path ] && cache [ test . path ] [ 1 ] ;
55
67
56
- this . _cache = { } ;
57
- try {
58
- if ( this . _context . config . cache ) {
59
- this . _cache = JSON . parse (
60
- fs . readFileSync ( this . _getTestPerformanceCachePath ( ) , 'utf8' ) ,
61
- ) ;
62
- }
63
- } catch ( e ) { }
64
-
65
- tests = tests . sort ( ( { path : pathA } , { path : pathB } ) => {
66
- const failedA = failed ( pathA ) ;
67
- const failedB = failed ( pathB ) ;
68
+ tests . forEach ( test => test . duration = time ( this . _getCache ( test ) , test ) ) ;
69
+ return tests . sort ( ( testA , testB ) => {
70
+ const cacheA = this . _getCache ( testA ) ;
71
+ const cacheB = this . _getCache ( testB ) ;
72
+ const failedA = hasFailed ( cacheA , testA ) ;
73
+ const failedB = hasFailed ( cacheB , testB ) ;
74
+ const hasTimeA = testA . duration != null ;
68
75
if ( failedA !== failedB ) {
69
76
return failedA ? - 1 : 1 ;
77
+ } else if ( hasTimeA != ( testB . duration != null ) ) {
78
+ // Check if only one of two tests has timing information
79
+ return hasTimeA != null ? 1 : - 1 ;
80
+ } else if ( testA . duration != null && testB . duration != null ) {
81
+ return testA . duration < testB . duration ? 1 : - 1 ;
82
+ } else {
83
+ return fileSize ( testA ) < fileSize ( testB ) ? 1 : - 1 ;
70
84
}
71
- const timeA = time ( pathA ) ;
72
- const timeB = time ( pathB ) ;
73
- const hasTimeA = timeA != null ;
74
- const hasTimeB = timeB != null ;
75
- // Check if only one of two tests has timing information
76
- if ( hasTimeA != hasTimeB ) {
77
- return hasTimeA ? 1 : - 1 ;
78
- }
79
- if ( timeA != null && ! timeB != null ) {
80
- return timeA < timeB ? 1 : - 1 ;
81
- }
82
- return fileSize ( pathA ) < fileSize ( pathB ) ? 1 : - 1 ;
83
85
} ) ;
84
-
85
- tests . forEach ( test => test . duration = time ( test . path ) ) ;
86
- return tests ;
87
86
}
88
87
89
88
cacheResults ( tests : Tests , results : AggregatedResult ) {
90
- const cache = this . _cache ;
91
89
const map = Object . create ( null ) ;
92
- tests . forEach ( ( { path } ) => map [ path ] = true ) ;
90
+ tests . forEach ( test => map [ test . path ] = test ) ;
93
91
results . testResults . forEach ( testResult => {
94
92
if ( testResult && map [ testResult . testFilePath ] && ! testResult . skipped ) {
93
+ const cache = this . _getCache ( map [ testResult . testFilePath ] ) ;
95
94
const perf = testResult . perfStats ;
96
95
cache [ testResult . testFilePath ] = [
97
96
testResult . numFailingTests ? FAIL : SUCCESS ,
98
97
perf . end - perf . start || 0 ,
99
98
] ;
100
99
}
101
100
} ) ;
102
- fs . writeFileSync (
103
- this . _getTestPerformanceCachePath ( ) ,
104
- JSON . stringify ( cache ) ,
105
- ) ;
101
+
102
+ this . _cache . forEach ( ( cache , context ) =>
103
+ fs . writeFileSync ( this . _getCachePath ( context ) , JSON . stringify ( cache ) ) ) ;
106
104
}
107
105
}
108
106
0 commit comments