forked from tnicola/cypress-parallel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test-suites.js
128 lines (108 loc) · 3.46 KB
/
test-suites.js
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
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const { settings } = require('./settings');
const getFilePathsByPath = (dir) =>
fs.readdirSync(dir).reduce((files, file) => {
const name = path.join(dir, file);
const isDirectory = fs.statSync(name).isDirectory();
if (isDirectory) return [...files, ...getFilePathsByPath(name)];
return [...files, name];
}, []);
const getFilePathsByGlob = (pattern) => {
const globOptions = {};
return new Promise((resolve, reject) => {
glob(pattern, globOptions, function (error, files) {
if (error) {
reject(error);
throw error;
}
resolve(files);
});
});
};
async function getTestSuitePaths() {
const isPattern = settings.testSuitesPath.includes('*');
let fileList;
if (isPattern) {
console.log(`Using pattern ${settings.testSuitesPath} to find test suites`);
fileList = await getFilePathsByGlob(settings.testSuitesPath);
} else {
console.log(
'DEPRECATED: using path is deprecated and will be removed, switch to glob pattern'
);
fileList = getFilePathsByPath(settings.testSuitesPath);
}
console.log(`${fileList.length} test suite(s) found.`);
if (settings.isVerbose) {
console.log('Paths to found suites');
console.log(JSON.stringify(fileList, null, 2));
}
// We can't run more threads than suites
if (fileList.length < settings.threadCount) {
console.log(`Thread setting is ${settings.threadCount}, but only ${fileList.length} test suite(s) were found. Adjusting configuration accordingly.`)
settings.threadCount = fileList.length
}
return fileList;
}
function distributeTestsByWeight(testSuitePaths) {
let specWeights = {};
try {
specWeights = JSON.parse(fs.readFileSync(settings.weightsJSON, 'utf8'));
} catch (err) {
console.log(`Weight file not found in path: ${settings.weightsJSON}`);
}
let map = new Map();
for (let f of testSuitePaths) {
let specWeight = settings.defaultWeight;
Object.keys(specWeights).forEach((spec) => {
if (f.endsWith(spec)) {
specWeight = specWeights[spec].weight;
}
});
map.set(f, specWeight);
}
map = new Map([...map.entries()].sort((a, b) => b[1] - a[1]));
const threads = [];
for (let i = 0; i < settings.threadCount; i++) {
threads.push({
weight: 0,
list: []
});
}
for (const [key, value] of map.entries()) {
threads.sort((w1, w2) => w1.weight - w2.weight);
threads[0].list.push(key);
threads[0].weight += +value;
}
// Run slowest group first
threads.sort((a, b) => b.weight - a.weight);
return threads;
}
function distributeTestsBySpecGroups(testSuitePaths) {
const groupPaths = settings.testSuitesPathGroups.split(";").map(paths => paths.split(','));
if (groupPaths.length != settings.threadCount) {
throw `Test groups paths should be same length as thread count. Got ${groupPaths.length} instead of ${settings.threadCount}`;
}
const threads = [];
for (let i = 0; i < settings.threadCount; i++) {
threads.push({
list: []
});
}
testSuitePaths.forEach((path) => {
for (let i = 0; i < groupPaths.length; i++) {
const belongsToThisGroup = groupPaths[i].some((groupPath => path.startsWith(groupPath)));
if(belongsToThisGroup) {
threads[i].list.push(path);
return;
}
}
});
return threads;
}
module.exports = {
getTestSuitePaths,
distributeTestsByWeight,
distributeTestsBySpecGroups
};