-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: randomization support [WIP REFERENCE - DO NOT MERGE] #2301
Conversation
cc @mochajs/mocha |
cc @TimothyGu |
@@ -12,6 +12,8 @@ var escapeRe = require('escape-string-regexp'); | |||
var path = require('path'); | |||
var reporters = require('./reporters'); | |||
var utils = require('./utils'); | |||
var Random = require('random-js'); | |||
var MAX_SAFE_INTEGER = 0x1fffffffffffff; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this number coming from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather get the number from the JS API or, if not available, an npm module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From https://www.npmjs.com/package/random-js#distributions
Random.integer(min, max)(engine)
: Produce an integer within the inclusive range [min
,max
].min
can be at its minimum -9007199254740992 (-2 ** 53).max
can be at its maximum 9007199254740992 (2 ** 53).
Number.MAX_SAFE_INTEGER
is the same value.
EDIT: Number.MAX_SAFE_INTEGER
is only available in ES2015 and later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sorry. 0x1fffffffffffff
is the value of Number.MAX_SAFE_INTEGER
if Number.MAX_SAFE_INTEGER
is implemented. But we're not guaranteed that, of course, and I didn't want to pull in some polyfill. I'll add a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dasilvacontin Would prefer not to npm install --save max-safe-integer
(don't know if that exists; probably does) if I can help it.
Thanks for putting time into this one peeps! |
@ScottFreeCode @TimothyGu Thanks for looking this over. I'll implement the suggested changes |
I don't think my questions in the description were answered though. If I'm deciding, I'll go with |
I'm not familiar with the current situation of browser testing. How do reporters interact with browsers? Can I use, say, the XUnit reporter with the browser? If yes, will the XUnit output be made to the browser console? |
so this is how it works on the CLI: # generate the seed first
$ mocha --generate-seed
0x10FFFA5D98AE6F # run tests with the seed
$ mocha --random 0x10FFFA5D98AE6F test/acceptance/random.js --reporter spec
random option
seed
✓ should be a valid seed
✓ should return a finite number
✓ should return a hex string
when Mocha is instantiated with "random" option
and that option is "false"
✓ should not populate the "randomConfig" option
and that option is undefined
✓ should not populate the "randomConfig" option
and that option is not an integer or convertable string
✓ should throw
and that option is a valid seed
randomConfig
✓ should define a function to shuffle tests in the "shuffleTests" prop
✓ should define a "seed" prop
✓ should be defined
✓ should define a hexadecimal representation in the "hex" prop
10 passing (24ms) For comparison, without randomization: $ mocha test/acceptance/random.js --reporter spec
random option
seed
✓ should return a hex string
✓ should be a valid seed
✓ should return a finite number
when Mocha is instantiated with "random" option
and that option is "false"
✓ should not populate the "randomConfig" option
and that option is undefined
✓ should not populate the "randomConfig" option
and that option is not an integer or convertable string
✓ should throw
and that option is a valid seed
randomConfig
✓ should be defined
✓ should define a "seed" prop
✓ should define a hexadecimal representation in the "hex" prop
✓ should define a function to shuffle tests in the "shuffleTests" prop
10 passing (24ms) |
@TimothyGu Generally, if you're in a browser, your only available reporter is the HTML reporter. If you're in a headless browser, then the HTML reporter is going to just dump HTML into your terminal, and you'll want one of the console-based reporters, like I don't use Mocha in a browser context without Karma to hold my hand, so I'm not the best source of information on this topic. @mantoni is much more qualified to elaborate on which reporters are supported, if he cares to. |
What's left to do:
|
note to self: Karma setup would look something like: var seed = require('mocha').seed();
console.log('Mocha seed: ' + seed);
config.set({
frameworks: ['mocha'],
client: {
random: seed
}
}); |
}; | ||
|
||
/** | ||
* Returns `true` if `value` is a "safe" 32-bit unsigned int. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and in various other places, it's a bit confusing to see uint32_t or integers in the range of [0, 2³² – 1] being called "safe," while what the function actually takes is integers in the range of [1, 2⁵³ – 1]. IMO, what we should allow is [0, 2⁵³ – 1] which can be described as "safe" unsigned 53-bit integer and matches with ECMAScript semantics. (In addition, we can optionally allow negative values as well.)
SauceLabs is taking a big ol' dump trying to run our tests in IE8. Considering the |
@TimothyGu @boneskull Pretty much all the reporters work in PhantomJS, too. The trick is to redirect console output and to provide a shim for |
2975dc5
to
f28da97
Compare
f28da97
to
75fe69f
Compare
// (traditional)-> space/name parameters body (lambda)-> parameters body multi-statement/single keep body content | ||
// (traditional)-> space/name parameters body (lambda)-> | ||
// parameters body multi-statement/single keep body | ||
// content | ||
.replace(/^function(?:\s*|\s+[^(]*)\([^)]*\)\s*\{((?:.|\n)*?)\s*\}$|^\([^)]*\)\s*=>\s*(?:\{((?:.|\n)*?)\s*\}|((?:.|\n)*))$/, '$1$2$3'); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment wrapping here basically breaks this documentation of the regex. Do we need to stop the linter from paying attention to that comment? Or should we break up the regex into parts (as strings) and compose them using new RegExp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't notice this. I'll ensure it's left as-is
woohoo finally |
So basically needs more tests. But I don't necessarily need to be the person to write them. |
Is there an updated description of what needs to happen to push this over the line? We would like to randomize our mocha builds to bring the flaky tests to the surface. |
not so much. new features are frozen until we get traction on immediate coverage needs. though I haven't had any time to pay attention to where we're at there |
4547268
to
7613521
Compare
@boneskull this sounds good. Worth pursuing now coverage in better place? Or do you think given where codebase is now there's a better alternative approach here? |
Edit: per #902 (comment), re-opening and marking as a draft. |
|
var intVal; | ||
if (/^0[xX]/.test(value)) { | ||
intVal = parseInt(value, 16); | ||
} else if (/^0[^.]/.test(value)) { | ||
intVal = parseInt(value, 8); | ||
} else { | ||
intVal = parseInt(value, 10); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like this could be simplified a bit.
var intVal; | |
if (/^0[xX]/.test(value)) { | |
intVal = parseInt(value, 16); | |
} else if (/^0[^.]/.test(value)) { | |
intVal = parseInt(value, 8); | |
} else { | |
intVal = parseInt(value, 10); | |
} | |
var base = 10; | |
var intVal; | |
if (/^0[xX]/.test(value)) { | |
base = 16; | |
} else if (/^0[^.]/.test(value)) { | |
base = 8; | |
} | |
intVal = parseInt(value, base); |
return !isNaN(intVal) && parseFloat(intVal) === intVal | ||
&& exports.isSafeUnsignedInteger(intVal) | ||
? intVal | ||
: NaN; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isSafeUnsignedInteger
already checks for an integer so there's no need to double check here. Also if the value is NaN
, you'll still hit the right checks without the additional NaN
check.
return !isNaN(intVal) && parseFloat(intVal) === intVal | |
&& exports.isSafeUnsignedInteger(intVal) | |
? intVal | |
: NaN; | |
return exports.isSafeUnsignedInteger(intVal) ? intVal : NaN; |
* @returns {string} Hexadecimal representation thereof | ||
*/ | ||
exports.toHex = function toHex(int) { | ||
return '0x' + int.toString(16).toUpperCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't have any validation compared to other functions.toHex('foo')
will happily return 0xFOO
. Is that expected behavior?
@fearphage thanks for the reviews, but this PR is just here as a reference. It's got a whole bunch of merge conflicts. I edited the title & OP to make that more clear. If you're interested in the work (great! 🙌) the right next step would be to send a separate PR. Edit: Closing to keep our review queue small. |
Edit (January 2024, @JoshuaKGoldberg): This PR is just here as a reference to support #902. If you want to see this feature land, send a PR yourself. See #902 (comment). Thanks! ✨
--random
CLI flag orrandom
option in browserQUESTIONS:
Automatic Seed Creation
How should we handle automatic seed creation?
Issues:
Suggestions:
.mocha-seed.txt
file or something. This file would not be read from; only written to.Mocha.seed()
in the browser, or--generate-seed
on the CLI.Update, Nov 20 2016:
"Specification"
mocha --generate-seed
. A random seed will be printed to the console.--random <seed>
will enable randomization.mocha.seed()
.mocha.options({random: mocha.seed()})
before callingmocha.run()
.Number.MAX_SAFE_INTEGER
, which is typically9007199254740991
.parseInt()
.TODO
--generate-seed
--random <seed>
MOCHA_SEED
environment variable. This would ease usage in CI envs.