mocha-distributed 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -148,16 +148,29 @@ You will see something like this on each of the items of the list:
148
148
  "type": "test",
149
149
  "title": "test-1.1-async",
150
150
  "timedOut": false,
151
+ "startTime": 1642705594300,
152
+ "endTime": 1642705594802,
151
153
  "duration": 502,
152
154
  "file": "/home/psanchez/github/mocha-distributed/example/suite-1.js",
153
155
  "state": "passed",
156
+ "failed": false,
154
157
  "speed": "slow",
155
158
  "err": 0
156
- }```
159
+ }
160
+ ```
157
161
 
158
162
  The JSON formatting will differ since it is saved in a single line.
159
163
 
160
- Apart of test_result you can also access passed_count and failed_count
164
+ Keep in mind that:
165
+
166
+ * Duration and start/end times are in milliseconds.
167
+ * Some fields are duplicated in a way, like "state" and "failed" by design
168
+ because sometimes is handy to have this when reading results back.
169
+ * You can access test_result, passed_count and failed_count in redis
170
+ * Skipped tests are never saved in redis by design, unfortunately
171
+
172
+ You might have a look at list-tests-from-redis.js for an example on how to
173
+ query redis and list all tests.
161
174
 
162
175
  ## Examples
163
176
 
@@ -243,9 +256,9 @@ or have been skipped will return 0.
243
256
  If you use jenkins, bamboo or any other build system, make sure
244
257
  one redis is installed somewhere and all runners can access to it.
245
258
 
246
- You can create as many processes processes or launch as docker or kubernetes
247
- instances as you wish, but for each of the runners that you create, make sure
248
- they have visibility to the redis.
259
+ Create as many processes, nodes, dockers, kubernetes pods as you wish,
260
+ but for each of the runners that you create, make sure each of them can connect
261
+ to the redis instance (e.g are in the same network).
249
262
 
250
263
  You can use the project name and build ID or job id as the execution ID for
251
264
  mocha-distributed. Use something unique among the builds of all your projects.
@@ -7,6 +7,9 @@ services:
7
7
  ports:
8
8
  - 6379:6379
9
9
 
10
+ networks:
11
+ - mordor_gh_network
12
+
10
13
  redis-commander:
11
14
  image: rediscommander/redis-commander:latest
12
15
  environment:
@@ -16,3 +19,9 @@ services:
16
19
  depends_on:
17
20
  - redis
18
21
 
22
+ networks:
23
+ - mordor_gh_network
24
+
25
+ networks:
26
+ mordor_gh_network:
27
+ external: true
package/index.js CHANGED
@@ -1,3 +1,8 @@
1
+ // -----------------------------------------------------------------------------
2
+ // Copyright (c) 2018 Pau Sanchez
3
+ //
4
+ // MIT Licensed
5
+ // -----------------------------------------------------------------------------
1
6
  const redis = require("redis");
2
7
  const crypto = require("crypto");
3
8
 
@@ -129,6 +134,7 @@ exports.mochaHooks = {
129
134
  },
130
135
  afterEach(done) {
131
136
  const SKIPPED = "pending";
137
+ const FAILED = "failed";
132
138
 
133
139
  // Save all data in redis in a way it can be retrieved and aggregated
134
140
  // easily for all test by an external reporter
@@ -139,17 +145,24 @@ exports.mochaHooks = {
139
145
  title: this.currentTest.title,
140
146
  timedOut: this.currentTest.timedOut,
141
147
  duration: this.currentTest.duration,
148
+ startTime: Date.now() - (this.currentTest.duration || 0),
149
+ endTime: Date.now(),
142
150
  file: this.currentTest.file,
143
151
  state: this.currentTest.state,
152
+ failed: this.currentTest.state === FAILED,
144
153
  speed: this.currentTest.speed,
145
- err: this.currentTest.err | null,
154
+ err: this.currentTest.err || null,
146
155
  };
147
156
 
148
- // save as single line on purpose
157
+ // save results as single line on purpose
149
158
  const key = `${g_testExecutionId}:test_result`;
150
159
  g_redis.rPush(key, JSON.stringify(testResult));
151
160
  g_redis.expire(key, g_expirationTime);
152
- g_redis.incr(`${g_testExecutionId}:${this.currentTest.state}_count`);
161
+
162
+ // increment passed_count/failed_count & set expiry time
163
+ const countKey = `${g_testExecutionId}:${this.currentTest.state}_count`
164
+ g_redis.incr(countKey);
165
+ g_redis.expire(countKey, g_expirationTime);
153
166
  }
