Skip to content

Commit 53657e7

Browse files
committed
shard gl jasmine tests
1 parent 635b643 commit 53657e7

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

.circleci/test.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
set +e
55
set +o pipefail
66

7+
ROOT=$(dirname $0)/..
78
EXIT_STATE=0
89
MAX_AUTO_RETRY=5
910

@@ -34,7 +35,12 @@ case $1 in
3435
;;
3536

3637
jasmine2)
37-
retry npm run test-jasmine -- --tags=gl --skip-tags=noCI,flaky
38+
SHARDS=($(node $ROOT/tasks/shard_jasmine_tests.js --tag=gl))
39+
40+
for s in ${SHARDS[@]}; do
41+
retry npm run test-jasmine -- "$s" --tags=gl --skip-tags=noCI,flaky
42+
done
43+
3844
retry npm run test-jasmine -- --tags=flaky --skip-tags=noCI
3945
exit $EXIT_STATE
4046
;;

tasks/shard_jasmine_tests.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
var fs = require('fs');
2+
var path = require('path');
3+
4+
var falafel = require('falafel');
5+
var glob = require('glob');
6+
var minimist = require('minimist');
7+
8+
var constants = require('./util/constants');
9+
var pathToJasmineTests = constants.pathToJasmineTests;
10+
11+
var argv = minimist(process.argv.slice(2), {
12+
string: ['tag', 'limit'],
13+
alias: {
14+
tag: ['t'],
15+
limit: ['l'],
16+
},
17+
default: {
18+
limit: 20
19+
}
20+
});
21+
22+
var tag = argv.tag;
23+
var limit = argv.limit;
24+
25+
glob(path.join(pathToJasmineTests, '*.js'), function(err, files) {
26+
if(err) throw err;
27+
28+
var file2cnt = {};
29+
30+
files.forEach(function(file) {
31+
var code = fs.readFileSync(file, 'utf-8');
32+
var bn = path.basename(file);
33+
34+
falafel(code, function(node) {
35+
if(isTestDescription(node, tag)) {
36+
if(file2cnt[bn]) {
37+
file2cnt[bn]++;
38+
} else {
39+
file2cnt[bn] = 1;
40+
}
41+
}
42+
});
43+
});
44+
45+
var ranking = Object.keys(file2cnt);
46+
var runs = [];
47+
48+
// if 'it' count in file greater than threshold,
49+
// run only this file separately,
50+
// don't try to shard within file
51+
Object.keys(file2cnt).forEach(function(f) {
52+
if(file2cnt[f] > limit) {
53+
runs.push(f);
54+
ranking.splice(ranking.indexOf(f), 1);
55+
}
56+
});
57+
58+
// sort ranking in decreasing order
59+
ranking.sort(function(a, b) { return file2cnt[b] - file2cnt[a]; });
60+
61+
var runi;
62+
var cnt;
63+
64+
function newRun() {
65+
var r0 = ranking[0];
66+
runi = [r0];
67+
cnt = file2cnt[r0];
68+
ranking.shift();
69+
}
70+
71+
function concat() {
72+
runs.push(runi.join(','));
73+
}
74+
75+
// try to match files with many tests with files not-that-many,
76+
// by matching first rank with one or multiple trailing ranks.
77+
newRun();
78+
while(ranking.length) {
79+
var rn = ranking[ranking.length - 1];
80+
81+
if((cnt + file2cnt[rn]) > limit) {
82+
concat();
83+
newRun();
84+
} else {
85+
runi.push(rn);
86+
cnt += file2cnt[rn];
87+
ranking.pop();
88+
}
89+
}
90+
concat();
91+
92+
// print result to stdout
93+
console.log(runs.join('\n'));
94+
});
95+
96+
function isTestDescription(node, tag) {
97+
var isDescription = (
98+
node.type === 'Literal' &&
99+
node.parent &&
100+
node.parent.type === 'CallExpression' &&
101+
node.parent.callee &&
102+
node.parent.callee.type === 'Identifier' &&
103+
node.parent.callee.name === 'it'
104+
);
105+
106+
if(!tag) return isDescription;
107+
108+
return (
109+
isDescription &&
110+
node.source().indexOf('@' + tag) !== -1
111+
);
112+
}

0 commit comments

Comments
 (0)