Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test with Math.random in JavaScript?

I have a function that will select a random value between a min and a max value. So when I have a test where I test that the value fall between the min and max value. But as there where some failures in my app the test passed some times and some times fails due to the randomness.

Would it be a good idea to override/mock Math.random() to return 0 and 1 and test that my value is same as max or min value? Or are there better ways to test randomness in JavaScript?

Here is the function that will be used to create the random number:

function constrain(min, max){
    return Math.round(Math.random() * (max - min) + min)
}
like image 420
Andreas Köberle Avatar asked May 09 '12 11:05

Andreas Köberle


People also ask

How do you use Math random in JavaScript?

Generating Javascript Random Numbers Javascript creates pseudo-random numbers with the function Math. random() . This function takes no parameters and creates a random decimal number between 0 and 1. The returned value may be 0, but it will never be 1.

How random is JS Math random?

random() is a pseudo-random number as no computer can generate a truly random number, that exhibits randomness over all scales and over all sizes of data sets. However, the pseudo-random number generated by Math. random() is usually sufficient for the needs of nearly any program you may write.

How do you get the Math random between two numbers in JavaScript?

Example: Integer Value Between Two Numbers In JavaScript, you can generate a random number with the Math. random() function. The above program will show an integer output between min (inclusive) to max (inclusive). First, the minimum and maximum values are taken as input from the user.

Is there a random function in JavaScript?

In JavaScript, random() is a function that is used to return a pseudo-random number or random number within a range. Because the random() function is a static function of the Math object, it must be invoked through the placeholder object called Math.


3 Answers

SinonJS is a JavaScript mocking framework which integrates with all of the major JavaScript Unit Testing frameworks. The adapters will take care of 'reverting' any stubs / mocks that you create during your tests.

// Stub out Math.random so it always returns '4' (chosen by fair dice roll)
sinon.stub(Math, 'random').returns(4);

// Double check that it worked.
equal(Math.random(), 4, "http://xkcd.com/221/");
like image 187
JonnyReeves Avatar answered Sep 28 '22 16:09

JonnyReeves


Generally your tests should pass for all possible values of your non-deterministic code. Maybe have a loop in your test where you do the test say 100 times. That will catch more failures without changing the application code. What you suggested is also an option.

like image 40
alexg Avatar answered Sep 28 '22 17:09

alexg


Preferrably, you should have no random element in your test at all. You should feed your method known values, so that you can determine if the result is exactly what you excpect.

If you have random values, you would have to test the method a lot of times, and you are still not sure that you get the exact result that you want, only that you get something in the right range.

If you for example use the current date in your code (new Date()), then you should provide your method with known dates when testing, otherwise your test will only show that the method works right now. Tomorrow it might fail.


Edit:

However, I can tell you right away that your method doesn't work well. You should use the floor method instead of round, otherwise the lowest and highest values will occur half as often as the other values:

function constrain(min, max){
  return Math.floor(Math.random() * (max - min + 1) + min)
}
like image 40
Guffa Avatar answered Sep 28 '22 16:09

Guffa