154
167
 
155
168
  done();
@@ -0,0 +1,85 @@
1
+ // -----------------------------------------------------------------------------
2
+ // Copyright (c) 2018 Pau Sanchez
3
+ //
4
+ // MIT Licensed
5
+ // -----------------------------------------------------------------------------
6
+
7
+ const redis = require("redis");
8
+
9
+ async function getTestResults(redisHost = 'localhost', redisPort = 6379) {
10
+ const allResults = []
11
+ try {
12
+ const redisClient = redis.createClient({
13
+ url: `redis://${redisHost}:${redisPort}/`
14
+ });
15
+
16
+ await redisClient.connect()
17
+
18
+ // get all potential test results keys
19
+ const keyResults = await redisClient.keys('*:test_result')
20
+
21
+ // we can get all in parallel
22
+ const parallelResults = []
23
+ for(const key of keyResults) {
24
+ const rawResultList = await redisClient.lRange(key, 0, -1)
25
+
26
+ let passed = 0
27
+ let failed = 0
28
+ let aggregatedDurationMs = 0
29
+ let firstStartTime = null
30
+ let lastEndTime = null
31
+ const jsonResultList = []
32
+ for (const rawResult of rawResultList) {
33
+ const jsonResult = JSON.parse(rawResult)
34
+ jsonResultList.push(jsonResult)
35
+
36
+ // compute some extra stuff
37
+ if (firstStartTime === null || jsonResult.startTime < firstStartTime) {
38
+ firstStartTime = jsonResult.startTime
39
+ }
40
+
41
+ if (lastEndTime === null || jsonResult.endTime > lastEndTime) {
42
+ lastEndTime = jsonResult.endTime
43
+ }
44
+
45
+ passed += (jsonResult.state === "passed")
46
+ failed += (jsonResult.state === "failed")
47
+
48
+ aggregatedDurationMs += (jsonResult.duration || 0)
49
+ }
50
+
51
+ // sort all jsonResultList by the full test route, because they will
52
+ // be visualized better
53
+ jsonResultList.sort((a, b) => (a.id.join('/') > b.id.join('/')) ? 1 : -1)
54
+
55
+ allResults.push({
56
+ key: key,
57
+ start_time : firstStartTime || 0,
58
+ end_time : lastEndTime || 0,
59
+ aggregated_duration: aggregatedDurationMs,
60
+ real_duration: (firstStartTime && lastEndTime) ? lastEndTime - firstStartTime : aggregatedDurationMs,
61
+ tests_passed : passed,
62
+ tests_failed : failed,
63
+ test_results : jsonResultList
64
+ })
65
+ }
66
+
67
+ // sort results by startTime, most recent first
68
+ allResults.sort((a, b) => (a.start_time < b.start_time) ? 1 : -1)
69
+
70
+ await redisClient.quit()
71
+ return allResults
72
+ }
73
+ catch(e) {
74
+ console.error ("Test Error: ", e)
75
+ return false
76
+ }
77
+ }
78
+
79
+
80
+ // -----------------------------------------------------------------------------
81
+ // Print results as JSON output
82
+ // -----------------------------------------------------------------------------
83
+ getTestResults().then( (results) => {
84
+ console.log (JSON.stringify(results, null, 2))
85
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocha-distributed",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Run multiple mocha suites and tests in parallel, from different processes or different machines",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -27,10 +27,10 @@
27
27
  "author": "Pau Sanchez",
28
28
  "license": "MIT",
29
29
  "dependencies": {
30
- "redis": "^4.0.1"
30
+ "redis": "^4.0.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "chai": "^4.2.0",
34
- "mocha": "^9.1.3"
34
+ "mocha": "^9.1.4"
35
35
  }
36
36
  }