Skip to content
This repository was archived by the owner on Jun 15, 2019. It is now read-only.

Commit 206bff8

Browse files
committed
perf(test): The performance of "Try to find an illegal short line" was highly improved (> 2k times!)
1. Due to performance issues, we must never expose `expect` method outside of an `if` block (that checks the test condition) in a loop. So I changed "Try to find an illegal short line" unit test. This improved the performance ~50 times! 2. `jest-expect-message` was removed and replaced it with two custom matchers that supports custom message: `toBeGreaterThan(...)` and `toBeLessThanOrEqual(...)`. This improved the performance ~45 times! See: mattphillips/jest-expect-message#8 (comment)
1 parent e12bcb7 commit 206bff8

File tree

5 files changed

+52
-41
lines changed

5 files changed

+52
-41
lines changed

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
node_js: "11"
1111

1212
if: env(UNIT_TEST_11) && type == push && tag !~ ^v\d+\.\d+\.\d+ &&
13-
commit_message =~ /^(test|feat|fix|refactor|pref|revert)\(/
13+
commit_message =~ /^(test|feat|fix|refactor|perf|revert)\(/
1414

1515
script: npm run test:unit:prod
1616
#--------------------------------------------------------------------------------------#
@@ -19,7 +19,7 @@ jobs:
1919
node_js: "10"
2020

2121
if: env(UNIT_TEST_10) && type == push && tag !~ ^v\d+\.\d+\.\d+ &&
22-
commit_message =~ /^(test|feat|fix|refactor|pref|revert)\(/
22+
commit_message =~ /^(test|feat|fix|refactor|perf|revert)\(/
2323

2424
# For debug purposes:
2525
before_script: echo -e "BUILD_DIR = $TRAVIS_BUILD_DIR\nBUILD_ID = $TRAVIS_BUILD_ID\nBUILD_NUMBER = $TRAVIS_BUILD_NUMBER\nBUILD_WEB_URL = $TRAVIS_BUILD_WEB_URL\nCOMMIT = $TRAVIS_COMMIT\nCOMMIT_MESSAGE = $TRAVIS_COMMIT_MESSAGE\nCOMMIT_RANGE = $TRAVIS_COMMIT_RANGE\nDEBUG_MODE = $TRAVIS_DEBUG_MODE\nEVENT_TYPE = $TRAVIS_EVENT_TYPE\nJOB_ID = $TRAVIS_JOB_ID\nJOB_NAME = $TRAVIS_JOB_NAME\nJOB_NUMBER = $TRAVIS_JOB_NUMBER\nJOB_WEB_URL = $TRAVIS_JOB_WEB_URL\nOS_NAME = $TRAVIS_OS_NAME\nOSX_IMAGE = $TRAVIS_OSX_IMAGE\nPULL_REQUEST = $TRAVIS_PULL_REQUEST\nPULL_REQUEST_BRANCH= $TRAVIS_PULL_REQUEST_BRANCH\nPULL_REQUEST_SHA = $TRAVIS_PULL_REQUEST_SHA\nPULL_REQUEST_SLUG = $TRAVIS_PULL_REQUEST_SLUG\nSECURE_ENV_VARS = $TRAVIS_SECURE_ENV_VARS\nSUDO = $TRAVIS_SUDO\nTEST_RESULT = $TRAVIS_TEST_RESULT\nTAG = $TRAVIS_TAG\nBUILD_STAGE_NAME = $TRAVIS_BUILD_STAGE_NAME"
@@ -40,7 +40,7 @@ jobs:
4040
node_js: lts/*
4141

4242
if: env(BUILD_AND_RELEASE) && type == push && tag !~ ^v\d+\.\d+\.\d+ && branch == master &&
43-
commit_message =~ /^((feat|fix|refactor|pref|build|revert)\(|test\((?i)[\s\S]*?\b(E2E|END-TO-END|END2END)\b)/ # https://regex101.com/r/XWKT5J/1/
43+
commit_message =~ /^((feat|fix|refactor|perf|build|revert)\(|test\((?i)[\s\S]*?\b(E2E|END-TO-END|END2END)\b)/ # https://regex101.com/r/XWKT5J/1/
4444

4545
script: >-
4646
if [[ $E2E_TEST == true || $SEMANTIC_RELEASE == true ]]; then

jest/unit/config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,4 @@ module.exports = {
3232
'src/*.{js,ts}'
3333
],
3434
coverageDirectory: 'coverage/unit',
35-
setupFilesAfterEnv: ['jest-expect-message'],
3635
}

jest/unit/text-wrap.ts

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,14 @@ describe('Case-specific tests:', () => {
6969
it("Check input's hash", () => expect(sha256(originalInput)).toBe('928c256346d0b16e69cd4c4ddd56e5608335f9ad16d1a25c26a9d8ff4b3e4edf'))
7070
})
7171

72+
const testsNum = allOptions.length
73+
7274
afterAll(() => {
73-
for (let i = 0; i < allOptions.length; ++i)
75+
for (let i = 0; i < testsNum; ++i)
7476
fs.writeFile(outputPath(i), outputs[i], err => {if (err) console.error(err)})
7577
})
7678

77-
for (let testNum = 0; testNum < allOptions.length; ++testNum) {
79+
for (let testNum = 0; testNum < testsNum; ++testNum) {
7880
const options = allOptions[testNum]
7981
const textWrap = new TextWrap(options)
8082
const maxLineLength = textWrap.wrapOn
@@ -138,22 +140,24 @@ for (let testNum = 0; testNum < allOptions.length; ++testNum) {
138140

139141
const upBound = regExp.test(input) ? regExp.lastIndex : input.length
140142
const slice = indentsN + input.slice(a, upBound) // is not strict in first cycle of the loop that hasn't indentsN
141-
const distance = textWrap.getVisualLength(slice)
142143

143-
expect(distance, `[${slice}]\n${regExp}`).toBeGreaterThan(maxLineLength)
144+
// WARNING: Due to performance issues, never expose `expect` method outside of an `if` block (that
145+
// checks the test condition) in a loop.
146+
if (textWrap.getVisualLength(slice) <= maxLineLength)
147+
expect(textWrap.getVisualLength(slice)).toBeGreaterThan(maxLineLength, `[${slice}]\n${regExp}`)
144148

145149
a = b
146150
}
147151
})
148152

149-
it("Try to find an illegal long line", // A line that should to be wrapped, but hasn't
153+
it('Try to find an illegal long line', // A line that should to be wrapped, but hasn't
150154
() => {
151155
// https://regex101.com/r/4DaiXE/1/
152-
const regexp = new RegExp(`^([^\\n]*)(?:(?!\\n)${bc.source})[^\\n]*(?!${ec.source}).`,
156+
const regExp = new RegExp(`^([^\\n]*)(?:(?!\\n)${bc.source})[^\\n]*(?!${ec.source}).`,
153157
bc.flags.appendIfNot('g').appendIfNot('m'))
154158

155159
while (true) {
156-
const match = regexp.exec(output)
160+
const match = regExp.exec(output)
157161
if (match === null) break
158162

159163
const vLen = textWrap.getVisualLength(match[0])
@@ -163,13 +167,13 @@ for (let testNum = 0; testNum < allOptions.length; ++testNum) {
163167
// Check to sure the line is breakable:
164168
textWrap.getVisualLength(match[1]) > textWrap.getVisualLength(indentsN)
165169
)
166-
expect(vLen, `[${match[0]}]\n${regexp}`).toBeLessThanOrEqual(maxLineLength)
170+
expect(vLen).toBeLessThanOrEqual(maxLineLength, `[${match[0]}]\n${regExp}`)
167171
}
168172
})
169173

170174
// it("Try to find an illegal long line using RegExp", // Same as above but using RegExp. This one is not strict and accurate because can only calculate length, but not vLen (visual-length)
171175
// () => {
172-
// expect(output).not.toMatch1(
176+
// expect(output).not.toMatch(
173177
// // https://regex101.com/r/OfQoDb/1
174178
// new RegExp(
175179
// `^(?=.{${indentsN.length},}[^\\w\\xA0\\n](?![^\\S\\n]|$)).{${maxLineLength},}\\S`,
@@ -184,24 +188,47 @@ for (let testNum = 0; testNum < allOptions.length; ++testNum) {
184188
}
185189
//*************************************************************************************/
186190

191+
// noinspection JSUnusedGlobalSymbols
187192
expect.extend({
188-
toMatch1(text: string, regExp: RegExp, msg: string | (() => string)) {
189-
const match1 = regExp.exec(text)
190-
const passed = match1 !== null
191-
192-
const message = (toClause: () => string) =>
193-
() => `Expected the text to ${toClause()}\n${typeof msg === 'string' ? msg : msg()}`
194-
195-
return passed ?
193+
toBeGreaterThan(received: number, floor: number, msg: string | (() => string)) {
194+
return received > floor ?
195+
{
196+
message: () => `Expected: ${received}${floor}\n${typeof msg === 'string' ? msg : msg()}`,
197+
pass: true,
198+
} :
199+
{
200+
message: () => `Expected: ${received} > ${floor}\n${typeof msg === 'string' ? msg : msg()}`,
201+
pass: false,
202+
}
203+
},
204+
toBeLessThanOrEqual(received: number, roof: number, msg: string | (() => string)) {
205+
return received <= roof ?
196206
{
197-
message: message(() => `not match ${regExp}\nFirst match:\n[${match1}]`),
207+
message: () => `Expected: ${received} > ${roof}\n${typeof msg === 'string' ? msg : msg()}`,
198208
pass: true,
199209
} :
200210
{
201-
message: message(() => `match ${regExp}`),
211+
message: () => `Expected: ${received}${roof}\n${typeof msg === 'string' ? msg : msg()}`,
202212
pass: false,
203213
}
204214
},
215+
// toMatch(text: string, regExp: RegExp, msg: string | (() => string)) {
216+
// const match1 = regExp.exec(text)
217+
// const passed = match1 !== null
218+
//
219+
// const message = (toClause: () => string) =>
220+
// () => `Expected the text to ${toClause()}\n${typeof msg === 'string' ? msg : msg()}`
221+
//
222+
// return passed ?
223+
// {
224+
// message: message(() => `not match ${regExp}\nFirst match:\n[${match1}]`),
225+
// pass: true,
226+
// } :
227+
// {
228+
// message: message(() => `match ${regExp}`),
229+
// pass: false,
230+
// }
231+
// },
205232
})
206233

207234
String.prototype.appendIfNot = function (part: string): string {
@@ -212,7 +239,9 @@ declare global {
212239
namespace jest {
213240
// noinspection JSUnusedGlobalSymbols
214241
interface Matchers<R> {
215-
toMatch1(regExp: RegExp, msg: string): R
242+
//toMatch(regExp: RegExp, msg: string | (() => string)): R
243+
toBeGreaterThan(floor: number, msg: string | (() => string)): R
244+
toBeLessThanOrEqual(roof: number, msg: string | (() => string)): R
216245
}
217246
}
218247

package-lock.json

Lines changed: 0 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,13 @@
5050
"@babel/preset-flow": "^7.0.0",
5151
"@types/debug": "^4.1.4",
5252
"@types/jest": "^24.0.12",
53-
"@types/jest-expect-message": "^1.0.0",
5453
"@types/puppeteer": "^1.12.4",
5554
"babel-jest": "^24.8.0",
5655
"cz-conventional-changelog": "^2.1.0",
5756
"fs-extra": "^8.0.1",
5857
"jest": "^24.7.1",
5958
"jest-config": "^24.7.1",
6059
"jest-environment-node": "^24.8.0",
61-
"jest-expect-message": "^1.0.2",
6260
"js-sha256": "^0.9.0",
6361
"lodash.camelcase": "^4.3.0",
6462
"mkdirp": "^0.5.1",

0 commit comments

Comments
 (0)